mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-23 00:13:35 +01:00
5e3c67a5cf
classes are now uppercase and in their own files. lowercase classes are deprecated. Interfaces are now actual interfaces that should be implemented instead of creating and returning an ai Object every time
1467 lines
63 KiB
JavaScript
1467 lines
63 KiB
JavaScript
/**
|
|
* eGroupware Framework ui object
|
|
* @package framework
|
|
* @author Hadi Nategh <hn@stylite.de>
|
|
* @author Andreas Stoeckel <as@stylite.de>
|
|
* @copyright Stylite AG 2014
|
|
* @description Framework ui object, is implementation of UI class
|
|
*/
|
|
|
|
/*egw:uses
|
|
vendor.bower-asset.jquery.dist.jquery;
|
|
/api/js/jquery/mousewheel/mousewheel.js;
|
|
egw_inheritance.js;
|
|
*/
|
|
|
|
import "../../../vendor/bower-asset/jquery/dist/jquery.min.js";
|
|
import "../jquery/jquery.noconflict.js";
|
|
import "../jquery/mousewheel/mousewheel.js";
|
|
import '../jsapi/egw_inheritance.js';
|
|
import {EGW_KEY_ENTER, EGW_KEY_SPACE} from '../egw_action/egw_action_constants';
|
|
import interact from "@interactjs/interactjs";
|
|
|
|
/**
|
|
* ui siemenu entry class
|
|
* Basic sidebar menu implementation
|
|
*
|
|
* @type @exp;Class@call;extend
|
|
*/
|
|
window.fw_ui_sidemenu_entry = (function(){ "use strict"; return Class.extend(
|
|
{
|
|
/**
|
|
* Framework ui sidemenu entry class constructor
|
|
*
|
|
* @param {object} _parent specifies the parent egw_fw_ui_sidemenu
|
|
* @param {object} _baseDiv specifies "div" element the entries should be appended to.
|
|
* @param {object} _elemDiv
|
|
* @param {string} _name specifies the title of the entry in the side menu
|
|
* @param {string} _icon specifies the icon which should be viewd besides the title in the side menu
|
|
* @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 {string} _app application name
|
|
*/
|
|
init: function (_parent, _baseDiv, _elemDiv, _name, _icon, _callback, _tag, _app)
|
|
{
|
|
this.baseDiv = _baseDiv;
|
|
this.elemDiv = _elemDiv;
|
|
this.entryName = _name;
|
|
this.icon = _icon;
|
|
this.tag = _tag;
|
|
this.parent = _parent;
|
|
this.atTop = false;
|
|
this.isDraged = false;
|
|
|
|
//Add a new div for the new entry to the base div
|
|
this.headerDiv = document.createElement("div");
|
|
this.headerDiv.id = _app+'_sidebox_header';
|
|
jQuery(this.headerDiv).addClass("egw_fw_ui_sidemenu_entry_header");
|
|
|
|
//Create the icon and set its image
|
|
var iconDiv = egw.image_element(this.icon, _name);
|
|
jQuery(iconDiv).addClass("egw_fw_ui_sidemenu_entry_icon");
|
|
|
|
//Create the AJAX loader image (currently NOT used)
|
|
this.ajaxloader = document.createElement("div");
|
|
jQuery(this.ajaxloader).addClass("egw_fw_ui_ajaxloader");
|
|
jQuery(this.ajaxloader).hide();
|
|
|
|
//Create the entry name header
|
|
var entryH1 = document.createElement("h1");
|
|
jQuery(entryH1).text(this.entryName);
|
|
|
|
//Append icon, name, and ajax loader
|
|
jQuery(this.headerDiv).append(iconDiv);
|
|
jQuery(this.headerDiv).append(entryH1);
|
|
jQuery(this.headerDiv).append(this.ajaxloader);
|
|
this.headerDiv._parent = this;
|
|
this.headerDiv._callbackObject = new egw_fw_class_callback(this, _callback);
|
|
jQuery(this.headerDiv).click(function(){
|
|
if (!this._parent.isDraged)
|
|
{
|
|
this._callbackObject.call(this);
|
|
}
|
|
this._parent.isDraged = false;
|
|
return true;
|
|
});
|
|
|
|
//close button on active header
|
|
this.closeButton = document.createElement('span');
|
|
this.closeButton.classList.add('close');
|
|
|
|
|
|
//Create the content div
|
|
this.contentDiv = document.createElement("div");
|
|
this.contentDiv.id = _app+'_sidebox_content';
|
|
jQuery(this.contentDiv).addClass("egw_fw_ui_sidemenu_entry_content")
|
|
.attr("role","menu")
|
|
.attr("aria-label",this.entryName);
|
|
jQuery(this.contentDiv).hide();
|
|
|
|
//Add in invisible marker to store the original position of this element in the DOM tree
|
|
this.marker = document.createElement("div");
|
|
this.marker._parent = this;
|
|
this.marker.className = 'egw_fw_ui_sidemenu_marker';
|
|
var entryH1_ = document.createElement("h1");
|
|
jQuery(entryH1_).text(this.entryName);
|
|
jQuery(this.marker).append(entryH1_);
|
|
jQuery(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;
|
|
jQuery(this.containerDiv).append(this.marker);
|
|
jQuery(this.containerDiv).append(this.headerDiv);
|
|
jQuery(this.containerDiv).append(this.contentDiv);
|
|
|
|
//Append header and content div to the base div
|
|
jQuery(this.elemDiv).append(this.containerDiv);
|
|
},
|
|
|
|
/**
|
|
* setContent replaces the content of the sidemenu entry with the content given by _content.
|
|
* @param {string} _content HTML/Text which should be displayed.
|
|
*/
|
|
setContent: function(_content)
|
|
{
|
|
//Set the content of the contentDiv
|
|
jQuery(this.contentDiv).empty();
|
|
jQuery(this.contentDiv).append(_content);
|
|
},
|
|
|
|
/**
|
|
* open openes this sidemenu_entry and displays the content.
|
|
*/
|
|
open: function()
|
|
{
|
|
jQuery(this.baseDiv).prepend(this.contentDiv);
|
|
jQuery(this.baseDiv).prepend(this.headerDiv);
|
|
|
|
this.atTop = true;
|
|
|
|
jQuery(this.headerDiv).addClass("egw_fw_ui_sidemenu_entry_header_active");
|
|
jQuery(this.contentDiv).show();
|
|
},
|
|
|
|
/**
|
|
* close closes this sidemenu_entry and hides the content.
|
|
*/
|
|
close: function()
|
|
{
|
|
/* Move the content and header div behind the marker again */
|
|
if (this.atTop)
|
|
{
|
|
jQuery(this.marker).after(this.contentDiv);
|
|
jQuery(this.marker).after(this.headerDiv);
|
|
this.atTop = false;
|
|
}
|
|
|
|
jQuery(this.headerDiv).removeClass("egw_fw_ui_sidemenu_entry_header_active");
|
|
jQuery(this.contentDiv).hide();
|
|
},
|
|
|
|
setCloseButton: function(_callback)
|
|
{
|
|
if (typeof _callback == "function" && this.closeButton)
|
|
{
|
|
this.headerDiv.append(this.closeButton);
|
|
this.closeButton.addEventListener('click', _callback);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* egw_fw_ui_sidemenu_entry_header_active
|
|
* showAjaxLoader shows the AjaxLoader animation which should be displayed when
|
|
* the content of the sidemenu entry is just being loaded.
|
|
*/
|
|
showAjaxLoader: function()
|
|
{
|
|
jQuery(this.ajaxloader).show();
|
|
},
|
|
|
|
/**
|
|
* showAjaxLoader hides the AjaxLoader animation
|
|
*/
|
|
hideAjaxLoader: function()
|
|
{
|
|
jQuery(this.ajaxloader).hide();
|
|
},
|
|
|
|
/**
|
|
* Removes this entry.
|
|
*/
|
|
remove: function()
|
|
{
|
|
jQuery(this.headerDiv).remove();
|
|
jQuery(this.contentDiv).remove();
|
|
}
|
|
});}).call(window);
|
|
|
|
/**
|
|
*
|
|
* @type @exp;Class@call;extend
|
|
*/
|
|
window.fw_ui_sidemenu = (function(){ "use strict"; return Class.extend(
|
|
{
|
|
/**
|
|
* The constructor of the egw_fw_ui_sidemenu.
|
|
*
|
|
* @param {object} _baseDiv specifies the "div" in which all entries added by the addEntry function should be displayed.
|
|
*/
|
|
init:function(_baseDiv)
|
|
{
|
|
this.baseDiv = _baseDiv;
|
|
this.elemDiv = document.createElement('div');
|
|
jQuery(this.baseDiv).append(this.elemDiv);
|
|
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
|
|
*
|
|
* @param {array} _resultArray
|
|
* @param {array} _children
|
|
*/
|
|
_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);
|
|
}
|
|
},
|
|
|
|
|
|
/**
|
|
* Adds an entry to the sidemenu.
|
|
*
|
|
* @param {string} _name specifies the title of the new sidemenu entry
|
|
* @param {string} _icon specifies the icon displayed aside the title
|
|
* @param {function}(_sender) _callback specifies the function which should be called when a callback is clicked
|
|
* @param {object} _tag extra data
|
|
* @param {string} _app application name
|
|
*/
|
|
addEntry: function(_name, _icon, _callback, _tag, _app)
|
|
{
|
|
//Create a new sidemenu entry and add it to the list
|
|
var entry = new egw_fw_ui_sidemenu_entry(this, this.baseDiv, this.elemDiv, _name, _icon,
|
|
_callback, _tag, _app);
|
|
this.entries[this.entries.length] = entry;
|
|
|
|
return entry;
|
|
},
|
|
|
|
/**
|
|
* Openes the specified entry whilst closing all other entries in the list.
|
|
*
|
|
* @param {object} _entry specifies the entry which should be opened.
|
|
*/
|
|
open: function(_entry)
|
|
{
|
|
//Close all other entries
|
|
for (var i = 0; i < this.entries.length; i++)
|
|
{
|
|
if (this.entries[i] != _entry)
|
|
{
|
|
this.entries[i].close();
|
|
}
|
|
}
|
|
|
|
if (_entry != null)
|
|
{
|
|
_entry.open();
|
|
}
|
|
|
|
this.activeEntry = _entry;
|
|
},
|
|
|
|
|
|
/**
|
|
* Deletes all sidemenu entries.
|
|
*/
|
|
clean: function()
|
|
{
|
|
for (var i = 0; i < this.entries.length; i++)
|
|
{
|
|
this.entries[i].remove();
|
|
}
|
|
|
|
this.entries = new Array();
|
|
}
|
|
});}).call(window);
|
|
|
|
/**
|
|
* Class: egw_fw_ui_tab
|
|
* The egw_fw_ui_tab represents a single tab "sheet" in the ui
|
|
*/
|
|
|
|
|
|
/**
|
|
* The constructor of the egw_fw_ui_tab class.
|
|
*
|
|
* @param {object} _parent specifies the parent egw_fw_ui_tabs class
|
|
* @param {object} _contHeaderDiv specifies the container "div" element, which should contain the headers
|
|
* @param {object} _contDiv specifies the container "div" element, which should contain the contents of the tabs
|
|
* @param {string} _icon specifies the icon which should be viewed besides the title of the tab
|
|
* @param {function}(_sender) _callback specifies the function which should be called when the tab title is clicked. The _sender parameter passed is a reference to this egw_fw_ui_tab element.
|
|
* @param {function}(_sender) _closeCallback specifies the function which should be called when the tab close button is clicked. The _sender parameter passed is a reference to this egw_fw_ui_tab 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 {int} _pos is the position where the tab will be inserted
|
|
* @param {string} application status (e.g. status="5")
|
|
*/
|
|
window.egw_fw_ui_tab = function(_parent, _contHeaderDiv, _contDiv, _icon, _callback,
|
|
_closeCallback, _tag, _pos, _status)
|
|
{
|
|
this.parent = _parent;
|
|
this.contHeaderDiv = _contHeaderDiv;
|
|
this.contDiv = _contDiv;
|
|
this.title = '';
|
|
this.tag = _tag;
|
|
this.closeable = true;
|
|
this.callback = _callback;
|
|
this.closeCallback = _closeCallback;
|
|
this.position = _pos;
|
|
this.status = _status;
|
|
this.notification = 0;
|
|
this.hint = '';
|
|
|
|
//Create the header div and set its "click" function and "hover" event
|
|
this.headerDiv = document.createElement("span");
|
|
this.headerDiv._position = _pos;
|
|
jQuery(this.headerDiv).attr('id', this.tag.appName+'-egw_fw_ui_tab_header').addClass("egw_fw_ui_tab_header");
|
|
|
|
//Create a new callback object and attach it to the header div
|
|
this.headerDiv._callbackObject = new egw_fw_class_callback(this, _callback);
|
|
jQuery(this.headerDiv).click(
|
|
function(){
|
|
this._callbackObject.call(this);
|
|
});
|
|
|
|
//Attach the hover effect to the header div
|
|
jQuery(this.headerDiv).hover(
|
|
function() {
|
|
if (!jQuery(this).hasClass("egw_fw_ui_tab_header_active"))
|
|
jQuery(this).addClass("egw_fw_ui_tab_header_hover");
|
|
},
|
|
function() {
|
|
jQuery(this).removeClass("egw_fw_ui_tab_header_hover");
|
|
}
|
|
);
|
|
|
|
// If dragging something over the tab, activate that app
|
|
var tab = this.headerDiv;
|
|
this.headerDiv.addEventListener('dragenter', (event) =>
|
|
{
|
|
event.stopPropagation();
|
|
if (!this.headerDiv.parentElement.dataset.dragblock)
|
|
{
|
|
this.headerDiv.parentElement.dataset.dragblock = true;
|
|
tab._callbackObject.call(tab);
|
|
}
|
|
tab.parentElement.addEventListener("dragend", dragBlockEnd)
|
|
tab.parentElement.addEventListener("dragleave", dragBlockEnd)
|
|
});
|
|
var dragBlockEnd = (e) =>
|
|
{
|
|
|
|
|
|
tab.parentElement.removeEventListener("dragend", dragBlockEnd);
|
|
tab.parentElement.removeEventListener("dragleave", dragBlockEnd);
|
|
window.clearTimeout(tab.parentElement.dataset.dragblock);
|
|
tab.parentElement.dataset.dragblock = window.setTimeout(() =>
|
|
{
|
|
tab.parentElement.removeAttribute("data-dragblock");
|
|
}, 100);
|
|
}
|
|
|
|
|
|
//Create the close button and append it to the header div
|
|
this.closeButton = document.createElement("span");
|
|
this.closeButton._callbackObject = new egw_fw_class_callback(this, _closeCallback);
|
|
jQuery(this.closeButton).addClass("egw_fw_ui_tab_close_button");
|
|
jQuery(this.closeButton).click(
|
|
function(){
|
|
//Only call the close callback if the tab is set closeable
|
|
if (this._callbackObject.context.closeable)
|
|
{
|
|
this._callbackObject.call(this);
|
|
return false;
|
|
}
|
|
return true;
|
|
});
|
|
|
|
this.notificationDiv = document.createElement("div");
|
|
var self = this;
|
|
jQuery(this.notificationDiv).addClass('notifyTabDiv')
|
|
.hide()
|
|
.click(function(e){
|
|
if (app.notifications.tabToggle(self.tag.appName))
|
|
{
|
|
e.stopImmediatePropagation();
|
|
}
|
|
})
|
|
.appendTo(this.headerDiv);
|
|
jQuery(this.headerDiv).append(this.closeButton);
|
|
|
|
//Create the icon and append it to the header div
|
|
var icon = egw.image_element(_icon);
|
|
jQuery(icon).addClass("egw_fw_ui_tab_icon");
|
|
jQuery(this.headerDiv).append(icon);
|
|
|
|
//Create the title h1 and append it to the header div
|
|
this.headerH1 = document.createElement("h1");
|
|
this.setTitle('');
|
|
jQuery(this.headerDiv).append(this.headerH1);
|
|
|
|
//Add close tab button on sidemenuentry for frameworkTabs
|
|
if (this.tag.isFrameworkTab)
|
|
{
|
|
this.tag.sidemenuEntry.setCloseButton(function(){
|
|
|
|
//Only call the close callback if the tab is set closeable
|
|
if (this._callbackObject.context.closeable)
|
|
{
|
|
this._callbackObject.call(this);
|
|
return false;
|
|
}
|
|
return true;
|
|
|
|
}.bind(this.closeButton));
|
|
}
|
|
|
|
this.contentDiv = document.createElement("div");
|
|
jQuery(this.contentDiv).addClass("egw_fw_ui_tab_content")
|
|
.attr("role","application")
|
|
.hide();
|
|
|
|
//Sort the element in at the given position
|
|
var _this = this;
|
|
var $_children = jQuery(this.contHeaderDiv).children();
|
|
var _cnt = $_children.size();
|
|
|
|
if (_cnt > 0 && _pos > -1)
|
|
{
|
|
$_children.each(function(i) {
|
|
if (_pos <= this._position)
|
|
{
|
|
jQuery(this).before(_this.headerDiv);
|
|
return false;
|
|
}
|
|
else if (i == (_cnt - 1))
|
|
{
|
|
jQuery(this).after(_this.headerDiv);
|
|
return false;
|
|
}
|
|
});
|
|
}
|
|
else
|
|
{
|
|
jQuery(this.contHeaderDiv).append(this.headerDiv);
|
|
}
|
|
|
|
jQuery(this.contDiv).append(this.contentDiv);
|
|
}
|
|
|
|
/**
|
|
* set notification
|
|
*
|
|
* @param {int} _value if set to 0 the notification gets reset if nothing set
|
|
* it will increase the notification value by one
|
|
*/
|
|
window.egw_fw_ui_tab.prototype.setNotification = function(_value)
|
|
{
|
|
this.notification = typeof _value != 'undefined' ? _value : this.notification+1;
|
|
jQuery(this.notificationDiv).text(this.notification).toggle(this.notification > 0);
|
|
};
|
|
|
|
/**
|
|
* setTitle sets the title of this tab. An existing title will be removed.
|
|
*
|
|
* @param {string} _title HTML/Text which should be displayed.
|
|
*/
|
|
window.egw_fw_ui_tab.prototype.setTitle = function(_title)
|
|
{
|
|
this.title = _title;
|
|
jQuery(this.headerH1).empty();
|
|
jQuery(this.headerH1).text(_title);
|
|
};
|
|
|
|
/**
|
|
* setHint sets tooltip of this tab. An existing tooltip will be removed.
|
|
*
|
|
* @param {string} _hint Text which should be displayed.
|
|
*/
|
|
window.egw_fw_ui_tab.prototype.setHint = function(_hint)
|
|
{
|
|
this.hint = _hint;
|
|
egw().tooltipBind(jQuery(this.headerDiv), _hint);
|
|
};
|
|
|
|
/**
|
|
* setTitle sets the content of this tab. Existing content is removed.
|
|
*
|
|
* @param {string} _content HTML/Text which should be displayed.
|
|
*/
|
|
window.egw_fw_ui_tab.prototype.setContent = function(_content)
|
|
{
|
|
jQuery(this.contentDiv).empty();
|
|
jQuery(this.contentDiv).append(_content);
|
|
};
|
|
|
|
/**
|
|
* Shows the content of the tab. Only one tab should be displayed at once. By using egw_fw_ui_tabs.showTab
|
|
* you can assure this.
|
|
*/
|
|
window.egw_fw_ui_tab.prototype.show = function()
|
|
{
|
|
jQuery(this.headerDiv).addClass("egw_fw_ui_tab_header_active");
|
|
var content = jQuery(this.contentDiv);
|
|
if(!content.is(':visible'))
|
|
{
|
|
content.show();
|
|
|
|
// Trigger an event on the browser content, so apps & widgets know
|
|
if(this.tag && this.tag.browser && this.tag.browser.contentDiv)
|
|
{
|
|
jQuery(this.tag.browser.contentDiv).trigger('show');
|
|
}
|
|
else if(content) // if the content is an iframe (eg. Calendar views)
|
|
{
|
|
jQuery(content).find('.egw_fw_content_browser_iframe').trigger('show');
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Hides the content of this tab.
|
|
*/
|
|
window.egw_fw_ui_tab.prototype.hide = function()
|
|
{
|
|
jQuery(this.headerDiv).removeClass("egw_fw_ui_tab_header_active");
|
|
var content = jQuery(this.contentDiv);
|
|
if(content.is(':visible'))
|
|
{
|
|
content.hide();
|
|
|
|
// Trigger an event on the browser content, so apps & widgets know
|
|
if(this.tag && this.tag.browser && this.tag.browser.contentDiv)
|
|
{
|
|
jQuery(this.tag.browser.contentDiv).trigger('hide');
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* hide tab header only
|
|
*/
|
|
window.egw_fw_ui_tab.prototype.hideTabHeader = function()
|
|
{
|
|
jQuery(this.headerDiv).hide();
|
|
};
|
|
|
|
/**
|
|
* Removes this tab and all its content.
|
|
*/
|
|
window.egw_fw_ui_tab.prototype.remove = function()
|
|
{
|
|
this.hide();
|
|
jQuery(this.contentDiv).remove();
|
|
jQuery(this.headerDiv).remove();
|
|
};
|
|
|
|
/**
|
|
* Sets whether the close button is shown/the close callback ever gets called.
|
|
*
|
|
* @param {boolean} _closeable if true, the close button is shown, if false, the close button is hidden. default is true.
|
|
*/
|
|
window.egw_fw_ui_tab.prototype.setCloseable = function(_closeable)
|
|
{
|
|
this.closeable = _closeable;
|
|
if (_closeable)
|
|
jQuery(this.closeButton).show();
|
|
else
|
|
jQuery(this.closeButton).hide();
|
|
};
|
|
|
|
|
|
/**
|
|
* Class: egw_fw_ui_tabs
|
|
* The egw_fw_ui_tabs class cares about displaying a set of tab sheets.
|
|
*/
|
|
|
|
|
|
/**
|
|
* The constructor of the egw_fw_ui_sidemenu_tabs class. Two "divs" are created inside the specified container element, one for the tab headers and one for the tab contents.
|
|
*
|
|
* @param {object} _contDiv specifies "div" element the tab ui element should be displayed in.
|
|
*/
|
|
window.egw_fw_ui_tabs = function(_contDiv)
|
|
{
|
|
this.contDiv = _contDiv;
|
|
|
|
//Create a div for the tab headers
|
|
this.contHeaderDiv = document.createElement("div");
|
|
jQuery(this.contHeaderDiv).addClass("egw_fw_ui_tabs_header");
|
|
jQuery(this.contDiv).append(this.contHeaderDiv);
|
|
|
|
this.appHeaderContainer = jQuery(document.createElement("div"));
|
|
this.appHeaderContainer.addClass("egw_fw_ui_app_header_container");
|
|
jQuery(this.contDiv).append(this.appHeaderContainer);
|
|
|
|
this.appHeader = jQuery(document.createElement("div"));
|
|
this.appHeader.addClass("egw_fw_ui_app_header");
|
|
this.appHeader.hide();
|
|
this.appHeaderContainer.append(this.appHeader);
|
|
|
|
this.tabs = Array();
|
|
|
|
this.activeTab = null;
|
|
this.tabHistory = Array();
|
|
}
|
|
|
|
/**
|
|
* Sets the "appHeader" text below the tabs list.
|
|
*
|
|
* @param {string} _text is the text which will be seen in the appHeader.
|
|
* @param {string} _msg_class css class for message
|
|
*/
|
|
window.egw_fw_ui_tabs.prototype.setAppHeader = function(_text, _msg_class)
|
|
{
|
|
this.appHeader.text(_text);
|
|
this.appHeader.prop('class', "egw_fw_ui_app_header");
|
|
if (_msg_class) this.appHeader.addClass(_msg_class);
|
|
this.appHeader.show();
|
|
};
|
|
|
|
/**
|
|
* Function internally used to remove double entries from the tab history. The tab
|
|
* history is used to store the order in which the tabs have been opened, to be able
|
|
* to switch back to the last tab when a tab is closed. Double entries in the tab history
|
|
* may appear whenever a tab is deleted.
|
|
*/
|
|
window.egw_fw_ui_tabs.prototype.cleanHistory = function()
|
|
{
|
|
for (var i = this.tabHistory.length - 1; i >= 0; i--)
|
|
{
|
|
if (this.tabHistory[i] == this.tabHistory[i - 1])
|
|
{
|
|
array_remove(this.tabHistory, i);
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Adds a new tab to the tabs ui element.
|
|
* @param {string} _icon which should be displayed on the tab sheet header
|
|
* @param {function} _callback (_sender) function which should be called whenever the tab header is clicked. The _sender parameter passed is a reference to this egw_fw_ui_tab element.
|
|
* @param {function} _closeCallback (_sender) function which should be called whenever the close button of the tab is clicked. The _sender parameter passed is a reference to this egw_fw_ui_tab 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 {int} _pos specifies the position in the tab list. If _pos is -1, the tab will be added to the end of the tab list
|
|
* @param {string} application status
|
|
*/
|
|
window.egw_fw_ui_tabs.prototype.addTab = function(_icon, _callback, _closeCallback, _tag, _pos, _status)
|
|
{
|
|
var pos = -1;
|
|
if (typeof _pos != 'undefined')
|
|
pos = _pos;
|
|
|
|
var tab = new egw_fw_ui_tab(this, this.contHeaderDiv, this.contDiv, _icon, _callback,
|
|
_closeCallback, _tag, pos, _status);
|
|
|
|
//Insert the tab into the tab list.
|
|
var inserted = false;
|
|
if (pos > -1)
|
|
{
|
|
for (var i in this.tabs)
|
|
{
|
|
if (this.tabs[i].position > pos)
|
|
{
|
|
this.tabs.splice(i, 0, tab);
|
|
inserted = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pos == -1 || !inserted)
|
|
{
|
|
this.tabs[this.tabs.length] = tab;
|
|
}
|
|
|
|
if (this.activeTab == null)
|
|
this.showTab(tab);
|
|
|
|
return tab;
|
|
};
|
|
|
|
/**
|
|
* Removes the specified tab from the tab list whilst trying to keep one tab open.
|
|
* The tab which will be opened is determined throughout the tab open history.
|
|
*
|
|
* @param {object} _tab is the object which should be closed.
|
|
*/
|
|
window.egw_fw_ui_tabs.prototype.removeTab = function(_tab)
|
|
{
|
|
//Delete the deleted tab from the history
|
|
for (var i = this.tabHistory.length - 1; i >= 0; i--)
|
|
{
|
|
if (this.tabHistory[i] == _tab)
|
|
array_remove(this.tabHistory, i);
|
|
}
|
|
|
|
//Delete entries in the histroy which might be double
|
|
this.cleanHistory();
|
|
// lookup for next available tab
|
|
var lookUpTheNextTab = function(_tab){
|
|
for(var t in this.tabs)
|
|
{
|
|
if (_tab != this.tabs[t] && (this.tabs[t]['status'] != '5' || this.tabs[t]['tag']['isFrameworkTab'])) return this.tabs[t];
|
|
}
|
|
}.bind(this);
|
|
//Special treatement if the currently active tab gets deleted
|
|
if (_tab == this.activeTab)
|
|
{
|
|
//Search for the next tab which should be selected
|
|
if (this.tabs.length > 0)
|
|
{
|
|
//Check whether there is another tab in the tab history,
|
|
//if not, look up for the next available tab.
|
|
var tab = lookUpTheNextTab(_tab);
|
|
if (typeof this.tabHistory[this.tabHistory.length - 1] != 'undefined')
|
|
{
|
|
tab = this.tabHistory[this.tabHistory.length - 1];
|
|
}
|
|
|
|
tab.callback.call(tab);
|
|
}
|
|
}
|
|
|
|
//Perform the actual deletion of the tab
|
|
_tab.remove();
|
|
for (var i = this.tabs.length - 1; i >= 0; i--)
|
|
{
|
|
if (this.tabs[i] == _tab)
|
|
array_remove(this.tabs, i);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Shows the specified _tab whilst closing all others.
|
|
*
|
|
* @param {object} _tab is the object which should be opened.
|
|
*/
|
|
window.egw_fw_ui_tabs.prototype.showTab = function(_tab)
|
|
{
|
|
if (this.activeTab != _tab && (_tab.status != '5' || _tab.tag.isFrameworkTab))
|
|
{
|
|
for (var i = 0; i < this.tabs.length; i++)
|
|
{
|
|
if (this.tabs[i] != _tab)
|
|
{
|
|
this.tabs[i].hide();
|
|
}
|
|
}
|
|
|
|
_tab.show();
|
|
this.activeTab = _tab;
|
|
|
|
if (this.tabHistory[this.tabHistory.length - 1] != _tab)
|
|
this.tabHistory[this.tabHistory.length] = _tab;
|
|
|
|
//Limit the tabHistory size in order to save memory
|
|
if (this.tabHistory.length > 50)
|
|
{
|
|
array_remove(this.tabHistory, 0);
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Calls the setCloseable function of all tabs in the list.
|
|
*
|
|
* @param {boolean} _closeable
|
|
*/
|
|
window.egw_fw_ui_tabs.prototype.setCloseable = function(_closeable)
|
|
{
|
|
for (var i = 0; i < this.tabs.length; i++)
|
|
{
|
|
this.tabs[i].setCloseable(_closeable);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Clears all data, removes all tabs, independently from the question, whether they may be closed or
|
|
* not.
|
|
*/
|
|
window.egw_fw_ui_tabs.prototype.clean = function()
|
|
{
|
|
//Remove all tabs, clean the tabs array
|
|
for (var i = 0; i < this.tabs.length; i++)
|
|
{
|
|
array_remove(this.tabs, i);
|
|
}
|
|
|
|
//Reset all arrays and references
|
|
this.tabs = new Array();
|
|
this.activeTab = null;
|
|
this.tabHistroy = new Array();
|
|
|
|
return true;
|
|
};
|
|
|
|
/**
|
|
* Check if we have not the last tab visible in the tab stack
|
|
*
|
|
* @return {boolean} returns true if the open tab is not the last visible tab otherwise false
|
|
*/
|
|
window.egw_fw_ui_tabs.prototype._isNotTheLastTab = function()
|
|
{
|
|
var n = 0;
|
|
for (var i in this.tabs)
|
|
{
|
|
//exclude open tabs with status 5, e.g. status app
|
|
if (this.tabs[i]['status'] != '5' || this.tabs[i]['tag']['isFrameworkTab']) n++;
|
|
}
|
|
return n > 1 ? true : false;
|
|
};
|
|
|
|
/**
|
|
* get tab object for given appname
|
|
*
|
|
* @param {string} _appname
|
|
* @returns {object|boolean} returns tab object, returns false if no tab found
|
|
*/
|
|
window.egw_fw_ui_tabs.prototype.getTab = function(_appname)
|
|
{
|
|
for (var i = 0; i < this.tabs.length; i++)
|
|
{
|
|
if (this.tabs[i] && this.tabs[i]['tag']['appName'] == _appname)
|
|
{
|
|
return this.tabs[i];
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
|
|
/**
|
|
* Class: egw_fw_ui_category
|
|
* A class which manages and renderes a simple menu with categories, which can be opened and shown
|
|
*
|
|
* @param {object} _contDiv
|
|
* @param {string} _name
|
|
* @param {string} _title
|
|
* @param {object} _content
|
|
* @param {function} _callback
|
|
* @param {function} _animationCallback
|
|
* @param {object} _tag
|
|
*/
|
|
|
|
window.egw_fw_ui_category = function(_contDiv, _name, _title, _content, _callback, _animationCallback, _tag)
|
|
{
|
|
//Copy the parameters
|
|
this.contDiv = _contDiv;
|
|
this.catName = _name;
|
|
this.callback = _callback;
|
|
this.animationCallback = _animationCallback;
|
|
this.tag = _tag;
|
|
|
|
// Unique ID for accessibility
|
|
let uid = "sidebox_nav_"+egw.uid();
|
|
|
|
//Create the ui divs
|
|
this.headerDiv = document.createElement('nav');
|
|
jQuery(this.headerDiv).addClass('egw_fw_ui_category')
|
|
.attr("aria-haspopup",true)
|
|
.attr("aria-labelledby",uid)
|
|
.attr("role","section")
|
|
.attr("tabindex",0);
|
|
|
|
//Add the text
|
|
var entryH2 = document.createElement('h2');
|
|
jQuery(entryH2)
|
|
.attr("id",uid)
|
|
.append(_title);
|
|
jQuery(this.headerDiv).append(entryH2);
|
|
|
|
//Add the content
|
|
this.contentDiv = document.createElement('ul');
|
|
this.contentDiv._parent = this;
|
|
jQuery(this.contentDiv).addClass('egw_fw_ui_category_content');
|
|
jQuery(this.contentDiv).append(_content);
|
|
jQuery(this.contentDiv).hide();
|
|
|
|
//Add content and header to the content div, add some magic jQuery code in order to make it foldable
|
|
this.headerDiv._parent = this;
|
|
entryH2._parent = this;
|
|
jQuery(this.headerDiv).on("keydown",
|
|
function(e) {
|
|
if(e.type == "keydown" && [EGW_KEY_ENTER, EGW_KEY_SPACE].indexOf(e.which) == -1) return;
|
|
if (!jQuery(this).hasClass("egw_fw_ui_category_active"))
|
|
{
|
|
this._parent.open(false);
|
|
}
|
|
else
|
|
{
|
|
this._parent.close(false);
|
|
}
|
|
e.stopPropagation();
|
|
});
|
|
jQuery(entryH2).on("click",
|
|
function(e) {
|
|
if (!jQuery(this).parent().hasClass("egw_fw_ui_category_active"))
|
|
{
|
|
this._parent.open(false);
|
|
}
|
|
else
|
|
{
|
|
this._parent.close(false);
|
|
}
|
|
e.stopPropagation();
|
|
});
|
|
jQuery(this.contDiv).append(this.headerDiv);
|
|
jQuery(this.headerDiv).append(this.contentDiv);
|
|
}
|
|
|
|
window.egw_fw_ui_category.prototype.open = function(_instantly)
|
|
{
|
|
this.callback.call(this, true);
|
|
jQuery(this.headerDiv).addClass('egw_fw_ui_category_active')
|
|
.attr("aria-expanded",true);
|
|
|
|
if (_instantly)
|
|
{
|
|
jQuery(this.contentDiv).show();
|
|
this.animationCallback();
|
|
}
|
|
else
|
|
{
|
|
jQuery(this.contentDiv).slideDown(200, function() {
|
|
this._parent.animationCallback.call(this._parent);
|
|
});
|
|
}
|
|
jQuery("li:first-child", this.headerDiv).eq(0).focus();
|
|
};
|
|
|
|
window.egw_fw_ui_category.prototype.close = function(_instantly)
|
|
{
|
|
this.callback.call(this, false);
|
|
jQuery(this.headerDiv).removeClass('egw_fw_ui_category_active')
|
|
.attr("aria-expanded", false);
|
|
|
|
if (_instantly)
|
|
{
|
|
jQuery(this.contentDiv).hide();
|
|
this.animationCallback();
|
|
}
|
|
else
|
|
{
|
|
jQuery(this.contentDiv).slideUp(200, function() {
|
|
this._parent.animationCallback.call(this._parent);
|
|
});
|
|
}
|
|
};
|
|
|
|
window.egw_fw_ui_category.prototype.remove = function()
|
|
{
|
|
//Delete the content and header div
|
|
jQuery(this.contDiv).remove();
|
|
jQuery(this.headerDiv).remove();
|
|
};
|
|
|
|
/**
|
|
* egw_fw_ui_scrollarea class
|
|
*
|
|
* @param {object} _contDiv
|
|
*/
|
|
|
|
window.egw_fw_ui_scrollarea = function(_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";
|
|
jQuery(this.scrollDiv).addClass("egw_fw_ui_scrollarea");
|
|
|
|
//Mousewheel handler
|
|
var self = this;
|
|
jQuery(this.scrollDiv).on('mousewheel',function(e, delta) {
|
|
var noscroll = false;
|
|
|
|
// Do not scrolldown/up when we are on selectbox items
|
|
// seems Firefox does not prevent the mousewheel event over
|
|
// selectbox items with scrollbars
|
|
if (e.target.tagName == "OPTION" || e.target.tagName == "SELECT")
|
|
{
|
|
noscroll = true;
|
|
}
|
|
if (delta && !noscroll)
|
|
{
|
|
e.stopPropagation();
|
|
self.scrollDelta(- delta * 30);
|
|
if (self.contHeight != this.scrollHeight) self.update();
|
|
}
|
|
|
|
});
|
|
|
|
//Create a container which contains the up/down buttons and the scrollDiv
|
|
this.outerDiv = document.createElement("div");
|
|
jQuery(this.outerDiv).addClass("egw_fw_ui_scrollarea_outerdiv");
|
|
jQuery(this.outerDiv).append(this.scrollDiv);
|
|
|
|
jQuery(this.contDiv).children().appendTo(this.scrollDiv);
|
|
jQuery(this.contDiv).append(this.outerDiv);
|
|
this.contentDiv = this.scrollDiv;
|
|
|
|
//Create the "up" and the "down" button
|
|
this.btnUp = document.createElement("span");
|
|
jQuery(this.btnUp).addClass("egw_fw_ui_scrollarea_button");
|
|
jQuery(this.btnUp).addClass("egw_fw_ui_scrollarea_button_up");
|
|
jQuery(this.btnUp).hide();
|
|
|
|
this.btnUp._parent = this;
|
|
jQuery(this.btnUp).mouseenter(function(){
|
|
this._parent.mouseOverToggle(true, -1);
|
|
jQuery(this).addClass("egw_fw_ui_scrollarea_button_hover");
|
|
});
|
|
jQuery(this.btnUp).click(function(){
|
|
this._parent.setScrollPos(0);
|
|
});
|
|
jQuery(this.btnUp).mouseleave(function(){
|
|
this._parent.mouseOverToggle(false, -1);
|
|
jQuery(this).removeClass("egw_fw_ui_scrollarea_button_hover");
|
|
});
|
|
|
|
jQuery(this.outerDiv).prepend(this.btnUp);
|
|
|
|
this.btnDown = document.createElement("span");
|
|
jQuery(this.btnDown).addClass("egw_fw_ui_scrollarea_button");
|
|
jQuery(this.btnDown).addClass("egw_fw_ui_scrollarea_button_down");
|
|
jQuery(this.btnDown).hide();
|
|
|
|
this.btnDown._parent = this;
|
|
jQuery(this.btnDown).mouseenter(function(){
|
|
this._parent.mouseOverToggle(true, 1);
|
|
jQuery(this).addClass("egw_fw_ui_scrollarea_button_hover");
|
|
});
|
|
jQuery(this.btnDown).click(function() {
|
|
this._parent.setScrollPos(this._parent.maxScrollPos);
|
|
});
|
|
jQuery(this.btnDown).mouseleave(function(){
|
|
this._parent.mouseOverToggle(false, 1);
|
|
jQuery(this).removeClass("egw_fw_ui_scrollarea_button_hover");
|
|
});
|
|
|
|
jQuery(this.outerDiv).prepend(this.btnDown);
|
|
|
|
//Update - read height of the children elements etc.
|
|
this.update();
|
|
}
|
|
|
|
window.egw_fw_ui_scrollarea.prototype.setScrollPos = function(_pos)
|
|
{
|
|
var scrollArea = egw.preference('scroll_area', 'common') == 1 ? true : false;
|
|
if (this.buttonsVisible)
|
|
{
|
|
if (scrollArea)
|
|
{
|
|
if (_pos <= 0)
|
|
{
|
|
if (this.btnUpEnabled)
|
|
jQuery(this.btnUp).addClass("egw_fw_ui_scrollarea_button_disabled");
|
|
if (!this.btnDownEnabled)
|
|
jQuery(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)
|
|
jQuery(this.btnDown).addClass("egw_fw_ui_scrollarea_button_disabled");
|
|
if (!this.btnUpEnabled)
|
|
jQuery(this.btnUp).removeClass("egw_fw_ui_scrollarea_button_disabled");
|
|
this.btnDownEnabled = false;
|
|
this.btnUpEnabled = true;
|
|
_pos = this.maxScrollPos;
|
|
}
|
|
else
|
|
{
|
|
if (!this.btnUpEnabled)
|
|
jQuery(this.btnUp).removeClass("egw_fw_ui_scrollarea_button_disabled");
|
|
if (!this.btnDownEnabled)
|
|
jQuery(this.btnDown).removeClass("egw_fw_ui_scrollarea_button_disabled");
|
|
this.btnUpEnabled = true;
|
|
this.btnDownEnabled = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (_pos <= 0)
|
|
{
|
|
_pos = 0;
|
|
}
|
|
else if (_pos >= this.maxScrollPos)
|
|
{
|
|
_pos = this.maxScrollPos;
|
|
}
|
|
jQuery(this.btnUp).addClass("egw_fw_ui_scrollarea_button_disabled");
|
|
jQuery(this.btnDown).addClass("egw_fw_ui_scrollarea_button_disabled");
|
|
}
|
|
this.scrollPos = _pos;
|
|
|
|
//Apply the calculated scroll position to the scrollDiv
|
|
this.scrollDiv.style.top = Math.round(-_pos) + 'px';
|
|
}
|
|
};
|
|
|
|
window.egw_fw_ui_scrollarea.prototype.scrollDelta = function(_delta)
|
|
{
|
|
this.setScrollPos(this.scrollPos + _delta);
|
|
};
|
|
|
|
window.egw_fw_ui_scrollarea.prototype.toggleButtons = function(_visible)
|
|
{
|
|
if (_visible)
|
|
{
|
|
jQuery(this.btnDown).show();
|
|
jQuery(this.btnUp).show();
|
|
this.buttonHeight = jQuery(this.btnDown).outerHeight();
|
|
this.maxScrollPos = this.contHeight - this.boxHeight;
|
|
this.setScrollPos(this.scrollPos);
|
|
}
|
|
else
|
|
{
|
|
this.scrollDiv.style.top = '0';
|
|
jQuery(this.btnDown).hide();
|
|
jQuery(this.btnUp).hide();
|
|
}
|
|
|
|
this.buttonsVisible = _visible;
|
|
};
|
|
|
|
window.egw_fw_ui_scrollarea.prototype.update = function()
|
|
{
|
|
//Get the height of the content and the outer box
|
|
this.contHeight = jQuery(this.scrollDiv).outerHeight();
|
|
this.boxHeight = jQuery(this.contDiv).height();
|
|
|
|
this.toggleButtons(this.contHeight > this.boxHeight);
|
|
this.setScrollPos(this.scrollPos);
|
|
};
|
|
|
|
window.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;
|
|
};
|
|
|
|
window.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
|
|
setTimeout(function(){_context.mouseOverCallback(_context);},
|
|
Math.round(_context.timerInterval * 1000));
|
|
}
|
|
};
|
|
|
|
window.egw_fw_ui_scrollarea.prototype.mouseOverToggle = function(_over, _dir)
|
|
{
|
|
this.mouseOver = _over;
|
|
this.dir = _dir;
|
|
this.update();
|
|
if (_over)
|
|
{
|
|
var _context = this;
|
|
setTimeout(function(){_context.mouseOverCallback(_context);},
|
|
Math.round(_context.timerInterval * 1000));
|
|
}
|
|
else
|
|
{
|
|
this.scrollTime = 0.0;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* egw_fw_ui_splitter class
|
|
*/
|
|
|
|
window.EGW_SPLITTER_HORIZONTAL = 0;
|
|
window.EGW_SPLITTER_VERTICAL = 1;
|
|
|
|
window.egw_fw_ui_splitter = function(_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;
|
|
jQuery(this.splitterDiv).addClass("egw_fw_ui_splitter");
|
|
|
|
//Setup the options for the dragable object
|
|
var dragoptions = {
|
|
listeners : {
|
|
start(event)
|
|
{
|
|
return event.currentTarget._parent.dragStartHandler.call(event.currentTarget._parent, event);
|
|
},
|
|
move (event)
|
|
{
|
|
return event.currentTarget._parent.dragHandler.call(event.currentTarget._parent, event);
|
|
},
|
|
end (event)
|
|
{
|
|
return event.currentTarget._parent.dragStopHandler.call(event.currentTarget._parent, event);
|
|
}
|
|
}
|
|
};
|
|
|
|
switch (this.orientation)
|
|
{
|
|
case EGW_SPLITTER_HORIZONTAL:
|
|
dragoptions.startAxis = 'y';
|
|
jQuery(this.splitterDiv).addClass("egw_fw_ui_splitter_horizontal");
|
|
break;
|
|
case EGW_SPLITTER_VERTICAL:
|
|
dragoptions.startAxis = 'x';
|
|
jQuery(this.splitterDiv).addClass("egw_fw_ui_splitter_vertical");
|
|
break;
|
|
}
|
|
interact(this.splitterDiv)
|
|
.styleCursor(false)
|
|
.draggable(dragoptions);
|
|
|
|
|
|
//Handle mouse hovering of the splitter div
|
|
jQuery(this.splitterDiv).mouseenter(function() {
|
|
jQuery(this).addClass("egw_fw_ui_splitter_hover");
|
|
});
|
|
jQuery(this.splitterDiv).mouseleave(function() {
|
|
jQuery(this).removeClass("egw_fw_ui_splitter_hover");
|
|
});
|
|
|
|
jQuery(this.contDiv).append(this.splitterDiv);
|
|
}
|
|
|
|
window.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;
|
|
};
|
|
|
|
window.egw_fw_ui_splitter.prototype.dragStartHandler = function(event)
|
|
{
|
|
switch (this.orientation)
|
|
{
|
|
case EGW_SPLITTER_HORIZONTAL:
|
|
this.startPos = event.clientY0;
|
|
break;
|
|
case EGW_SPLITTER_VERTICAL:
|
|
this.startPos = event.clientX0;
|
|
break;
|
|
}
|
|
};
|
|
|
|
window.egw_fw_ui_splitter.prototype.dragHandler = function(event)
|
|
{
|
|
var delta = 0;
|
|
switch (this.orientation)
|
|
{
|
|
case EGW_SPLITTER_HORIZONTAL:
|
|
delta = event.delta.y;
|
|
break;
|
|
case EGW_SPLITTER_VERTICAL:
|
|
delta = event.delta.x;
|
|
break;
|
|
}
|
|
|
|
//Clip the delta value
|
|
this.constraints[0].size += delta;
|
|
this.constraints[1].size -= delta;
|
|
|
|
// reset the size to minsize if it's dragged beyond it
|
|
if (this.constraints[0].size + delta <= this.constraints[0].minsize)
|
|
{
|
|
this.constraints[0].size = this.constraints[0].minsize;
|
|
return;
|
|
}
|
|
|
|
this.resizeCallback(this.constraints[0].size, this.constraints[1].size);
|
|
};
|
|
|
|
|
|
window.egw_fw_ui_splitter.prototype.dragStopHandler = function(event)
|
|
{
|
|
this.resizeCallback(this.constraints[0].size, this.constraints[1].size);
|
|
};
|
|
|
|
/**
|
|
* Disable/Enable drabbale splitter
|
|
* @param {type} _state
|
|
*/
|
|
window.egw_fw_ui_splitter.prototype.set_disable = function (_state)
|
|
{
|
|
interact(this.splitterDiv).options.drag.enabled = !_state;
|
|
};
|
|
|
|
/**
|
|
* Constructor for toggleSidebar UI object
|
|
*
|
|
* @param {type} _contentDiv sidemenu div
|
|
* @param {function} _toggleCallback callback function to set toggle prefernces and resize handling
|
|
* @param {object} _callbackContext context of the toggleCallback
|
|
* @returns {egw_fw_ui_toggleSidebar}
|
|
*/
|
|
window.egw_fw_ui_toggleSidebar = function(_contentDiv, _toggleCallback, _callbackContext)
|
|
{
|
|
var self = this;
|
|
this.toggleCallback = _toggleCallback;
|
|
this.toggleDiv = jQuery(document.createElement('div'))
|
|
.attr({id:"egw_fw_toggler", title:egw.lang("show/hide")})
|
|
.addClass('noPrint')
|
|
.click(function(){
|
|
self.onToggle(_callbackContext);
|
|
});
|
|
var span = jQuery(document.createElement('span')).addClass('et2_clickable').appendTo(this.toggleDiv);
|
|
|
|
if (egw.preference('audio_effect', 'common') === "1")
|
|
{
|
|
this.toggleAudio = jQuery(document.createElement('audio'))
|
|
.attr({src:"data:audio/mp3;base64,SUQzAwAAAAAAJlRQRTEAAAAcAAAAU291bmRKYXkuY29tIFNvdW5kIEVmZmVjdHMA//vWAAAAAAAASwUAAAAAAAlgoAAAFrIo+LjaAAKfxR8DGzAACAQAQA8EkDc7EmNfYBtgNPaFrAX/9oYzFwDKfkgRoZf+zWYNvDVIGBBhYuGFP/dyGC4BaACAQCggBQP/V7RKYyZLCE4pcV8NX//vxpiA4t4zAn8hhBCDf/9vFkHhc4ucXGO0UGOMLYDs///+90DAlRcYXUFRAXOTwzAi4W+BjD/////upmoIL/1M1v/w980IGSAcWAcLAyQYG5gpQAIGFh4t4ssXwcoBlSIGNFgFFwNEODVIWz8LuC3+UwvHcIoBQN4Fjg3k7vCxQTMiH8PQDVH/cdgtQNwB0gev/7MOeVw1eF/wvuDYx//iUC0JwIeQckCb//83GaDIg7CGCyDUgf//fyuTg0xSAjwaQuBhKYoP////FLjYGXImFz4sZFCJjoFwBdAG2AdJ/////6rWb2b2QW//4NtwuDFLhxoAKQFJhvgjgTgK0GVC2YHqwHJAcYBpKBnaAN8PVEmBvAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJZSnCiy0k4IEAAAEPQYcZfSbpcuCrxPRUofBcFTCjMrLtlv7OHxgQzpaYnK2y89WMsoalSPhYLqFeL4SnFB77rCGWGozl7lnVjqfbevVetFG6ncWQxX56sV2I4F8TKuyLrZe7iOOLuaucwuroV9Peu3/1Zr1+Zc2+tahfj05eb7P1mG2di7MYv/W+ZhpOUjre8zTa8xkD1lEJkh1Pk75ueqyybLIy1hmejpMzMzMzMydtojxtkvFssHvFnjaR6MYf/71gBgAAbkikZmPYAA3vFIzMewABxqKRiZhgADl8UjEzTAACIfn8zMzMzMzNMLq2xZPbvm/CSnjI58qBsM0AePNClCzTGisMIAAABJBGBuH8MVwOtkzNMplZZyVTC3tGdGDtJz56O4aFNCKxOOuWPN2PsRk4IxeViDT+YLj0POLoSoP5JdLzuL/s60tlzMPmS+qcagjXwLmIGZva7vOPNUiPu74tRtrbddfRM0ucqeZs/TksFGqRNJHqZauV6VDu3m1LUtjl67W77UHxZszk2x3l9qd+fTP6v4lXnaI9pZCLpkmSF5EP5bLYkLSUdzMzMzMzMzjVX71PjYpJx1fZXD+Wx5ZiBOZmZmZmZl+r8D75ZXvFWxVqkQCSJCVEpKkSI5IIBARAuhFIMwoeqTNpiW0hUaFSgwREB7m3acuqImasfzMkKTlSLTp1atWozw+dVsoBDVrWVC2P5ePWSzRBhld7EK+N8vScE8/s/UudSlaH3IdWxW8duajqU08svLoufM63XOY4kXZD7DEqXNeY2Lj+7T7fRsTWt0ZvkO16qs7g/ma9vOLPytGrxtVc16a173V8ayXudd+mfjNn46KuZYcO0Z8pupPC8mHyOw4oK4OpmZmZmZmWYWrHVy8evnqeyRERtKjHNB/MzMzMzMzPqGzG4SOuCSePCYJYZEYkqh4qJEQQBABBASR1jSVwtxXKPFYrDI6EetaUMvULEJOteHkiozGfKy2QsWNIL6G6aM3LQHzotRkAfjy1jiX2Dyi7FKW75UVO2fPma3S3Wvsx4tW5rllCxqrfHZrzrF1ilQuXnah+kFLdxxAulirjh9jDHwzaiWPmkrNrJPijcfcvE057t9amlnpimDOWXffb92BiKGK1Xl6KFC88X5f+nGW63Vron4eW2X6lBsvVjp4dOQkgfDouvzMzMzMzMlz4HyW7qosGxBIZUshmVkJph+ZmZmZmZmrb5kcVVqEJMTF60diaZAWo8TRLCHCFRUJSFTSCbhSBABB/wqVH1ADI3sLjj/+9YADAAGFFxQdmMEkLkreg7MTJIW8Udn+YwgAtypLP8xhAhzgzxqKpBQ5pEIPc06zPtEaESpzaQtpRRiOQw8cvso+AJ5zLAT8Q3Ed1l7hNE7M8ae/FLLuzbW3jp4efiQCz925zXMLHLOt5tYaZDrB5h+Kn65Uwwwv6/LGzy5IKWpE235/eZ93hvHm69rGvDEP7+cl0giv8/v7zz//z7j3Huu35fbrunPT3NSyn1hh/4Yd5///4Ydw13fMdb5lYrw/Zt4WT5f///6v/vQ+UIAVCMhIQcylUQQQQwAa44jT5al3AkCOc6wLC0BI+klhnGsczzSjKhiLCah0gk5AiIE2R5FymQAdYGcKIpUSmIxHALOD1wOggbqJoPNDxVcvk6w9DgNBF03PJ2QMKVhQAsArcXGXA9RTKSQTcvM9S2NSDjQWgOWO9VdNNbHWdV1mZMDJn3KI4zQ1oU01p0E1Vsu6GWzA8ZlctoMbmf2r2Z7f0a2Ny4dJ8zOFwWGiD//+j/+g2bPl4ykcmYCoBkKsisisUEAmCmk2b9FnQ4JzU7S9UFh+wNxvYU9jrwc6rr2KWVxJMM+pIVz1Z/J3CH0UwFgwKhVPE3UuzctaKjmiYJGldyYtZ3KmXM0qzSEgCqJ90zcqbeP/rv//zz1tZe+uCSioMc6tnn/3v//+hQBpt2YJIH/jaq+Pfwuy3m8tb5z/8t/IlNHMdd9GWStLiBMsMcda/H987/67//+amDAV/vbAaP6nD/32sKkq36g0BvICo2wqQEAKBKSGLQQDIgDIcUH4MfzbeGqdueEklbTzkBvYXCEr2oQHBUxVkcteEFDTt3k7kpnX3QBhlAYSe7dfjeT+pyg6amgu6bmJiv8Sgy1zNn5nCQlEpsPeHWW//5rPW+6Sra+luwdiaeqFWtY/zX97rX982ADBqjQcVghlK8Lr//1V5//3+c5rgKfP07cJY+i5GCUcg7//r8df/O/+sv1/w4vBZkLnYKlsJkcsctp9P1Us6yE44CYdVIAARCATcrU//vWAAUABLJTU39hgAqo6mqM57wB1EVLQawxjYpfqKg09LGxm8bUZbUfZiUFF5jMOy4MsgbKGnep/hU5JytWrfZWsrT1lbjqYrHzRtVazaMxdLoUnpiY/a0TuR/B1B2jhYrtb2gPm1rvWqytZdrV3KnJi76YyOjJKTYmj9njoyJK2toq6y5ny61CcssnV3qTk4/lnja+Um1YCcfLmmrJzo6LSprM2HKPe/EkNfkd836tsZICSq7cGcfsRD1QpRZkGO4A5qnUaXrbEop8vYsB7jL17BVqha1aoVKrZNMUbD5zq9ewn50qEuoxUNQ1WxmaM4TQnO+O3HFHriufL4E+dPGJa2iUUzJ5Cr6VzafrxTK6SeLu0W2meJCOY5kNTtXOJ4Tlv9gZorDB3Oh0f2o2sJok5Q58qj/LigHCyHQYK3TwqxYczU+UqVVLjhStx/M3uK4FclSrhXOL7ZsAJpoBSbMom70MwikxjEozjj7q2UbxPASLxpjc+dQ4So43QnmdVxYXOMvVYjIaw6K5UExacHYiD2ZE1czahbUttLr+ncQHkONZaWtlnHtWWrR/PXuOIktG2l9V1edaXrM5htOfnhuIhDSH0aU6Rkg/LpUL5UJhmHA7lQczQtqIIUTzi5e6tKrCUuILiMxjaLrHtL5SnBdWVf3tc9OLczTXLtmAA0kCrdoKlpVCEsENlYMthvjAczuMAULtLE4iQ2OlILqCsVoTQ4iYVatjQPOEQHjAiTFArBAZNGVVY2DM9Trl06d6eRrfpb5+f+lVzXc8ykX0ltEbRLkNNZ5ctahY+sDJydj4MhIL66LPKx+TCeTTpbBBK5b93mYHYVBuVC2e9+59r/uMrc2j0MsrAa1waZOW0R9/8sqAdaAAAAALYHUciZJyoCiOottjmClO0UgxBaT8M4fZxmQoV0p0prTRCRZZHStj0o6KxrlDIaYXacSy0jUanU8oh1D6HiWqp4Z4pj9+YI7j9S8MwboYxtjOnE+p2pQvqv6vnWbZtnb+sjnM5MquP//71gA2gAZZU0xh73tiyGo5jT3vbBrp7ytHvY3LNblldPYxuVdZnt4k7hHdOUFvXlehB/n8pWBbV64Z0qzOnJWvrLMKDBjVfQfqOwblpeO5TdvbFOxN7FCrGles0GAk0WnIdiVQu9Rs5WWU2R34YW1/6nAJSOL0K3Kj8F7Fgb70n92poAAAAAAmoAYpoDDOE4SgFmLq9QoISWYpAvQQJ0Lw+yxIadKmfXgMbg+XZVHSjxNTieqdIn41oqCiEueZ4q0lqusa5bkAh9F4gY+po5nkiRMbSZfwJmp+wNctoEGFBc54MdgvA3R2/q2tTG4PkNT2o9VdWMyKNojtp+l2OcsBhn8wtT9XpBvdPor5hkkpaK2Xk3mtp2VpdObRa7+Iq2RX9pZIkeA33ZoMJtbxinFXF3WjnjVCRhp8MJu1ZACFhQMajZdhETx4qZ/kAgAAqWgDOdSmIOOA7kWfqnUZ3gjIdILIGu8Rg8m1RzsxipiBGw4opUsjzbCaKErMidQhads6h8+IG1aQ1TIlxXTWjUUrj5JLAzGQ1NASVscnyJNqxUPK9emWx2WF5k1JKrmLJh+M3RzOTWx4hJjBCOTNI3AWgOoD5dEEkpSCIJ2csKavE95ccr09C28IpKOxJK7BUfumLp7Eese/jDrBXK5w+O6wlf2TS1tivOX6t7wba1pnZvO7W1prM/vXm1K3396/Tb5/tr29ldyf/LTtq49ONzjTHLjQABAACctANI5DIhhDCBF3RsxHnOBVFpAPgV7pqGRWHYtGRzZGd4aFYsmB5gkgRMSKeHJMPoPPaL2GrXBixCySka0pDkJ4eppjXRKQujgH3XGUjTBecLqG1DRKcwcWRJQuQtWFqOq4xbiPsVlgler2pOMlq1CNDk5fIhN2J44OaXrHd9+FKlfVkEeSgSDlaiKj6wrbVCWWcUqBPbdXEE6K3Vn+tOzv5/ded21fmu98zes/k5Of01tnfXNm+Zad2lumGsU+11IfZCxomeGA92iAMqcbttK2Z5eOqRyjiSv/+9YACIAFFVNO6exLaJ2qWd09iW0UKUk1p6UtgoYpprWEpbBEyOcH0qzTW1hUbuxy4cLKQ9OSUYk8musk1eY8b1OFw5Kh+CYsnxitBYAqA7HVWFpFQw1C8NqCIGlk0CFDk4SKBQwWQF7SZaqLL5URIcRtKkqKIecKixdItIiJhS4jslsVERPBtG+RC5QkWwnk8odYQIlkCGCRVdNNCjKuKoW25xokFbCPXYkcLJF8ikU///b/VrJQApE5JbaU0EEUiXQlEtmk4xpMkSrIWq3Dh9DPG2lurSzq41MxJdhEVeJNCe6sgEZcgiEwdlmISgGuVkqhPSaKkD91I2cCwSRxOMwpqiYaCglQuMF0kJtizCJOmlCFeCoXYskKpY2kURLLLxnE1IeDoqN6i0qh5KgD6CcjQitCwvMoSrL3TFspQR4hQNo4KiQ2h29kIgyRCtCr//rkiwATjkku2J/joJwnoSkVMVQqIdpgi1FeYwEsZFM29ZGiOPLrBdGI1x44o961skZcJiNYlTTmysVszENjbSYGBQKGs2RnoHGSkSQrFMekhqkUKIUQrTRMLqMIydCQSo4ozdZIqXTIovexapnLg2StoChJa5QoJGTqgrbEQfIUK8Jk5XW5ok+UgfemhQ0rF735h55s3S1L1f4q1ViWbKyz2IsrgAUbbk22I950Xqjbzs4m8H9l7IWxrOYu1MCagVXJ2iIscUkXmNkYjRjxY4vbsgH7HiPoTsZspM05RcufQkhAKH7uOaYZUUxAm6BO8UxbPj64VRCp00EyzCaU1JFndWHUSJZCR7PJkir2EE0SxkRGnF1SFrFowYVRkRXTzaixPNQusbmvrEyqyrPxibfei5j1N0uGPyv9syRci+7SsqiKkm5IACmkU3ZQNUSHfeHI20F0Ys2d5kOAKqxqGkyVlnZ3b1yV6/Ahl3RR0E0Ow5EYtQWtQwqQmMr2PLkhaENEKDCXCcW2RJk6N8+IBPHIgjqDVUMTiurR3BOwFG1KpYgJrTg3LlrY3imWUOVy//vWADWABmFSy+sPe2LTLrl9YYxuWS1NL6wxjYsoqWX1hjGwt1O32I9KPlFAi7g1eJ1uZzBZnp9pO0Fu25M8dlw5OXpdWuS/mA6eMq9dsRcWeFVXKdWPHyENKMT7TZ4xYfXaMMjdTHOjbv0zY7ftw+9kZsRfZJOf+sbcBcnEYfitILW6/qc0AATSSctxEmNPdOG2bPwu9oy+44h0Dss+gJHVSveQR7PjvVjY1gWEgDI0BIDRU6Xx1L0R9EG9vMgPh4TUzLRSMBLOEMIi+IyQNHAaKdtRc68tXxFWzbq8qQCREYHBDMbrC4wjP1rD96DsWHHxOUxnfPmJ042bnhscvVOlRLL5t9mhzbUHHNoZy+6sklIj5KrsP9Tsa1qFUEDZSjP1SE5CThGgcJ48Uv1Zma3ntr051pmb/82nqZXb/M3ysz09M9P/kzPfWZvu72dSl5bchkd2AA7UtYADZTLl2BEmQrByBUAyMPEDFIUNomULrQ1TNnCADE7kt1IRycmzBFjBNImMjIgH60T3GFSYdi0dF8tKFVisDUuklalJrJ66Vj55cwjdKal1KtKrJdQyS7ZMrdgxNEgDqtZHFevYq1c5SB6RrI4NWFeEipjgfICowcHJXUrzk1ofD+mVE9QP6sc1ZPiWWYTRFRcWVK8il/BOEIfiUseLpZOYh1EfwbmAtXEydsbySLPk//3d60DarODu47/HLBvuvpkzF9ZNV19QjkACaSbm+wTxsKbwJac1c0KQGM5T2Dro+pIxgpC0vmYjmKwd1XNPry6cHyY6B4tllLbj4Oh+Oj5DLo+K3zYPSqeqWT25iOo9GVnzozJpZMTkq1WurY2W32E7CG0mODwquIxJJxyISlQXTs+HgS0hkSoF47na0lCgsDuYFx1wqnJPMTiohFcyNGxEw2XlYzLyLhFKpUSWJqlWpOXy88X1pwfOCdWA1HnR/cHBpQbHEFrArnUhFC8IPCr4Uzrxxu8WtONWXE1MyBCoVJtKw3vNddJQA0F4EopjYPMV0xbKBf/71gAKgATuU07p6UtokypJ3z0pbRTdSzusJS2ieimndYSltHsVG6dEjNI6g8TLsafKh0CWTBDJBg2wUi5tGWTNMU4lQvGiydFLXHhAZ1AMEJsfSI2nLNJzQwLiGTBwclnMaiQksiYmEn+w+SmqDMAwj1AVsiw0oKXmcbexMiOHUQXeJxWn2eoRriZ4yXIFTwIELy7R5exUuSwc4jmcfxQNlwEhRChQWT/2f/+lkhVMTNmslutoCNFQhDYj2Y7zJb9KdXQF1Osu08gUxsvFe7aDJlQUyFDjtf9cvMl12QQ400itiCr8SZk8ymm9JWUDV0npiiNE0sg7BHLkaBCTDDZAhJo7yq7EbgOwBGIcfi/KEKMhPx6EoaGmUVhNtyDF2WHEeHOwGE1UCGFN0H14gfpEkWVbgfyqnq6o7u//1/vTNrUFL7dZbaQqNwX0ks0/6ysIRDMlfyXU8efAmaLYwH46Rj7gRMGE7mfQHF1TKlrstWRMQbHR8PG2AbNGWRULgzmUeWL0MCpJWZeRMSkg0KSEXIGQ9rJFTiQm1EsKWJMG1UTbJCTEoLEQhsY6sydhBVjptY+FDjSFCZA0WQB5tEAVA3J0mC+EwbD5IiPkaESWV1JYLkJ0lRhUZFRQaRaQCYnYKP///6rfJCY/tbbbQJfbvMTLbz9JI5bGW6rCRaG4CfSJEaZJVaqZtUlJeySow2DA02ocbRIWG2pIWFTEyJVEGycUOJi47HGjzSIgGBOgM4RmjRDFRgy+sBZHRSKqAPJybMoxESNOPnysIhkVCYwRvIStnViCBQlC9CtJyyjRYVCaCJALkoUF6UaYupCs2gP09CQCrTRdUmbaJkfbX8Au2f//+oAuNgBW3VyW0ACJKIct4IQrur6Mr5Gx4rGnnS+7eNtxLHDIQUXnSZslmxOXVXqjMwSWTVPFVRmbGbS9aeHBuVRHTRIK56A+PyscQ4aGhydWRFRDicQyxEmUHz03jadfjXnJ66YFhhlwrsLXU/3jL9DM/HApphDEApkBLZP/+9YAPYAFl1LL7T2AALVKWX2sMAAeDiksmYmAA9pFJZMxQADxIYeKwkH8eHxYN9ptTlegRKDiu0ZPHXjuXF0bmFpNqZskMYRD2m19zMFe1Va2kVBYDIIDHlmkFFVKEl23SW2gSM5L9yOLs5fyzD1VrMPvLTy2JwFFY9O0byfeiK4grT26qo5vmWHOrl7JwXxCeaWXBmg3eX2WDgvPRDO2Ua+tVRmfMHKZxEteuTUImwNP3USacfHlEl6QuPnNHqphinEAljQWCmQi/hg0/0Kw561l7jPF/zhinmt19VZUQW4UNa0W43WhyvWtcWJyGzAXM2qz5apjg8s8YPDijGOBWC6mtFzt41Uy4XJijhglUaVCQQAAASEQ15cCiDksUqtmbpRqngIx3byG1ZU+yQ464qF8ZMc8MCh0yZTYnw6QMDgMQBKIXMkMOGob+LGKQAqQSgDY9aeQFKCUCZIGHzhYaGKQLJAiAdhDFzxgYCrIexDzMzF0KkO0cwdQ5KZUWZm7yflxNzc4QIeVGo6BlCYQZBSLIIMkTaaBmbHi6RpBDUeCNdSbopsgmpa6bJuggo+YIG5UPHbnyoitKg7KTTUaMt2ZBBGmqYKWgXEzE2LRQYyPORpBFVOmk7otY4gpFMzWyX/7GqBc0LGK11JJu5oyv/y0X1qKVSbsgpObmaRfYxNwwAAASHgkES/bZp6WMJeVo08rfDYBuvx21F0z0EIhAWDUcIWFgZYqHTlw1LoGvFgo8A0s8CgAEAcCREiiZOgKDw28OgASKD9A3pToooC4BcBdNw+cLSQt9CgQR0LOJg1oqSGTLJmUyysV4XMOEhxGEiamjImaDG5qhN2UOUMgVpYMjRkEEknWqbk26BiYMZlsjCoeQQZOpNnemtCjUgpTqMTI1Lh5aRmgzpJT6CSaaCC1uiy0mZZsixXTYuIzFaakjQnS6TTMp0jZSZ4xRTZjpk51J0//1ouq6FboMiX0TyZggg//5FFkwpNI+szUV1nSkcM2PF2eRIRII1RIRDRC//vWAASABiBY3P5rBIK+6xufzeEQEjFJYd2UgCLSLKszsvAEkEgkEgkEg1huvqGfxpzBBGmGDrWr6TCvwV0DE+sEAa1x0IKN8YfRo6zkH10RGQRTDNFdfluJXbFtplj43DMdfyKpqU+6fGSy/OkjEsqQ03jKH4elBeaq6oa3IYllPT243F2VMFR4aO1oMKq6XVZTjq1lrOntw5KJyX1HMf6kpIhK7W9/vLf/T5/vPDn1MKWtYm4g2k3J5BDv/zvN873H8OfT09vDDkNuW/cbwru5LKl96l7QNbeWzhVX/ASAKASARwQQQBAIBAIBAIMOczwbD+OSKk4YmfS6RkwIl2dYaAaTudAIzOMGTTszfyGEH0ky5dBdnZBUxLRu60+aq1rbiczryx7YclKalfCbxmae3SSixUrQI1yQxFIumpfu1tSixLMbcP5Nsw2UL7kajjz2r1neX6wqWPpMPvXHEuSpyJbGYf/H8f///7f/bwsd+YrW856LT9JCY/3/7rffx53mffwwlEY5Xf+Ly/71HYy+PU1W0/0q6saz///XLPDoYCQistkrwyyhousbrhjjFujc3SYSaSRXTDuFNaVQ4IQRBElwiQ144qyQikmk1L/xteFkIpFIpQxsUhUEQRFIpZuQJIkWoWTnRComlJF/5VLxVISVDKlWcWlZCiuOYiJkVyuP9f6qZihQx6zUFkSLdksiZyhU0iXIQq1K4xyU1USKUakC1oWud5Isazzvw1v/m0Giqb2U3sqtVcxiwGecYYhtYpYIllvGZtNmKa/BiwlGN1AnM+P5DcVg1VrKfponFGfMUJ8+fIcbryOnWVhZZqyuJ+k5LiXE0WiHCNJiVyeblcnrn8QY4twHz5PIc9kVyufSvYsG2nuYuJasLNvSmYn0KM9y9ivcXiMUc3TxYWWuISejKZy3ItYjRUNZmaE7ewo1rZr6xfBVqdV0+Xr3T9Zi/FrW3i1teFbMtQVeDMO+WDT+tgKVKNlJoCaM6Ewo56kFQKJc2FGwEKzTSvMopv/71gAOgAQTW9Lp6VtohauKfT0obRAtSTemJW2CFqkndPSxtNsIlSXblsf+KUTpLmmsXACIqeuxJtp0FxtTYUTJJtA6lyI2jdZpqa1ctpttbW1sWUoDuHtjpOw22tYeJI7WQ5znPaisH0fXPjbBKom0kOrqAQjvfDnTXxfTr//kMnXx//7a+v+Tv2+AXttmdtjQjDDnaJHChB2n3BVLUhWa2LSFEXIT2oSVpdpslg1IEUTuu0TxVACAKUyrpL2yiCHRSjChKJQ+gFxwHGwLjpVV9ZHDRUlRlytg6Jg6DNM4Lam7pj6BqQYVDWTIdAGB0TMU1zQtKdxkmHNz1xdfURIr3X/IOhWOP/j+Lk1f5NVyosKJtlBzYgNI4sLCgmByatIYHQMqnKztzSiRatXIRaKFlImqKzTRE3JUFQqwIlchdS2NQXSpdTTIVLWiMXWduYu/Ot2zs/lF9WNqLjY/xDJLXb7PU26a4zo6rFRLU2KRBqPqZmUh5ltS7m9JzuzV/Uv0YKySHHps7862n////p1u9uFO1wsO2gRlbVmjwVzC45by4kJjTRV6xETVKMVxCxG0OESysER2UltBEhIhErkpVLfaBBrA9N+l5lTUhP3dmZtMytrXr9Fl8+rWLmnzo6Ld8fsldiZZjvrH/ai89hSuzK3IDk5JrtFr6dyyKVGPY489U5yqGeqnqRbrtIxpJrj9Aij/6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACptkqVyti20B6XkoX6Oq7rzkuow2FUtsyetWSqoB4EhKHMxWsMUTkmi/1LrZ+5GBQ6hDmNH5cjWzHiqsol14XTpS40EpotuXj9XNkiKjKjWNs0QilJGrM0iZhjUkS6BpmWN6tFVE6KDDkbLI0Mtzy0hRSlkkTdNM6ZPH1n1OOSbYQqJhUMyIBV6MlSp960MvWupzIzOlT3HKcmbPGHB5OyAtNuqG20CkGFtmYEcrlGrmXnw3s6uc4cWKpZl5Dmbx//+9YAYAAE8lFK6exLYJqqGV097GwVFU0xrDHtkqEpZjT2PbI4hQIbDE8ZlrVibMhVbYj9jR8tm4v7fwH1av8/FTFUkIXYu+aVr03PmObbiiraUy1Q9ri5U80979KvPdR1av9tl6/Rypgifnob9ZQ8dHbnTKtdP/zlcPn4L1dXVZcddcutImUyffY3qtqb3wyWuGdJoHjIdFRuKkgD7NI5bJJHbYBAdTVkyYzDoGfeVRKigGxagGHU0Ykgk2JINTyNDRno9CUToyrdUWlVFSk4gstqPRNowViOuJyNWqq7KpGJvUKzWT5onjScmFhjbt9SK6GkXNSpRDiXIdFeH9GVa4UquaS+kJrCcYMaBZjYzpS82k/IribRfCYoN1FDirhv2tVjsKXnlkgqZ3j99bMkFteWzEmcosHUstdf31B////9v/r42SWNyVxyy2wCegJpDCfD1FyJVOpUcwqnKdRp6tuZFqo5FtwOuuuMj5tSVBCXQNfe6USVLAjOGROVFg6OvY4ClmS6PNFQsMBvlYZBvDiaXp0qZib22sYuV0rEYV9WNTPCUS24sivXCmbmZdQFLAfR1VtlOVSqj9kUS8oWK/jsSsVk0NVzJyZXLxzRLagwHeL7pFxJLTD+DKx6pLFrTWHz6Pq8v//////ZrAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsrakjbbbkiAWGnDNsNXq+tmJSKVZ8jUzRHRKPxKbB4tElFtIyUvivEZDyPvvFU8J0Lpy4fJi0ywZJYjKO61MvBqcA2VYySSaYnsswJxKbMT2CNSEwljsSXL0e9l3jpDUjkbHKkrIj4FQMwIYkmIFQDHag+W8zA2+IJwCQEg+SnvMpBKbMRBPCdDC6c9ac+s1ma1rXK5vZNvZsJf/1Hvr5U7w7EuoKhICgqdWdkRDZY5Y2023JEAuJGqow5f0ekTS//vWAGAABW9Rx+sMY2Ss6Zj9YSxsk+nqyAGlDcqZPlkANKW5ZDKZZPP7BUDEIImCGAyBIDGoPMhVA3BpUsTdCIicEYSRPFJ0MqLkpY0Qu4uhUjkfg1LNbEonGR9rV0hNYXLmz1cPJMHUrKmnjk9YXk5DNV0LsAlHZaOR6AM+kBJBOAEkU6XLrWhYMUItF0RSaYxWTH0MRWBsWkpiZKutM67B1vmbbR4GwSiUQu/5Hu/WV1HlDyzdYaE1R4iPcGgwNHGFAIYKFBA5Qypw6dUnUURCNDIyMI4WsQiIHQdEArMPzatWp55RSTurq6uruO6ODkOglCUQBdHYkQglDIgC5g804koY9epRIwYWg+mJKGjYeJYkoaNIer+JmOrVpiHq/5iJ/UokYMLR6v4j////6aZ+rWJ4/+JiLq1ZRg0bEwpRIhCUSkPXClDRpD9HByDwShKIAujwSIQlEpAYtyuyoahgoYMDBPAaSaSSdRkhIhkaGi6CckJECoPA8IyQ27c9Suv7q/7q6up/+8eyRCEaGi6BuEVio0NF0DbmkKyqak88lVk01Ju2MlVlk4Tq6uquG/////5KNVf/ySqSU4a5pCsVOqTzfck7hPJRWVSSnD6yiIRoaLoG3b/VXDckqsqmpPN9yu6urq891/8lGquE3IhSIhkZKLwiiEILA6DoKCskbYDKwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/71gBgAAAAAEsAAAAAAAAJYAAAAAAAASwAAAAAAAAlgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/+9YAYAAAAABLAAAAAAAACWAAAAAAAAEsAAAAAAAAJYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//vWAGAAAAAASwAAAAAAAAlgAAAAAAABLAAAAAAAACWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/71gBgAAAAAEsAAAAAAAAJYAAAAAAAASwAAAAAAAAlgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/+9YAYAAAAABLAAAAAAAACWAAAAAAAAEsAAAAAAAAJYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//vWAGAAAAAASwAAAAAAAAlgAAAAAAABLAAAAAAAACWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/71gBgAAAAAEsAAAAAAAAJYAAAAAAAASwAAAAAAAAlgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/+9YAYAAAAABLAAAAAAAACWAAAAAAAAEsAAAAAAAAJYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//vWAGAAAAAASwAAAAAAAAlgAAAAAAABLAAAAAAAACWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/71gBgAAAAAEsAAAAAAAAJYAAAAAAAASwAAAAAAAAlgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAA="})
|
|
.appendTo(this.toggleDiv);
|
|
}
|
|
this.contDiv = jQuery(_contentDiv);
|
|
this.contDiv.prepend(this.toggleDiv);
|
|
};
|
|
|
|
/**
|
|
* Toggle menu on/off
|
|
* @param {object} _callbackContext context of the toggleCallback
|
|
*/
|
|
window.egw_fw_ui_toggleSidebar.prototype.onToggle = function(_callbackContext)
|
|
{
|
|
if (typeof this.toggleAudio != 'undefined') this.toggleAudio[0].play();
|
|
if (this.contDiv.hasClass('egw_fw_sidebar_toggleOn'))
|
|
{
|
|
this.contDiv.removeClass('egw_fw_sidebar_toggleOn');
|
|
var splitter = _callbackContext.splitterUi;
|
|
splitter.set_disable(false);
|
|
this.toggleCallback.call(_callbackContext,'off');
|
|
window.setTimeout(function() {
|
|
jQuery(window).resize();
|
|
},500);
|
|
}
|
|
else
|
|
{
|
|
this.contDiv.addClass('egw_fw_sidebar_toggleOn');
|
|
_callbackContext.splitterUi.set_disable(true);
|
|
this.toggleCallback.call(_callbackContext, 'on');
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Set sidebar toggle state
|
|
*
|
|
* @param {string} _state state can be 'on' or 'off'
|
|
* @param {type} _toggleCallback callback function to handle toggle preference and resize
|
|
* @param {type} _context context of callback function
|
|
*/
|
|
window.egw_fw_ui_toggleSidebar.prototype.set_toggle = function (_state, _toggleCallback, _context)
|
|
{
|
|
this.contDiv.toggleClass('egw_fw_sidebar_toggleOn',_state === 'on'?true:false);
|
|
_context.splitterUi.set_disable(_state === 'on'?true:false);
|
|
_toggleCallback.call(_context, _state);
|
|
}; |