/** * eGroupware Framework ui object * @package framework * @author Hadi Nategh * @author Andreas Stoeckel * @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"); this.headerDiv.setAttribute('title', this.tag.displayName); //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; this.headerDiv.addEventListener("keydown", function(e) { if (!["Enter", " "].includes(e.key) || e.target !== this) { return; } if (!jQuery(this).hasClass("egw_fw_ui_category_active")) { this._parent.open(false); } else { this._parent.close(false); } } ); entryH2.addEventListener("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.outerDiv.scrollIntoView(); 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,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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/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); };