/**
 * jsApplication
 * 
 * @author 2020 Bjoern Annighoefer
 */

var jsa = jsa || {};

/**
 * jsa is the global namespace for all Classes and functions belonging to jsa. 
 * __All jsa elements must be accessed via 'jsa.', e.g. 'new jsa.Application'.__
 * @namespace
 * @var {namespace} jsa
 * 
 * @example
 * //Create a new jsa Application
 * let app = new jsa.Application({
 *   name:'My Application'
 * });
 */
var jsa = (function() {

    /* CONSTANTS */
    /**
     * The current version of jsApplication
     * @var {string} VERSION
     * 
     * @example
     * // Get the jsa version
     * let v = jsa.VERSION;
     */
    let VERSION = '0.6.2';

    /**
     * The maximum level of nesting in menus
     * @var {int} MAX_MENU_POPUP_LEVEL
     * 
     * @example
     * // Get the maximum menu level
     * let v = jsa.MAX_MENU_POPUP_LEVEL;
     */
    let MAX_MENU_POPUP_LEVEL = 9;

    /**
     * A look-up table that maps a direction to its opposite, e.g. 
     * south (s) to north (n). It is used internally for identifying 
     * direction related CSS class names. The structure is defined as 
     * follows:
     * 
     *     {
     *         n : 's',
     *         e : 'w',
     *         s : 'n',
     *         w : 'e',
     *         nw : 'se',
     *         ne : 'sw',
     *         se : 'nw',
     *         sw : 'ne'
     *     }
     * 
     * @var {dict} DIRECTION_OPPOSITE
     */
    let DIRECTION_OPPOSITE = {
        n : 's',
        e : 'w',
        s : 'n',
        w : 'e',
        nw : 'se',
        ne : 'sw',
        se : 'nw',
        sw : 'ne'
    }

    /**
     * The default start-up levels for the application. Observers can listen to 
     * them to customize the start-up of an application. The defintion of this
     * structure is as follows:
     * 
     *      {
     *        INIT : 'INIT', //The $app variable is ready, but nothing else
     *        DATA : 'DATA', //The data connection (e.g. ecore sync, eoq, database, ...) is established. Good to add database relient plug-ins here. 
     *        MENU : 'MENU', //The menu is initialized. Good to add custom menu extensions here.
     *        TOOLS : 'TOOLS', // The toolbar is initialized. Good to add custom tools here.
     *        VIEWS : 'VIEWS',//nager is initialized good to add custom views here
     *        END: 'END' //The app is completly initialized and all graphical components are ready
     *      }
     * 
     * 
     * See [Application.SetStartupLevel]{@link Application#SetStartupLevel}.
     * @var {Object} APPLICATION_STARTUP_LEVELS
     * @type {{VIEWS: string, INIT: string, DATA: string, END: string, MENU: string, TOOLS: string}}
     */
    let APPLICATION_STARTUP_LEVELS = {
        INIT : 'INIT', //The $app variable is ready, but nothing else
        DATA : 'DATA', //The data connection (e.g. ecore sync, eoq, database, ...) is established. Good to add database relient plug-ins here. 
        MENU : 'MENU', //The menu is initialized. Good to add custom menu extensions here.
        TOOLS : 'TOOLS', // The toolbar is initialized. Good to add custom tools here.
        VIEWS : 'VIEWS',//nager is initialized good to add custom views here
        END: 'END' //The app is completly initialized and all graphical components are ready
    };

    
    /* HELPER FUNCTIONS */
    /**
     * Removes a specific element from an array. If the element is not included in the array, nothing happens.
     * @function ArrayRemove
     * @param {Array} arr - The array from which the element shall be removed
     * @param {number} value - The element to be removed from the array (arr).
     * @returns {Array} The given array (arr) without the element.
     *
     * @example
     * let abcd = ['a','b','c','d'];
     * let abd = jsa.ArrayRemove(abcd,'c');
     */
    function ArrayRemove(arr, value) {
        return arr.filter(function(ele){
            return ele != value;
        });
     }

    /**
     * Gets the width in pixels for the rendering area of the browser. 
     * This is only a temporal snapshot.  If the browser window or 
     * screen is resized, the value will change.
     * @function GetBrowserWidth
     * @returns {number} The width in pixels. 
     *
     * @example
     * let currentWidth = jsa.GetBrowserWidth();
     */
    function GetBrowserWidth() {
        return Math.max(
          document.body.scrollWidth,
          document.documentElement.scrollWidth,
          document.body.offsetWidth,
          document.documentElement.offsetWidth,
          document.documentElement.clientWidth
        );
      }

    /**
     * Gets the height in pixels for the rendering area of the browser. 
     * This is only a temporal snapshot.  If the browser window or 
     * screen is resized, the value will change.
     * @function GetBrowserHeight
     * @returns {number} The height in pixels
     *
     * @example
     * let currentWidth = jsa.GetBrowserHeight();
     */
    function GetBrowserHeight() {
    return Math.max(
        document.body.scrollHeight,
        document.documentElement.scrollHeight,
        document.body.offsetHeight,
        document.documentElement.offsetHeight,
        document.documentElement.clientHeight
    );
    }

    /**
     * CopyParams assigns values of fields that exist in the given object 
     * and in params from the params' fields to the object's fields. 
     * CopyParams(object,params) behaves similar to Object.assign(object,params)
     * , but it will not assign any field that does not exist in object before.
     * CopyParams is used for the initialization of almost every jsApplication UI 
     * element.
     * @function CopyParams
     * @param {Object} object - The objects whose fields shall be initialized from params.
     * @param {dict} params - The dict with (partially) identical fields whose values are copied to the corresponding fields of object.
     *
     * @example
     * let obj = {a: 1, b: 2, c: 3};
     * let par = {a: 4, c: 5, d: 6};
     * jsa.CopyParams(obj,par);
     * // obj -> {a: 4, b: 2, c: 5}
     */
    function CopyParams(object,params) {
        for(member in object) {
            if(member in params) {
                object[member] = params[member];
            }
        }
    };

    /**
     * A function that copies all fields from a source class to a 
     * target class. It excludes constructors and prototypes. It is
     * used as part of jsa.Mixin.
     * This function is for internal use only!
     * @function CopyClassProperties
     * @param {class} target - The targe class object
     * @param {class} source - The source class object
     */
    function CopyClassProperties(target, source) {
        for (let key of Reflect.ownKeys(source)) {
            if (key !== "constructor" && key !== "prototype" && key !== "name") {
                let desc = Object.getOwnPropertyDescriptor(source, key);
                Object.defineProperty(target, key, desc);
            }
        }
    };
    

    /**
     * Mixin fakes double inheritance. It can be used to inherit fields and methods
     * for a class that has already inherited from another class via ClassA.prototype =
     * Object.create(ClassB.prototype). Mixin can be used to inherit arbitrary times. 
     * Attention: Mixin does not take care on conflicts. Methods and field will be 
     * overwritten them with the ones from the latest mixin call. To inherit fields 
     * probably, make sure that the constructor of the inherited class is called in 
     * inheriting class, e.g. ClassB.call(this,...). Mixin inheritance is not probably 
     * recognized by the instanceof operator.
     * Special thanks to https://hacks.mozilla.org/2015/08/es6-in-depth-subclassing/
     * for the code.
     * @function Mixin
     * @param {class} clazz - The class that inherits
     * @param {class} superclazz - The class from which is inherited
     *
     * @example
     * function ClassA() {
     *  this.fieldA = 'a';
     * };
     * ClassA.prototype.methodA = function() {
     *  console.log('I am methodA!');
     * };
     * 
     * function ClassB() {
     *  this.fieldB = 'b';
     * };
     * ClassB.prototype.methodB = function() {
     *  console.log('I am methodB!');
     * };
     * 
     * function ClassC() {
     *  ClassA.call(this); //super constructor 1
     *  ClassB.call(this); //super constructor 2
     * };
     * ClassC.prototype = Object.Create(ClassA.prototype); //first (regular) inheritance
     * jsa.Mixin(ClassC,ClassB); //second (mixin) inheritance
     * 
     * let o = new ClassC();
     * o.methodA(); // -> 'I am methodA!'
     * o.methodB(); // -> 'I am methodB!'
     */
    function Mixin(clazz, superclazz) {
        CopyClassProperties(clazz, superclazz);
        CopyClassProperties(clazz.prototype, superclazz.prototype);
    };


    /* MULTIKEYMAP */
    /**
     * @class MultiKeyMap
     * @constructor MultiKeyMap
     * @classdesc A map that uses an array of keys instead of a single key.
     * the type of elements in the keys array can be arbitrary.
     * 
     * @example
     * let map = new jsa.MultiKeyMap();
     * map.Set(['string',13,3.14],'my value');
     * map.Has(['string',13,3.14]); //-> true
     * map.Get(['string',13,3.14]); //-> 'my value'
     * map.Delete(['string',13,3.14]); //-> true
     */
    function MultiKeyMap() {
        this.map = new Map();
    }

    /**
     * Checks if the given key exist in the map.
     * @method MultiKeyMap.prototype.Has
     * @param {Array} keys - An array of keys
     * @returns {boolean} True if the keys exists and false if not.
     */
    MultiKeyMap.prototype.Has = function(keys) {
        let has = false;
        let map = this.map;
        try {
            //loop until the very second last key
            for(let i=0;i<keys.length-1;i++) {
                let key = keys[i];
                if(map.has(key)) {
                    map = map.get(key);
                } else {
                    throw Error(); //leave the loop
                }
            }
            //check the last key for inclusion
            has = map.has(keys[keys.length-1]);
        } catch(e) {
            //nothing because it just means the element is not included
        }
        return has;
    };

    /**
     * Returns a value from the MultiKeyMap. Returns undefined if the value does not exist.
     * @method MultiKeyMap.prototype.Get
     * @param {Array} keys - An array of keys. Must have the same keys as used for storing.
     * @returns {Object} The value stored in the map or undefined.
     */
    MultiKeyMap.prototype.Get = function(keys) {
        value = undefined;
        let map = this.map;
        try {
            //loop until the very second last key
            for(let i=0;i<keys.length-1;i++) {
                let key = keys[i];
                if(map.has(key)) {
                    map = map.get(key);
                } else {
                    throw Error(); //leave the loop
                }
            }
            //return the last keys value
            value = map.get(keys[keys.length-1]);
        } catch(e) {
            //nothing because it just means the element is not included
        }
        return value;
    };

    /**
     * Stores a value in the MultiKeyMap or overwrites an existing one. 
     * @method MultiKeyMap.prototype.Set
     * @param {Array} keys - An array of keys
     * @param {Object} value - An arbitrary value to be stored at keys 
     */
    MultiKeyMap.prototype.Set = function(keys,value) {
        let map = this.map;
        //loop until the very second last key
        for(let i=0;i<keys.length-1;i++) {
            let key = keys[i];
            if(map.has(key)) {
                //return it if it exists
                map = map.get(key);
            } else {
                //create it if not
                newMap = new Map();
                map.set(key,newMap);
                map = newMap;
            }
        }
        //in the last key place the value
        map.set(keys[keys.length-1],value);
    };

    /**
     * Removes a value from the MultiKeyMap. 
     * @method MultiKeyMap.prototype.Delete
     * @param {Array} keys - An array of keys
     * @returns {boolean} True if the deletion was successful. False if not.
     */
    MultiKeyMap.prototype.Delete = function(keys) {
        let del = false;
        let map = this.map;
        try {
            //loop until the very second last key
            for(let i=0;i<keys.length-1;i++) {
                let key = keys[i];
                if(map.has(key)) {
                    map = map.get(key);
                } else {
                    throw Error(); //leave the loop
                }
            }
            //check the last key for inclusion
            del = map.delete(keys[keys.length-1]);
        } catch(e) {
            //nothing because it just means the element is not included
        }
        return del;
    };


    /* ALLREDIRECTEDDOMCALLBACKS */
    /**
     * Is used internally to keep track on all context-preserving DOM redirections.
     * See also [RedirectDomCallbackToUiElement]{@link RedirectDomCallbackToUiElement}
     * and [RemoveRedirectDomCallbackFromUiElement]{@link RemoveRedirectDomCallbackFromUiElement}.
     * @var allRedirectedDomCallbacks
     */
    let allRedirectedDomCallbacks = new MultiKeyMap();

    /**
     * This function adds a callback to a HTML event such that the callback
     * method is called in the context of the given object, i.e. using 
     * this... with the callback method behaves as expected and does not
     * refer to the HTML element
     * @function RedirectDomCallbackToUiElement
     * @param {HTML_DOM_ELEMENT} domElement - The HTML DOM element whose event shall be captured
     * @param {string} callbackId - The event to be captured, e.g. 'click' or 'mouseover' (s. https://developer.mozilla.org/de/docs/Web/Events)
     * @param {Object} uielement - The context object in which callbackFcn shall be called.
     * @param {method} callbackFcn - The method to be called if the event takes place.
     * @returns {function} - The internally created callback wrapper. This is the function that is 
     * actually registered as an event callback to the DOM element.
     *
     * @example
     * let MyUiElement = function() {
     *  this.name = 'My private name';
     * };
     * MyUiElement.prototype.OnClick = function(evt) {
     *  alert(this.name); 
     * };
     * 
     * let uielement = new MyUiElement();
     * let dom = document.createElement("div"); 
     * jsa.RedirectDomCallbackToUiElement(dom,'click',uielement,uielement.OnClick);
     * //clicking the div results in --> alert('My private name');
     */
    function RedirectDomCallbackToUiElement(domElement,callbackId,uielement,callbackFcn) {
        let redirectCallback = null;
        let redirectInfo = [domElement,callbackId,uielement,callbackFcn];

        if(allRedirectedDomCallbacks.Has(redirectInfo)) { //prevent double registrations
            redirectCallback = allRedirectedDomCallbacks.Get(redirectInfo);
        } else {
            domElement.uielement = uielement;
            redirectCallback = function(event) {
                //prevent dissolved callbacks from being called, even. This can happen if elements are dissolved in DOM callbacks
                if(!this.uielement.isDissolved) callbackFcn.call(this.uielement,event);
            };
            domElement.addEventListener(callbackId,redirectCallback); 
            allRedirectedDomCallbacks.Set(redirectInfo,redirectCallback);
        }
        return redirectCallback;
    };

    /**
     * This function removes a context-preserving callback established by
     * [RedirectDomCallbackToUiElement]{@link RedirectDomCallbackToUiElement}.
     * @function RemoveRedirectDomCallbackFromUiElement
     * @param {HTML_DOM_ELEMENT} domElement - The HTML DOM element whose event shall not be captured any more.
     * @param {string} callbackId - The event that was captured, e.g. 'click' or 'mouseover' (s. https://developer.mozilla.org/de/docs/Web/Events)
     * @param {Object} uielement - The context object in which callbackFcn is called.
     * @param {method} callbackFcn - The method to be called if the event takes place.
     *
     * @example
     * let MyUiElement = function() {
     *  this.name = 'My private name';
     * };
     * MyUiElement.prototype.OnClick = function(evt) {
     *  alert(this.name); 
     * };
     * 
     * let uielement = new MyUiElement();
     * let dom = document.createElement("div"); 
     * jsa.RedirectDomCallbackToUiElement(dom,'click',uielement,uielement.OnClick);
     * //... after some time you might want to remove the callback
     * jsa.RemoveRedirectDomCallbackFromUiElement(dom,'click',uielement,uielement.OnClick);
     */
    function RemoveRedirectDomCallbackFromUiElement(domElement,callbackId,uielement,callbackFcn) {
        let redirectInfo = [domElement,callbackId,uielement,callbackFcn];
        if(allRedirectedDomCallbacks.Has(redirectInfo)) { 
            let redirectCallback = allRedirectedDomCallbacks.Get(redirectInfo);
            domElement.removeEventListener(callbackId,redirectCallback); 
            allRedirectedDomCallbacks.Delete(redirectInfo);
        }
        
    };

    /**
     * Adds an array of CSS class names to the class attribute of a HTML DOM element.
     * Is used internally to transfer the content of param.style to HTML DOM elements.
     * @function ApplyStyles
     * @param {Array.<string>} styles - Array of styles, e.g. ['button','my-button'].
     * @param {HTML_DOM_ELEMENT} domElement - The HTML DOM element whose class property shall be changed
     *
     * @example
     * let dom = document.createElement("div"); 
     * jsa.ApplyStyles(['button','my-button'],dom);
     */
    function ApplyStyles(styles,domElement) {
        for(let i=0;i<styles.length;i++) {
            domElement.classList.add(styles[i]);
        }
    };

    /**
     * Generates a random numeric string of a fixed length. Is used internally, to set 
     * the id property of HTML DOM elements that have no ID. For all jsa UI elements the 
     * ID can be customized with setting params.id.
     * @function GenerateId
     * @returns {string} The ID as a string.
     *
     * @example
     * jsa.GenerateId(); //-> '53221' or '16432' or ...
     */
    function GenerateId() {
        return Math.random().toString(36).slice(-5);
    };

    /**
     * This encapsulates document.createElement(...) by simultaneously 
     * creating an HTML DOM element and setting its 'id' property to
     * either a specified ID or a random ID (s. GenerateId()).
     * @function CreateDomElementWithUniqueId
     * @param {string} elementType - The tag type to be created. 
     * @param {string} id=null - (optional) The id to be used for the new DOM element
     * @param {string} title=null - (optional) Sets the HTML title attribute to this value
     * @returns {HTML_DOM_ELEMENT} The new HTML DOM element
     *
     * @example
     * let domWithCustomId = jsa.CreateDomElementWithUniqueId("div","my_new_dom_element"); 
     * let domWithRandomId = jsa.CreateDomElementWithUniqueId("div"); 
     */
    function CreateDomElementWithUniqueId(elementType,id=null,title=null) {
        let  domElement = document.createElement(elementType);
        if(id) {
            domElement.id = id;
        } else {
            domElement.id = GenerateId();
        }
        if(title) {
            domElement.title = title;
        }
        return domElement;
    };


    /* OBSERVABLE */
    /**
     * @class Observable
     * @constructor Observable
     * @classdesc This is the super class for all elements in jsa 
     * that can be observed. An Observable will inform all observers by calling
     * their callback function. Use [StartObserving()]{@link Observable#StartObserving} to start listening to an
     * Observable. 
     *
     * @comment Observable internals
     * @property {Array} this.observers - (readonly) The list of observers that will be informed on [Notify()]{@link Observable#Notify}.
     */
    function Observable() {
        this.observers = [];
        this.shallNotify = true; //if set to false, no notifications are send
    }

    /**
     * Add an observer to the list observers. Each observer must be an instance of jsa.Observer. 
     * On Notify() its onNotifyCallback method is called (s. [Observer]{@link Observer}).
     * @method Observable.prototype.StartObserving
     * @param {Observer} observer - The observing object to be added. 
     * @returns {this} The observable itself
     *
     * @example
     * let nameChangeObserver = new jsa.Observer({
     *     onNotifyCallback: function(event,source) {
     *         if(jsa.EVENT.IS_INSTANCE(event,jsa.EVENT.TYPES.SET_NAME)) {
     *             name = event.data.name;
     *             alert('The name of the view changed to '+name);
     *         }
     *     }
     * });
     * let view = new jsa.View({name:'my view'});
     * view.StartObserving(nameChangeObserver);
     */
    Observable.prototype.StartObserving = function(observer) {
        this.observers.push(observer);
        return this;
    };

    /**
     * Removes an observer from the list of observers. Afterwards the observer gets no updates anymore.
     * @method Observable.prototype.StopObserving
     * @param {Observer} observer - The observing object to be added.  
     * @returns {this} The observable itself
     *
     * @example
     * // ... continues StartObserving example
     * view.StopObserving(nameChangeObserver);
     */
    Observable.prototype.StopObserving = function(observer) {
        this.observers = this.observers.filter(function(ele){ 
            return ele != observer; 
        });
        return this;
    };

    /**
     * Informs all observers of the observable on the given event.
     * @method Observable.prototype.Notify
     * @param {Event} event - The jsa event object to be forwarded to all listeners. Must be an instance of [Event]{@link Event}.
     * @param {type} excludedObserver=null - (optional) A specific observer that is not informed about the event. For instance this can be used to prevent infinite event loops in case the observer is itself an event provider. In that case the observe would exclude itself.
     * @returns {this} The observable itself
     *
     * @example
     * // ... continues StartObserving example
     * view.Notify(new Event(view,'NAMECHANGE',{view: view,name: 'my views new name'}));
     */
    Observable.prototype.Notify = function(event,excludedObserver=null) {
        if(this.shallNotify&&this.observers.length>0) {
            this.observers.forEach( function(observer) {
                if(observer!=excludedObserver) {
                    observer.onNotifyCallback(event);
                }
            });
        }
        return this;
    };

    /**
     * Disables all notification for this observable until EnableNotify is called.
     * Events send after notification is stopped are lost.
     * @method Observable.prototype.DisableNotify
     * @returns {this} The observable itself
     *
     * @example
     * // ... continues StartObserving example
     * view.DisableNotify();
     * view.Notify(new Event(view,'NAMECHANGE',{view: view,name: 'my views new name'})); //nothing happens
     * view.EnableNotify();
     * view.Notify(new Event(view,'NAMECHANGE',{view: view,name: 'my views new name'})); //notification comes through
     */
    Observable.prototype.DisableNotify = function() {
        this.shallNotify = false;
        return this;
    };

    /**
     * Enables all notification for this observable until EnableNotify is called.
     * @method Observable.prototype.EnableNotify
     * @returns {this} The observable itself
     *
     * @example
     * // ... continues StartObserving example
     * view.DisableNotify();
     * view.Notify(new Event(view,'NAMECHANGE',{view: view,name: 'my views new name'})); //nothing happens
     * view.EnableNotify();
     * view.Notify(new Event(view,'NAMECHANGE',{view: view,name: 'my views new name'})); //notification comes through
     */
    Observable.prototype.EnableNotify = function() {
        this.shallNotify = true;
        return this;
    };


    /*OBSERVER */
    /**
     * @class Observer
     * @constructor Observer
     * @classdesc The super class for all objects that would like to observe 
     * the events of an [jsa.Observable]{@link Observable}. On an event, the observable
     * calls onNotifyCallback of the observer.
     *
     * @param {dict} params=(see_below) - A dictionary of initialization parameters. Below for details.
     *
     * @comment Observer parameters
     * @property {Object} params.data=null - Custom user data to be used in callback. This prevents that always a specialization of Observer must be derived. The content of data can be accessed within the callback method via this.data.
     * @property {function} params.onNotifyCallback=null - The method/function that is called by the observable.
     *
     * @returns {this} The observer itself
     * 
     * @example
     * let nameChangeObserver = new jsa.Observer({
     *     onNotifyCallback: function(event,source) {
     *         if('NAMECHANGE' == event.eventId) {
     *             name = event.data.name;
     *             alert('The name of the view changed to '+name);
     *         }
     *     }
     * });
     * let view = new jsa.View({name:'my view'});
     * view.StartObserving(nameChangeObserver);
     */
    function Observer(params={}) {
        this.data = null; //custom user data to be used in callback
        this.onNotifyCallback = null;
        //copy parameters
        CopyParams(this,params);

        return this;
    };

    /**
     * Contains global event id definitions for jsa events. 
     * @class EVENT
     * @static
     * @property {string} SEPARATOR='/' - The split character for event IDs. 
     * @property {string} TYPES.SET='SET' - Generic set property value set events. 
     * @property {string} TYPES.SET_CONTENT='SET/content' - Setting the 'content' property of an element.
     * @property {string} TYPES.SET_STYLE='SET/style' - Setting the 'style' property of an element.
     * @property {string} TYPES.SET_ID='SET/id' - Setting the 'id' property of an element. 
     * @property {string} TYPES.SET_NAME='SET/name' - Setting the 'name' property of an element. 
     * @property {string} TYPES.SET_ICON='SET/icon' - Setting the 'icon' property of an element. 
     * @property {string} TYPES.SET_IS_ENABLED='SET/isEnabled' - Fired if an element is enabled or disabled.
     * @property {string} TYPES.SET_IS_ENABLED='SET/isEnabled' - Fired if an element is shown or hidden.
     * @property {string} TYPES.SET_ACTIVE_VIEW='SET/activeView' - The activeView property (of a ViewManager) changed.
     * @property {string} TYPES.SET_STARTUP_LEVEL='SET/startupLevel' - The startupLevel property (of an Application) changed.
     * @property {string} TYPES.ADD='ADD' - An value or entry was added to a multi-value property.
     * @property {string} TYPES.ADD_CHILD='ADD/children' - An child was added to the 'children' property.
     * @property {string} TYPES.REMOVE='REMOVE' - An value or entry was removed from a multi-value property.
     * @property {string} TYPES.REMOVE_CHILD='REMOVE/children'- An child was removed from the 'children' property.
     * @property {string} TYPES.METHOD_CALL='METHOD_CALL' - A certain method from a element was called (not all methods are observable)
     * @property {string} TYPES.METHOD_CALL_EXECUTE='METHOD_CALL/Execute' - Execute (from a CommandManager) was called.
     * @property {string} TYPES.METHOD_CALL_UNDO='METHOD_CALL/Undo'- Undo (from a CommandManager) was called.
     * @property {string} TYPES.METHOD_CALL_REDO='METHOD_CALL/Redo'- Redo (from a CommandManager) was called.
     * @property {string} TYPES.METHOD_CALL_DISSOLVE='METHOD_CALL/Dissolve - Dissolve (from a UIElementA) was called.
     * 
     * @example
     * if(jsa.EVENT.IS_INSTANCE(event,jsa.EVENT.TYPES.SET_CONTENT)) {
     *  //react if the content of an element was changed.
     * }
     */
    EVENT = {
        SEPARATOR: "/",
        TYPES: {
            SET: "SET",
            SET_CONTENT: "SET/content",
            SET_STYLE: "SET/style",
            SET_ID: "SET/id",
            SET_NAME: "SET/name",
            SET_ICON: "SET/ICON",
            SET_ACTIVE_VIEW: "SET/activeView",
            SET_STARTUP_LEVEL: "SET/startupLevel",
            SET_IS_ENABLED: "SET/isEnabled",
            SET_IS_VISIBLE: "SET/isVisible",
            ADD: "ADD",
            ADD_CHILD: "ADD/children",
            REMOVE: "REMOVE",
            REMOVE_CHILD: "REMOVE/children",
            METHOD_CALL: "METHOD_CALL",
            METHOD_CALL_EXECUTE: "METHOD_CALL/Execute",
            METHOD_CALL_UNDO: "METHOD_CALL/Undo",
            METHOD_CALL_REDO: "METHOD_CALL/Redo",
            METHOD_CALL_DISSOLVE: "METHOD_CALL/Dissolve"
        },
        /**
         * Checks if an event is of a certain event type by
         * comparing the event ID with an static event type
         * @method EVENT.IS_INSTANCE
         * @param {EventA} event - The event to be checked
         * @param {string} eventType - The event type or (partial) event ID to be checked.
         * @returns {boolean} True if the event is and instance of the event type and false if not.
         * @example
         * if(jsa.EVENT.IS_INSTANCE(event,jsa.EVENT.TYPES.SET_CONTENT)) {
         *  //react if the content of an element was changed.
         * }
         */
        IS_INSTANCE: function(event,eventType) {
            return event.eventId.startsWith(eventType);
        },
        /**
         * Build an jsa event Id from a array of strings, i.e. it places the separator 
         * between the given string segments of the event ID.
         * @method EVENT.EVENT_ID
         * @param {Array.<string>} segments - The array of event id segments to put in the event ID.
         * @returns {string} An valid event ID.
         * @example
         * let eventId = jsa.EVENT.EVENT_ID([jsa.EVENT.TYPES.SET,'content']);
         * // eventId is 'SET/content'
         */
        EVENT_ID: function(segments) {
            return segments.join(this.SEPARATOR);
        },
        /**
         * Splits an event ID in its segments by the event separator and returns this as an array.
         * @method EVENT.EVENT_SEGMENTS
         * @param {string} eventID - An valid event ID.
         * @returns {Array.<string>} The array of event id segments split at the separator.
         * @example
         * let eventId = jsa.EVENT.EVENT_ID([jsa.EVENT.TYPES.SET,'content']);
         * // eventId is 'SET/content'
         * let segments = jsa.EVENT.EVENT_SEGMENTS(eventId);
         * // segments is ['SET','content']
         */
        EVENT_SEGMENTS: function(eventId) {
            return eventId.split(this.SEPARATOR);
        }
    };

    /* EVENT A */
    /**
     * @abstract 
     * @class EventA
     * @classdesc The base interface for all events issued from an [jsa.Observable]{@link Observable} 
     * to an [jsa.Observer]{@link Observer}. There is no fixed set of events. Event can
     * be inherited to create custom events. However, all events exhibit the fields source,
     * and eventId to allow a unified event processing in observers.
     * See also the static event definitions and helpers at [EVENT]{@link EVENT}.
     *
     * @param {Observable} source - The source of the event
     * @param {string} eventId - A unique identification string for the type of event. It is preferred to use capital letters only.
     * @comment Event internals
     * @property {Observable} this.source - (readonly) The source of the event
     * @property {string} this.eventId - (readonly) A unique identification string for the type of event.
     *
     */
    function EventA(source,eventId) {
        this.source = source;
        this.eventId = eventId; //a string
    };

    /* EVENT CUSTOM */
    /**
     * @class EventCustom
     * @classdesc A class for events with an arbitrary event id and a custom data field. Use this if you do not want 
     * to extend the EventA class on your own.
     * The content of data can be custom. 
     * See also the static event definitions and helpers at [EVENT]{@link EVENT}.
     * @extends EventA
     *
     * @param {Observable} source - The source of the event
     * @param {string} eventId - A unique identification string for the type of event. It is preferred to use capital letters only.
     * @param {Object} data - A single primitive value or a complex object. In relation to the type, the structure of data should be static
     *
     * @comment Event internals
     * @property {Object} this.data - (readonly) The data attached to the event, which depends on the event type.
     *
     */
    function EventCustom(source,eventId,data) {
        EventA.call(this,source,eventId);
        this.data = data; //custom user data 
    };
    EventCustom.prototype = Object.create(EventA);

    /* EVENT SET */
    /**
     * @class EventSet
     * @classdesc An event that indicates that a property of an element has changed.
     * See also the static event definitions and helpers at [EVENT]{@link EVENT}.
     * @extends EventA
     *
     * @param {Observable} source - The source of the event
     * @param {string} propertyName - The name of the property that has changed
     * @param {Object} newValue - The current value of the property
     * @param {Object} oldValue - The old value of the property
     *
     * @comment Event internals
     * @property {string} this.propertyName - The name of the property that has changed
     * @property {Object} this.value - The current value of the property
     * @property {Object} this.oldValue - The old value of the property
     *
     */
    function EventSet(source,propertyName,newValue,oldValue) {
        EventA.call(this,source,EVENT.EVENT_ID([EVENT.TYPES.SET,propertyName]));
        this.propertyName = propertyName;
        this.value = newValue;
        this.oldValue = oldValue;
    };
    EventSet.prototype = Object.create(EventA);

    /* EVENT ADD */
    /**
     * @class EventAdd
     * @classdesc An event that indicates that an entry was added to a multi-element property, e.g. CustomContainerA.children.
     * See also the static event definitions and helpers at [EVENT]{@link EVENT}.
     * @extends EventA
     *
     * @param {Observable} source - The source of the event
     * @param {string} propertyName - The name of the property that has changed
     * @param {Object} value - The added value/entry
     * @param {Object} index - The index where the value/entry was added
     *
     * @comment Event internals
     * @property {string} this.propertyName - The name of the property that has changed
     * @property {Object} this.value - The added value
     * @property {Object} this.index - The index where the value was added
     *
     */
    function EventAdd(source,propertyName,value,index) {
        EventA.call(this,source,EVENT.EVENT_ID([EVENT.TYPES.ADD,propertyName]));
        this.propertyName = propertyName;
        this.value = value;
        this.index = index;
    };
    EventAdd.prototype = Object.create(EventA);

    /* EVENT REMOVE */
    /**
     * @class EventRemove
     * @classdesc An event that indicates that an entry was removed from a multi-element property, e.g. CustomContainerA.children.
     * See also the static event definitions and helpers at [EVENT]{@link EVENT}.
     * @extends EventA
     *
     * @param {Observable} source - The source of the event
     * @param {string} propertyName - The name of the property that has changed
     * @param {Object} value - The removed value/entry
     * @param {Object} index - The index where the value/entry was added
     *
     * @comment Event internals
     * @property {string} this.propertyName - The name of the property that has changed
     * @property {Object} this.value - The added value
     * @property {Object} this.index - The index where the value was added
     *
     */
    function EventRemove(source,propertyName,value,index) {
        EventA.call(this,source,EVENT.EVENT_ID([EVENT.TYPES.REMOVE,propertyName]));
        this.propertyName = propertyName;
        this.value = value;
        this.index = index;
    };
    EventRemove.prototype = Object.create(EventA);

    /* EVENT METHOD CALL */
    /**
     * @class EventMethodCall
     * @classdesc An event that indicates that a certain method of an object was called e.g. UIElement.Dissolve.
     * See also the static event definitions and helpers at [EVENT]{@link EVENT}.
     * @extends EventA
     *
     * @param {Observable} source - The source of the event
     * @param {string} methodName - The name of the method called
     * @param {Object} args - The input arguments of the method
     * @param {Object} result - The return value of the method
     *
     * @comment Event internals
     * @property {string} this.methodName - The name of the method called
     * @property {Object} this.args - The input arguments of the method
     * @property {Object} this.result - The return value of the method
     *
     */
    function EventMethodCall(source,methodName,args,result) {
        EventA.call(this,source,EVENT.EVENT_ID([EVENT.TYPES.METHOD_CALL,methodName]));
        this.args = args;
        this.result = result;
    };
    EventMethodCall.prototype = Object.create(EventA);


    /****************************************************
     * 
     * UI ELEMENTS START HERE 
     * 
     * **************************************************/

    /* UIELEMENTA (abstract)*/
    /**
     * @abstract
     * @class UIElementA
     * @classdesc The abstract base class for all visual elements of an jsApplication.
     * A UiElement is expected to include exactly one HTML DOM element.
     * It provides basic interactions as show, hide, disable, enable. 
     * It defines the basic methods for the interaction to HTML DOM elements, 
     * i.e. CreateDom and GetDomElement.  
     * 
     * @param {dict} params=(see_below) - A dictionary of initialization parameters. Below for details.
     * @param {boolean} [createDom=true] - To be used for inheritance of jsa elements. If set to false the HTML DOM element will not be created, e.g. [CreateDom()]{@link UIElementA#CreateDom} is not called.
     * 
     * @comment UIElementA parameters
     * @property {string} params.id=(random) - The id of the related DOM element.
     * @property {string} params.name='' - The name of the element.
     * @property {Object} params.data=null - Any user data to be attached to the element, e.g. for the use in callbacks.
     * @property {boolean} params.startVisible=true - Whether the element shall be visible after creation.
     * @property {boolean} params.startEnabled=true - Whether the element shall be enabled after creation.
     * @property {boolean} params.hasTooltip=false - Whether the element shall show a tooltip on mouseover or not.
     * @property {string} params.tooltip='' - The tooltip text
     * @property {string} params.titleAttr=null - The HTML title attribute of the HTML DOM element 
     * @comment UIElementA internals
     * @property {HTML_DOM_ELEMENT} this.domElement - (readonly) The HTML DOM element as attached to the document tree. This ensures compatibility to any other js library or function. Usually, this should not be accessed directly. Use [GetDomElement()]{@link UIElement#GetDomElement} instead.
     * @property {Application} this.app - (readonly) The jsa.Application object this element belongs to. This will be filled as soon as this object was added to an Application or any other element, which is a child of an application. Otherwise it is null.
     * @property {UIElementA} this.parent - (readonly) The parent element this element belongs to. This is set after adding it to a parent using AddChild(). Otherwise it is null.
     * @property {int} this.level=0 - (readonly) Indicates the level of nesting this UI element is currently in. The application itself has level 0. Every direct child level 1 and so on.
     * @property {HTML_STYLE_OBJECT} this.defaultDisplayStyle - (readonly) Internally used to store the original style of the corresponding HTML element during show and hide operations. Do not change it manually.
     * @property {boolean} this.isVisible - (readonly) The current state of visibility.
     * @property {boolean} this.isEnabled - (readonly) The current state of enablement.
     * @property {boolean} this.isDissolved - (readonly) This indicates that the element was dissolved, i.e. Dissolve was called.
     * @extends Observable
     * 
     * @returns {this} Instance of the element itself to enable method chaining
     */

    function UIElementA() {
        Observable.call(this);
        this.id = GenerateId();
        this.name = '';
        this.data = null; //user data
        this.startEnabled = true;
        this.startVisible = true;
        this.hasTooltip = false;
        this.tooltip = '';
        this.titleAttr = null;

        //internals
        /**
         * @private
         */
        this.domElement = {};
        this.app = null;
        this.parent = null; //the parent element
        this.defaultDisplayStyle = undefined;
        this.level = 0; //the number of nesting within the parents
        this.notify = true; //if false this disables all notifications to observables
        this.isVisible = true;
        this.isEnabled = true;
        this.isDissolved = false;

        return this;
    };
    UIElementA.prototype = Object.create(Observable.prototype);

    /**
     * Creates the HTML DOM element. In general, CreateDom is called automatically by the 
     * constructor. If it is necessary that the element must be initialized further before
     * the DOM can be created, the constructor can be called with createDom=false and 
     * CreateDom can be invoked manually afterwards. createDom=false shall also be used 
     * if the UiElement is used within an inheritance.
     * @method UIElementA.prototype.CreateDom
     */
    UIElementA.prototype.CreateDom = function() {
        throw new Error('UIElementA: Error: Not implemented needs to be overwritten!');
    }

    /**
     * Returns the HTML DOM element. It is the original DOM element, on which any build-in 
     * JS function or other JS framework can be used on.
     * @method UIElementA.prototype.GetDomElement
     * @returns {HTML_DOM_ELEMENT} The DOM element as attached to the document tree.
     *
     * @example
     * // Access the css style of an jsApplication element
     * myElement.GetDomElement().style.color = 'yellow';
     */
    UIElementA.prototype.GetDomElement = function() {
        return this.domElement;
    };

    /**
     * Returns the application object this element belongs to. This will only work, 
     * if the element or one of its parents was added to an Application instance with 
     * AddChild.
     * @returns {Application} The jsa.Application object.
     * @method UIElementA.prototype.GetApp
     *
     * @example
     * myElement.GetApp(); //returns null
     * app.AddChild(myElement);
     * myElement.GetApp(); //returns app
     */
    UIElementA.prototype.GetApp = function() {
        let  app = null;

        let  parent = this;
        while(parent.parent) {
            parent = parent.parent;
            if(parent instanceof Application) {
                app = parent;
            }
        }
        return app;
    };

    /**
     * Returns the tooltip string of the element. If null, no tooltip will be shown.
     * By default this returns this.tooltip. Overwrite this method to make the tooltip
     * dependent on other properties.
     * @method UIElementA.prototype.GetTooltip
     * @returns {string} The tooltip string.
     */
    UIElementA.prototype.GetTooltip = function() {
        return this.tooltip;
    };

    /**
     * This is the destructor. Dissolve friendly cleans up the element. It deletes the HTML DOM element and removes the element from any parent.
     * @method UIElementA.prototype.Dissolve
     * 
     * @fires [EventMethodCall]{@link EventMethodCall}(eventId= [EVENT.TYPES.METHOD_CALL]{@link EVENT}+'/Dissolve'; methodName = 'Dissolve')
     *
     * @example
     * myElement.Dissolve();
     * //will also do myParent.RemoveChild(myElement) 
     */
    UIElementA.prototype.Dissolve = function() {
        if(!this.isDissolved) {
            if(this.parent) {
                this.parent.RemoveChild(this,false);
            }
            if(this.domElement && this.domElement.parentElement) {
                this.domElement.parentElement.removeChild(this.domElement);
            }
            //mark as dissolved
            this.isDissolved = true;
            //notify observers
            this.Notify(new EventMethodCall(this,'Dissolve',null,null));
        }
    };

    /**
     * Visibly show the element to the screen. For most basic elements.
     * this behaves as domElement.style.display != 'none', but the behavior
     * can be changed by overwriting this method.
     * @returns {this} Returns an instance of the element itself to allow method chaining.
     * @method UIElementA.prototype.Show
     * 
     * @fires [EventSet]{@link EventSet}(eventId= [EVENT.TYPES.SET_IS_VISIBLE]{@link EVENT}; propertyName = 'isVisible')
     *
     * @example
     * if(myElement.isVisible==false) {
     *   myElement.Show();
     * }
     */
    UIElementA.prototype.Show = function() {
        if(!this.isVisible) {
            this.GetDomElement().style.display = this.defaultDisplayStyle;
            /* HACK: backdrop filters do not care about display none */
            this.GetDomElement().style.backdropFilter = this.defaultBackdropFilter;
            this.isVisible = true;
            //notify observers
            this.Notify(new EventSet(this,'isVisible',true,false));
        }
        return this;
    };

    /**
     * Hide the element from the screen. For most basic elements.
     * this behaves as domElement.style.display = 'none', but the behavior
     * can be changed by overwriting this method.
     * @returns {this} Returns an instance of the element itself to allow method chaining.
     * @method UIElementA.prototype.Hide
     * 
     * @fires [EventSet]{@link EventSet}(eventId= [EVENT.TYPES.SET_IS_VISIBLE]{@link EVENT}; propertyName = 'isVisible')
     *
     * @example
     * if(myElement.isVisible==true) {
     *   myElement.Hide();
     * }
     */
    UIElementA.prototype.Hide = function() {
        if(this.isVisible) {
            this.defaultDisplayStyle = this.GetDomElement().style.display;
            this.GetDomElement().style.display = 'none';
            /* HACK: backdrop filters do not care about display none */
            this.defaultBackdropFilter = this.GetDomElement().style.backdropFilter;
            this.GetDomElement().style.backdropFilter = 'none';
            this.isVisible = false;
            //notify observers
            this.Notify(new EventSet(this,'isVisible',false,true));
        }
        return this;
    };

    /**
     * Enable an element. Enabled means it takes user inputs and reacts to mouse events.
     * @returns {this} Returns an instance of the element itself to allow method chaining.
     * @method UIElementA.prototype.Enable
     * 
     * @fires [EventSet]{@link EventSet}(eventId= [EVENT.TYPES.SET_IS_ENABLED]{@link EVENT}; propertyName = 'isEnabled')
     *
     * @example
     * if(myElement.isEnabled=false) {
     *   myElement.Enable();
     * }
     */
    UIElementA.prototype.Enable = function() {
        if(!this.isEnabled) {
            let oldValue = this.isEnabled;
            this.GetDomElement().classList.remove('jsa-disabled');
            this.isEnabled = true;
            //notify observers
            this.Notify(new EventSet(this,'isEnabled',true,oldValue));
        }
        return this;
    };

    /**
     * Disable an element. Disabled means it takes no user inputs and does not react to mouse events.
     * @returns {this} Returns an instance of the element itself to allow method chaining.
     * @method UIElementA.prototype.Disable
     * 
     * @fires [EventSet]{@link EventSet}(eventId= [EVENT.TYPES.SET_IS_ENABLED]{@link EVENT}; propertyName = 'isEnabled')
     *
     * @example
     * if(myElement.isEnabled=true) {
     *   myElement.Disable();
     * }
     */
    UIElementA.prototype.Disable = function() {
        if(this.isEnabled) {
            let oldValue = this.isEnabled;
            this.GetDomElement().classList.add('jsa-disabled');
            this.isEnabled = false;
            //notify observers
            this.Notify(new EventSet(this,'isEnabled',false,oldValue));
        }
        return this;
    };

    /**
     * Checks whether this UI element is a direct (recurse = false) or indirect child of a given parent UiElement
     * @param {CustomContainerA} parent - The parent element to be checked against.
     * @param {boolean} recurse=true - If false only direct children are checked.
     * @returns {boolean} Returns true if this is a child of the parent.
     * @method UIElementA.prototype.IsChildOf
     */
    UIElementA.prototype.IsChildOf = function(parent,recurse=true) {
        let isChild = false;
        if(this.parent) {
            if(this.parent==parent) {
                isChild = true;
            } else if(recurse) {
                isChild = this.parent.IsChildOf(parent,true); // recursion
            }
        }
        return isChild;
    };

    /**
     * Is called when the element is added to a parent by [AddChild()]{@link CustomContainerA#AddChild}. 
     * Overwrite this method to add a custom behavior.
     * @callback
     * @param container {UIElementA} - The new container of this element.
     * @param app {Application} - The application object of the container, i.e. container.GetApp(). If the container is not part of an application, this is null.
     * @method UIElementA.prototype.OnAdded
     *
     * @example
     * MyElementClass.prototype = Object.create(UIElementA.prototype);
     * //@override
     * MyElementClass.prototype.OnAdded = function(container,app) {
     *   UIElementA.prototype.OnAdded.call(this,container,app); //call super OnAdded method if required.
     *   //Do own implementation here ...
     * };
     */
    UIElementA.prototype.OnAdded = function(container,app) {
        this.parent = container;
        if(this.parent) {
            this.level = this.parent.level+1;
        }
        this.app = app;
    };

    /**
     * Is called if the element is removed from its current parent by [RemoveChild()]{@link CustomContainerA#RemoveChild}. 
     * Overwrite this function to add a custom behavior.
     * @method UIElementA.prototype.OnRemoved
     *
     * @example
     * MyElementClass.prototype = Object.create(UIElementA.prototype);
     * //@override
     * MyElementClass.prototype.OnRemoved = function() {
     *   UIElementA.prototype.OnRemoved.call(this); //call super OnRemoved method if required.
     *   //Do own implementation here ...
     * };
     */
    UIElementA.prototype.OnRemoved = function() {
        this.parent = null;
        this.app = null;
    };


    /* UIELEMENTWITHICON*/
    /**
     * @abstract
     * @class UIElementWithIconA
     * @classdesc The abstract base class for all UI elements that exhibit an icon. 
     * Inheriting this class provides the local property icon as well as the universal 
     * Implementation of the SetIcon method. This base class is meant for complex UI element,
     * not for the icon class itself. It forwards the icon setting to a contained
     * Icon element. Every class inheriting this must call once DefineIconContainer to 
     * make it functional.
     * 
     * @property {string} this.icon - (readonly) The icon string, which is a url or CSS class name
     * 
     * @returns {this} Instance of the element itself to enable method chaining
     */
    function UIElementWithIconA() {
        this.icon = '';

        this.uiElementWithIconA = {
            iconContainer : null,
            setRoutine : ''
        };
        return this;
    };

    /**
     * Define the container and set routine, which is used when SetIcon is called.
     * @param {UIElementA} iconContainer - The element that contains the icon and to that the SetIcon call shall forwarded.
     * @param {string} iconSetRoutine - The name of the function to be called for the iconContainer, i.e. SetIcon calls iconContainer.iconSetRoutine().
     * @returns {this} Instance of the element itself to enable method chaining
     * @method UIElementWithIconA.prototype.DefineIconContainer
     */
    UIElementWithIconA.prototype.DefineIconContainer = function(iconContainer,iconSetRoutine) {
        this.uiElementWithIconA.iconContainer = iconContainer;
        this.uiElementWithIconA.setRoutine = iconSetRoutine;
        return this;
    };

     /**
     * Sets the icon dynamically.
     * @param {string} icon - The path to the new icon.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method UIElementWithIconA.prototype.SetIcon
     * 
     * @fires [EventSet]{@link EventSet}(eventId= [EVENT.TYPES.SET_ICON]{@link EVENT}; propertyName = 'icon')
     */
    UIElementWithIconA.prototype.SetIcon = function(icon) {
        let oldValue = this.icon
        this.icon = icon;
        //forward to the container if defined
        if(this.uiElementWithIconA.iconContainer) this.uiElementWithIconA.iconContainer[this.uiElementWithIconA.setRoutine](icon);
        //notify
        this.Notify(new EventSet(this,'icon',icon,oldValue));
        return this;
    };

    /* UIELEMENTWITHNAME*/
    /**
     * @abstract
     * @class UIElementWithNameA
     * @classdesc The abstract base class for all UI elements that exhibit a name. 
     * Inheriting this class provides the local property name as well as the universal 
     * Implementation of the SetName method. This base class is meant for complex UI element.
     * It forwards the name setting to a contained named element. Every class inheriting 
     * this must call once DefineNameContainer to make it functional.
     * 
     * @property {string} this.name - (readonly) the name
     * 
     * @returns {this} Instance of the element itself to enable method chaining
     */
    function UIElementWithNameA() {
        this.name = '';

        this.uiElementWithNameA = {
            nameContainer : null,
            setRoutine : ''
        };
        return this;
    };

    /**
     * Define the container and set routine, which is used when SetName is called.
     * @param {UIElementA} iconContainer - The element that contains the name and to that the SetName call shall forwarded.
     * @param {string} iconSetRoutine - The name of the function to be called for the nameContainer, i.e. SetName calls nameContainer.nameSetRoutine().
     * @returns {this} Instance of the element itself to enable method chaining
     * @method UIElementWithNameA.prototype.DefineNameContainer
     */
    UIElementWithNameA.prototype.DefineNameContainer = function(iconContainer,nameSetRoutine) {
        this.uiElementWithNameA.iconContainer = iconContainer;
        this.uiElementWithNameA.setRoutine = nameSetRoutine;
        return this;
    };

     /**
     * Sets the name dynamically.
     * @param {string} name - The new name
     * @returns {this} Instance of the element itself to enable method chaining
     * @method UIElementWithNameA.prototype.SetName
     * 
     * @fires [EventSet]{@link EventSet}(eventId= [EVENT.TYPES.SET_NAME]{@link EVENT}; propertyName = 'name')
     */
    UIElementWithNameA.prototype.SetName = function(name) {
        let oldValue = this.name
        this.name = name;
        //forward to the container if defined
        if(this.uiElementWithNameA.nameContainer) this.uiElementWithNameA.nameContainer[this.uiElementWithNameA.setRoutine](name);
        //notify
        this.Notify(new EventSet(this,'name',name,oldValue));
        return this;
    };


    /* CUSTOM UI ELEMENT */
    /**
     * @classdesc This is the base class for any real UiElement with a single 
     * HTML DOM element and no children. If only a basic HTML tag shall be transformed 
     * into a jsa element his class is completely sufficient. Just set params.elementType
     * to the tag type desired.
     * @class CustomUiElement
     * @extends UIElementA
     *
     * @param {dict} params=(see_below) - A dictionary of initialization parameters. Below for details.
     * @param {boolean} [createDom=true] - To be used for inheritance of jsa elements. If set to false the HTML DOM element will not be created, e.g. CreateDom() is not called.
     *
     * @comment CustomUiElement
     * @property {string} params.content='' Usually the innerHTML content of the HTML DOM element
     * @property {string} params.elementType='div' The tag type to be created.
     * @property {Array.<string>} params.style=[]] - An arry of CSS class names copied to the class property of DOM element, e.g. ['css-class1','css-class2']. 
     * @property {string} params.href=null - Compatibility attribute for elementType='a'. 
     * @property {function} params.onClickCallback=null - If this is not null, the function is registered for the elements HTML 'click' events. The function is called in the context of the element itself.
     * @property {function} params.onMouseOverCallback=null - If this is not null, the function is registered for the elements HTML 'mouseover' events. The function is called in the context of the element itself.
     * @property {function} params.onMouseOutCallback=null - If this is not null, the function is registered for the elements HTML 'mouseout' events. The function is called in the context of the element itself.
     *
     * @returns {this} Instance of the element itself to enable method chaining
     * 
     * @example
     * app = new jsa.Application({});
     * myClickCallback = function(evt) { 
     *   alert(this.content); 
     * };
     * myFirstJsaElement = new jsa.CustomUiElement({
     *   elementType:'div', 
     *   content:'Hello World!', 
     *   onClickCallback:myClickCallback 
     * });
     * app.AddChild(myFirstJsaElement);
     * myFirstJsaElement.Hide(); //Hide the newly created element the jsa-style way.
     * myFirstJsaElement.Show(); //Show the newly created element the jsa-style way.
     * // Clicking the element alerts 'Hello World!'
     */
    function CustomUiElement(params,createDom=true) {
        UIElementA.call(this);

        //params
        this.content = '';
        this.elementType = 'div';
        this.style = [];
        this.href = null; //only for <a> elements
        this.onClickCallback = null;
        this.onMouseOverCallback = null;
        this.onMouseOutCallback = null;

        //copy params
        CopyParams(this, params);

        //create DOM
        if(createDom) {
            this.CreateDom();
        }

        return this;
    };
    CustomUiElement.prototype = Object.create(UIElementA.prototype);

    /**
     * Creates the HTML DOM element. In general, CreateDom is called automatically by the constructor. 
     * Please see [UIElementA.CreateDom]{@link UIElementA#CreateDom} for the general explanation.
     * In this case it creates the DOM element, sets the content, and registers event listeners 
     * @returns {this} Instance of the element itself to enable method chaining
     * @method CustomUiElement.prototype.CreateDom
     */
    CustomUiElement.prototype.CreateDom = function() {
        this.domElement = CreateDomElementWithUniqueId(this.elementType,this.id,this.titleAttr);
        this.SetStyle(this.style);
        this.SetContent(this.content);

        if('a'==this.elementType && this.href) {
            this.domElement.href = this.href;
        }
        if(this.onClickCallback) {
            RedirectDomCallbackToUiElement(this.domElement,'click',this,this.onClickCallback);
        }
        if(this.onMouseOverCallback) {
            RedirectDomCallbackToUiElement(this.domElement,'mouseover',this,this.onMouseOverCallback);
        }
        if(this.onMouseOutCallback) {
            RedirectDomCallbackToUiElement(this.domElement,'mouseout',this,this.onMouseOutCallback);
        }

        if(this.hasTooltip) {
            RedirectDomCallbackToUiElement(this.domElement,'mouseover',this,this.TriggerTooltip);
            RedirectDomCallbackToUiElement(this.domElement,'mouseout',this,this.StopTooltip);
        }

        if(!this.startVisible) {
            this.Hide();
        }

        return this;
    };

    /**
     * Takes care of displaying the tooltip if the element has one. 
     * Used internally. No need to call it manually.
     * @param {MouseEvent} event - The HTML onmouseover event
     * @returns {this} Instance of the element itself to enable method chaining
     * @method CustomUiElement.prototype.TriggerTooltip
     */
    CustomUiElement.prototype.TriggerTooltip = function(event) {
        if(this.hasTooltip&&this.app) {
            let x = event.clientX;
            let y = event.clientY;
            this.app.TriggerTooltip(this,x,y);
        }
        return this;
    };

    /**
     * Takes care of stop displaying the tooltip if the element has one. 
     * Used internally. No need to call it manually.
     * @param {MouseEvent} event - The HTML onmouseover event
     * @returns {this} Instance of the element itself to enable method chaining
     * @method CustomUiElement.prototype.StopTooltip
     */
    CustomUiElement.prototype.StopTooltip = function(event) {
        if(this.app) {
            this.app.StopTooltip();
        }
        return this;
    };

    /**
     * Changes the content of the element during run-time, in general this the same as setting 
     * innerHTML, but vary depending on the class if this method is overwritten.
     * @param {string} content - The new content of the element. If necessary HTML code works also
     * @returns {this} Instance of the element itself to enable method chaining
     * @method CustomUiElement.prototype.SetContent
     * 
     * @fires [EventSet]{@link EventSet}(eventId= [EVENT.TYPES.SET_CONTENT]{@link EVENT}; propertyName = 'content')
     *
     * @example
     * // ... continues the CustomUiElement example
     * myFirstJsaElement.SetContent('This is the new content'); //-> new text appears visually
     */
    CustomUiElement.prototype.SetContent = function(content) {
        let oldContent = this.content;
        this.content = content;
        if(this.domElement) {
            this.domElement.innerHTML = content;
        }
        //notify observers
        this.Notify(new EventSet(this,'content',content,oldContent));
        return this;
    };

    /**
     * Changes CSS classes and, therefore, the appearance of the DOM element during run-time.
     * @param {Array.<string>} style - The CSS classes to be set, e.g. ['css-class1','css-class2'].
     * @returns {this} Instance of the element itself to enable method chaining
     * @method CustomUiElement.prototype.SetStyle
     * 
     * @fires [EventSet]{@link EventSet}(eventId= [EVENT.TYPES.SET_STYLE]{@link EVENT}; propertyName = 'style')
     *
     * @example
     * // ... continues the CustomUiElement example
     * myFirstJsaElement.SetStyle(['new-clicked-css-style']); //-> new style appears visually
     */
    CustomUiElement.prototype.SetStyle = function(style) {
        let oldValue = this.style;
        this.style = style;
        if(this.domElement) {
            this.domElement.setAttribute("class", "");
            ApplyStyles(style,this.domElement);
        }
        //notify observers
        this.Notify(new EventSet(this,'style',this.style,oldValue));
        return this;
    };

    /**
     * Changes the id attribute of the DOM element during run-time.
     * @param {string} id - The new ID.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method CustomUiElement.prototype.SetId
     * 
     * @fires [EventSet]{@link EventSet}(eventId= [EVENT.TYPES.SET_ID]{@link EVENT}; propertyName = 'id')
     *
     * @example
     * // ... continues the CustomUiElement example
     * myFirstJsaElement.SetId('my-first-jsa-element'); //-> new style appears visually
     */
    CustomUiElement.prototype.SetId = function(id) {
        let oldValue = this.id;
        this.id = id;
        if(this.domElement) {
            this.domElement.id = id;
        }
        //notify observers
        this.Notify(new EventSet(this,'id',this.id,oldValue));
        return this;
    };

    /**
     * Enables an element. Overridden to enable callbacks on this element.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method CustomUiElement.prototype.Enable
     * @override
     */
    CustomUiElement.prototype.Enable = function() {
        if(!this.isEnabled) {
            if(this.onClickCallback) {
                RedirectDomCallbackToUiElement(this.domElement,'click',this,this.onClickCallback);
            }
            if(this.onMouseOverCallback) {
                RedirectDomCallbackToUiElement(this.domElement,'mouseover',this,this.onMouseOverCallback);
            }
            if(this.onMouseOutCallback) {
                RedirectDomCallbackToUiElement(this.domElement,'mouseout',this,this.onMouseOutCallback);
            }
            UIElementA.prototype.Enable.call(this);
        }
        return this;
    }

    /**
     * Disables an element. Overridden to disable callbacks on this element.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method CustomUiElement.prototype.Disable
     * @override
     */
    CustomUiElement.prototype.Disable = function() {
        if(this.isEnabled) {
            RemoveRedirectDomCallbackFromUiElement(this.domElement,'click',this,this.onClickCallback);
            RemoveRedirectDomCallbackFromUiElement(this.domElement,'mouseover',this,this.onMouseOverCallback);
            RemoveRedirectDomCallbackFromUiElement(this.domElement,'mouseout',this,this.onMouseOutCallback);
            UIElementA.prototype.Disable.call(this);
        }
        return this;
    }

    //Overrides
    /**
     * Clean up the before the object is destroyed. Overrides UiElementA#Dissolve to remove any callbacks and tooltips.
     * @method CustomUiElement.prototype.Dissolve
     * @override
     */
    CustomUiElement.prototype.Dissolve = function() {
        RemoveRedirectDomCallbackFromUiElement(this.domElement,'click',this,this.onClickCallback);
        RemoveRedirectDomCallbackFromUiElement(this.domElement,'mouseover',this,this.onMouseOverCallback);
        RemoveRedirectDomCallbackFromUiElement(this.domElement,'mouseout',this,this.onMouseOutCallback);
        if(this.hasTooltip) {
            this.StopTooltip();
            RemoveRedirectDomCallbackFromUiElement(this.domElement,'mouseover',this,this.TriggerTooltip);
            RemoveRedirectDomCallbackFromUiElement(this.domElement,'mouseout',this,this.StopTooltip);
        }
        UIElementA.prototype.Dissolve.call(this);
    }


    /* CUSTOMCONTAINERA (abstract) */
    /**
     * @abstract
     * @class CustomContainerA
     * @classdesc The abstract base class for all jsa UI elements that can contain children, 
     * i.e. other UI elements can live inside this UI element. In comparison to normal UI elements,
     * UI container elements have usually no params.content, but the content is created by adding children
     * and can be dynamically modified during runtime by adding and removing further children.
     *
     * @comment UiContainerA
     * @property {dict} this.containerDomElement=empty_dict - _(readonly)_ The HTML DOM element that contains the children.
     * @property {Array} this.children=[]] - _(readonly)_ The array of jsa UI elements that are children of this container.
     * @extends CustomUiElement
     *
     * @returns {this} Instance of the element itself to enable method chaining
     * @constructor CustomContainerA
     * 
     * @example
     * app = new jsa.Application({});
     * myJsaContainer = new jsa.CustomContainer({}); //CustomContainer is an UiContainerA.
     * app.AddChild(myJsaContainer);
     * myJsaElement = new jsa.CustomUiElement({
     *   elementType:'div', 
     *   content:'Hello World!'
     * });
     * myJsaContainer.AddChild(myJsaElement); //adds the hello world div to the inner div tag.
     */
    function CustomContainerA(params,createDom=true) {
        CustomUiElement.call(this,params,false);


        //internals
        this.containerDomElement = {};
        this.children = [];
        this.redirectContainer = null; //the location for adding children. 

        if(createDom) {
            this.CreateDom();
        }
        return this;
    };

    CustomContainerA.prototype = Object.create(CustomUiElement.prototype);

    /**
     * Sets the a container where children shall be added. 
     * By default the container is the element itself. However, for 
     * complex UI elements this can be changed to make children appear in 
     * one of the sub compartments. On AddChild() the children will be added 
     * to the redirect container.
     * @param {CustomContainerA} container - The UI container which is new container. 
     * @returns {this} Instance of the element itself to enable method chaining
     * @method CustomContainerA.prototype.DefineRedirectContainer
     *
     */
    CustomContainerA.prototype.DefineRedirectContainer = function(container) {
        if(container != this.redirectContainer) {
            this.redirectContainer = container;
        }
        return this;
    };

    /**
     * Gets the default container were children shall be added. 
     * By default this is the element itself, e.g. this.
     * @returns {CustomContainerA} The container for children to be added.
     * @method CustomContainerA.prototype.GetRedirectContainer
     *
     */
    CustomContainerA.prototype.GetRedirectContainer = function() {
        return this.redirectContainer;
    };

    /**
     * Add another UI element as a child to this one. Depending on the implementation 
     * of the container object, the added object is usually shown immediately within
     * the container DOM element of the container UI element.
     * Will remove the child from any previous parent element before adding it.
     * @param {UIElementA} child - The child UI element to be added.
     * @param {bool} redirect=true - Whether the children of actual container element shall be returned instead of the own children.
     * See [DefineRedirectContainer]{@link CustomContainerA#DefineRedirectContainer} for details.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method CustomContainerA.prototype.AddChild
     *
     * @example
     * // ... continues the general UiContainerA example above
     * myJsaContainer.AddChild(myJsaElement);
     */
    CustomContainerA.prototype.AddChild = function(child,redirect=true) {
        if(child) {
            //make sure the child has not two parents
            if(child.parent) child.parent.RemoveChild(child,false);
            //add it to itself or the redirect container
            if(redirect&&this.redirectContainer) {
                this.redirectContainer.AddChild(child,true);
            } else {
                this.children.push(child);
                this.GetContainingDom(false).appendChild(child.GetDomElement());
                child.OnAdded(this,this.app);
                //notify observers
                this.Notify(new EventAdd(this,'children',child,this.children.length-1));
            }
        } else {
            throw new Error('Element could not be added as a child, because it was null or undefined');
        }
        return this;
    };

    /**
     * The same as [AddChild]{@link CustomContainerA#AddChild}, but lets you specify the position of 
     * child if there are already children in the container, i.e. the new child can be inserted before
     * already existing children.
     * Will remove the child from any previous parent element before adding it.
     * @param {UIElementA} child - The UI element object to be added.
     * @param {int} i - The index where the element is inserted. Use i=0 to add before the first element.
     * @param {bool} redirect=true - Whether the children of actual container element shall be returned instead of the own children.
     * See [DefineRedirectContainer]{@link CustomContainerA#DefineRedirectContainer} for details.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method CustomContainerA.prototype.AddChildAtIndex
     *
     * @example
     * // ... continues the general UiContainerA example above
     * myJsaContainer.AddChildAtIndex(myJsaElement,0); //add as first element
     */
    CustomContainerA.prototype.AddChildAtIndex = function(child,i,redirect=true) {
        //make sure the child has not two parents
        if(child.parent) child.parent.RemoveChild(child,false);
        //add it to itself or the redirect container
        if(redirect&&this.redirectContainer) {
            this.redirectContainer.AddChildAtIndex(child,i,true);
        } else {
            let index = -1; //is set later
            if(this.children.length==0 || i >= this.children.length) {
                this.children.push(child);
                this.GetContainingDom(false).appendChild(child.GetDomElement());
                index = this.children.length-1;
            } else if(i<=0) {
                this.children.unshift(child);//[uielement] + this.children;
                this.GetContainingDom(false).insertBefore(child.GetDomElement(),this.children[1].GetDomElement());
                index = 0;
            } else {
                this.children.splice(i,0,child);
                this.GetContainingDom(false).insertBefore(child.GetDomElement(),this.children[i+1].GetDomElement());
                index = i;
            }
            child.OnAdded(this,this.app);
            //notify observers
            this.Notify(new EventAdd(this,'children',child,index));
        }

        return this;
    }

    /**
     * Removes a UI element from the container. Usually this also removes the element
     * immediately from the screen.
     * @param {UIElementA} child - The UI element to be removed. If the element is no child of the container, nothing happens.
     * @param {bool} redirect=true - Whether the children of actual container element shall be returned instead of the own children.
     * See [DefineRedirectContainer]{@link CustomContainerA#DefineRedirectContainer} for details.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method CustomContainerA.prototype.RemoveChild
     *
     * @example
     * // ... continues the general UiContainerA example above
     * myJsaContainer.RemoveChild(myJsaElement);
     */
    CustomContainerA.prototype.RemoveChild = function(child,redirect=true) {
        if(redirect&&this.redirectContainer) {
            this.redirectContainer.RemoveChild(child,true);
        } else {
            this.GetContainingDom(false).removeChild(child.GetDomElement());
            this.children = ArrayRemove(this.children,child);
            child.OnRemoved();
            //notify observers
            this.Notify(new EventRemove(this,'children',child,-1)); //index has no meaning here
        }
        return this;
    };

    /**
     * Returns the all children of the container.
     * @param {bool} redirect=true - Whether the children of actual container element shall be returned instead of the own children.
     * See [DefineRedirectContainer]{@link CustomContainerA#DefineRedirectContainer} for details.
     * @returns {Array.<UIElementA>} The array of children
     * @method CustomContainerA.prototype.GetChildren()
     */
    CustomContainerA.prototype.GetChildren = function(redirect=true) {
        let children = null;
        if(redirect&&this.redirectContainer) {
            children = this.redirectContainer.GetChildren(true);
        } else {
            children = this.children.slice(); //return a copy to prevent modification
        }
        return children;
    };

    /**
     * This function returns the HTML DOM element, which contains the DOM
     * elements of the children. This can return the same value as 
     * [UiElementA.GetDomElement()]{@link UIElementA@GetDomElement}, but
     * must not be. This depends on the container implementation.
     * @param {bool} redirect=true - if the request shall be forwarded to a child UI element in case it is a complex UI element.
     * @method CustomContainerA.prototype.GetContainingDom
     * @returns {HTML_DOM_ELEMENT} The original HTML DOM element that contains the children. This can be used in any other JS framework.
     *
     * @example
     * // ... continues the general UiContainerA example above
     * myJsaContainer.GetDomElement().style.color = 'red'; //change the text color
     */
    CustomContainerA.prototype.GetContainingDom = function(redirect=true) {
        let containerDom = null;
        if(redirect&&this.redirectContainer) {
            containerDom = this.redirectContainer.GetContainingDom(true);
        } else {
            containerDom = this.containerDomElement;
        }
        return containerDom;
    };

    /**
     * Overwrites [UiElementA.Dissolve]{@link UIElementA#Dissolve} in order 
     * to automatically dissolve all children of the container.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method CustomContainerA.prototype.Dissolve
     *
     */
    CustomContainerA.prototype.Dissolve = function() {
        this.children.forEach( function(child) {
            child.Dissolve();
        })
        CustomUiElement.prototype.Dissolve.call(this);
        return this;
    };

    /**
     * Gets a specific child by search all children for a specific
     * id. If the child is not included null is returned.
     * @param {sting} id - The ID value of child to be returned, i.e. params.id.
     * @returns {UIElementA} The child with the 
     * @method CustomContainerA.prototype.GetChildById
     *
     * @example
     * app = new jsa.Application({});
     * myJsaContainer = new jsa.CustomContainer({}); //CustomContainer is an UiContainerA.
     * app.AddChild(myJsaContainer);
     * myJsaElement = new jsa.CustomUiElement({
     *   id:'my-element234',
     *   elementType:'div', 
     *   content:'Hello World!'
     * });
     * myJsaContainer.AddChild(myJsaElement); 
     * myJsaContainer.GetChildById('my-element123'); // -> returns null
     * myJsaContainer.GetChildById('my-element234'); // -> returns myJsaElement
     */
    CustomContainerA.prototype.GetChildById = function(id) {
        return this.children.find(function(child) {
            return (child.id==id);
        })
    }

    //@Override
    /**
     * Overrides [UiElementA.OnAdded()]{@link UiElementA#OnAdded} in order to recursively
     * propagate the Application of this element to all children.
     * @param container {UIElementA} - The new container of this element.
     * @param app {Application} - The application object of the container, i.e. container.GetApp(). If the container is not part of an application, this is null.
     * @method CustomContainerA.prototype.OnAdded
     *
     */
    CustomContainerA.prototype.OnAdded = function(container,app) {
        UIElementA.prototype.OnAdded.call(this,container,app);
        //make sure the app is also propagated to all contained children
        for(let i=0;i<this.children.length;i++) {
            let child = this.children[i];
            child.OnAdded(this,app);
        }
    };


    /* CUSTOM CONTAINER */
    /**
     * @class CustomContainer
     * @classdesc This is the base class for all UI containers that have a minimum of two 
     * DOM elements. One for the element itself, as well as one, which contains the children.
     * A minimal container looks ass a DOM structure as follows:
     * 
     *      -------------------
     *     | element DOM       |
     *     |  ---------------  | 
     *     | | container DOM | |
     *     | |               | |
     *     | |             <------- Children go here
     *     | |               | |
     *     |  ---------------  |
     *      -------------------
     *  
     * See [CustomFlatContainer]{@link CustomFlatContainer} for a container based on a single 
     * DOM element.
     *
     * @param {dict} params=(see_below) - A dictionary of initialization parameters. Below for details.
     * @param {boolean} [createDom=true] - To be used for inheritance of jsa elements. If set to false the HTML DOM element will not be created, e.g. CreateDom() is not called.
     *
     * @comment CustomContainer parameters
     * @property {string} params.containerElementType='div' - >property description<
     * @property {Array.<string>} params.containerStyle=[]] - >property description<
     * @returns {this} Instance of the element itself to enable method chaining
     *
     * @constructor CustomContainer
     * @extends CustomContainerA
     * 
     * @example
     * app = new jsa.Application({});
     * myJsaContainer = new jsa.CustomContainer({}); //creates two nested div tags.
     * app.AddChild(myJsaContainer);
     * myJsaElement = new jsa.CustomUiElement({
     *   elementType:'div', 
     *   content:'Hello World!'
     * });
     * myJsaContainer.AddChild(myJsaElement); //adds the hello world div to the inner div tag.
     */
    function CustomContainer(params,createDom=true) {
        CustomContainerA.call(this,params,false);

        //params
        this.containerElementType = 'div';
        this.containerStyle = [];

        //copy params
        CopyParams(this, params);

        //create DOM
        if(createDom) {
            this.CreateDom();
        }

        return this;
    };

    CustomContainer.prototype = Object.create(CustomContainerA.prototype);

    /**
     * Creates the HTML DOM element. In general, CreateDom is called automatically by the constructor. 
     * Please see [UIElementA.CreateDom]{@link UIElementA#CreateDom} for the general explanation.
     * In this case it creates the DOM element, and the container DOM element.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method CustomContainer.prototype.CreateDom
     *
     */
    CustomContainer.prototype.CreateDom = function() {
        CustomUiElement.prototype.CreateDom.call(this);
        this.domElement.innerHTML = ''; //remove what was set by CustomUiElement
        
        this.containerDomElement = CreateDomElementWithUniqueId(this.containerElementType,this.id+'-container');
        this.SetContainerStyles(this.containerStyle);
        this.SetContent(this.content);
        this.domElement.appendChild(this.containerDomElement);

        return this;
    };

    //@ Override
    /**
     * Overrides [CustomUiElement.SetContent(...)]{@link CustomUiElement#SetContent} in order
     * to set the content to the container DOM element instead of the outer
     * DOM element.
     * @param {string} content - The content string, can also be HTML code.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method CustomContainer.prototype.SetContent
     * 
     * @example
     * //... continues the general CustomContainer example above
     * myJsaContainer.SetContent('This appears in the inner div'); 
     */
    CustomContainer.prototype.SetContent = function(content) {
        this.content = content;
        if(this.domElement) {
            this.containerDomElement.innerHTML = content;
        }
        return this;
    };

    /**
     * Changes CSS classes and, therefore, the appearance of the container DOM element during run-time.
     * Otherwise this behaves similar to [CustomUiElement.SetStyle(...)]{@link CustomUiElement#SetStyle}.
     * @param {Array.<string>} styles - The CSS classes to be set, e.g. ['css-class1','css-class2'].
     * @returns {this} Instance of the element itself to enable method chaining
     * @method CustomContainer.prototype.SetContainerStyles
     *
     * @example
     * //... continues the general CustomContainer example above
     * myJsaContainer.SetContainerStyles(['my-container-style']); 
     */
    CustomContainer.prototype.SetContainerStyles = function(styles) {
        if(this.containerDomElement) {
            ApplyStyles(styles,this.containerDomElement);
        }
        return this;
    };


    /* CUSTOM FLAT CONTAINER */
    /**
     * @class CustomFlatContainer
     * @classdesc This is the base class for all UI containers that have only a single 
     * DOM elements. A flat container's DOM structure looks as follows:
     * 
     *      -------------------
     *     | element DOM       |
     *     | and               |
     *     | container DOM     |
     *     | are the same      |
     *     |               <------- Children go here
     *     |                   |
     *     |                   |
     *      -------------------
     * 
     * See [CustomContainer]{@link CustomContainer} for a container with individual inner DOM elements.
     *
     * @param {dict} params=(see_below) - A dictionary of initialization parameters. Below for details.
     * @param {boolean} [createDom=true] - To be used for inheritance of jsa elements. If set to false the HTML DOM element will not be created, e.g. CreateDom() is not called.
     *
     * @returns {this} Instance of the element itself to enable method chaining
     * @constructor CustomFlatContainer
     * @extends CustomUiElement
     * 
     * @example
     * //Use CustomFlatContainer to create a unsorted list
     * app = new jsa.Application({});
     * myJsaContainer = new jsa.CustomFlatContainer({
     *   elementType:'ul'
     * }); 
     * app.AddChild(myJsaContainer);
     * myJsaElement = new jsa.CustomUiElement({
     *   elementType:'li', 
     *   content:'Bullet point 1'
     * });
     * myJsaContainer.AddChild(myJsaElement); //adds the li tag to the ul tag.
     */
    function CustomFlatContainer(params,createDom=true) {
        CustomContainerA.call(this,params,false);
        //params

        //copy params
        CopyParams(this, params);

        //create DOM
        if(createDom) {
            this.CreateDom();
        }
        return this;
    };

    CustomFlatContainer.prototype = Object.create(CustomContainerA.prototype);

    /**
     * Creates the HTML DOM element. In general, CreateDom is called automatically by the constructor. 
     * Please see [UIElementA.CreateDom]{@link UIElementA#CreateDom} for the general explanation.
     * In this case it creates the DOM element. 
     * @returns {this} Instance of the element itself to enable method chaining
     * @method CustomFlatContainer.prototype.CreateDom
     */
    CustomFlatContainer.prototype.CreateDom = function() {
        CustomUiElement.prototype.CreateDom.call(this);

        this.containerDomElement = this.domElement;
        this.containerDomElement.innerHTML = this.content;

        return this;
    };


    /* BUTTON */
    /**
     * @class Button
     * @classdesc A standard button intended to receive the users click to trigger some action.
     * 
     *      ----------
     *     |  Button  | <-- click me
     *      ----------
     *
     * @param {dict} params=(see_below) - A dictionary of initialization parameters. Below for details.
     * @param {boolean} [createDom=true] - To be used for inheritance of jsa elements. If set to false the HTML DOM element will not be created, e.g. CreateDom() is not called.
     *
     * @comment Button parameters
     * @property {string} params.elementType='div' - The tag element to be used for the button. By default this is div, but can also be button or a.
     * @property {Array.<string>} params.style=['jsa-button']] - The CSS styles for the outer DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     *
     * @returns {this} Instance of the element itself to enable method chaining
     * @constructor Button
     * @extends CustomUiElement
     * 
     * @example
     * app = new jsa.Application({});
     * myButton = new jsa.Button({
     *   content:'Click Me', 
     *   elementType:'button', //use the default HTML button
     *   onClickCallback:function(evt) {
     *     alert('Button '+this.content+' was clicked.')
     *   }
     * });
     * app.AddChild(myButton); 
     */
    function Button(params={},createDom=true) {
        CustomUiElement.call(this,params,false);
    
        //members
        this.elementType = 'div';
        this.style = ['jsa-button'];

        //copy params
        CopyParams(this,params);

        if(createDom) {
            this.CreateDom();
        }
    
        return this;
    };
    
    Button.prototype = Object.create(CustomUiElement.prototype);

    /**
     * Creates the HTML DOM element. In general, CreateDom is called automatically by the constructor. 
     * Please see [UIElementA.CreateDom]{@link UIElementA#CreateDom} for the general explanation.
     * @method Button.prototype.CreateDom
     *
     */
    Button.prototype.CreateDom = function() {
        CustomUiElement.prototype.CreateDom.call(this);
        if(!this.startEnabled) {
            this.Disable();
        }
    };

    //@Override
    /**
     * Overwrites the default enable behavior in order to work correctly with 
     * 'button' tag style buttons. 
     * @returns {this} Instance of the element itself to enable method chaining
     * @method Button.prototype.Enable
     * @override
     *
     * @example
     * // ... continuing the general Button example
     * myButton.Enable(); //Button can be clicked and looks enabled
     */
    Button.prototype.Enable = function() {
        if(!this.isEnabled) {
            this.GetDomElement().classList.remove('jsa-button-disabled');
            this.GetDomElement().removeAttribute('disabled');
            CustomUiElement.prototype.Enable.call(this);
        }
        return this;
    };

    //@Override

    /**
     * Overwrites the default disable behavior in order to work correctly with 
     * 'button' tag style buttons. The passive look works only for button tags.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method Button.prototype.Disable
     *
     * @example
     * // ... continuing the general Button example
     * myButton.Disable(); //Button can not be clicked any more and looks disabled
     */
    Button.prototype.Disable = function() {
        if(this.isEnabled) {
            this.GetDomElement().classList.add('jsa-button-disabled');
            this.GetDomElement().setAttribute('disabled',true);
            CustomUiElement.prototype.Disable.call(this);
        }
        return this;
    }; 


    /* ICON */
    /**
     * @class Icon
     * @classdesc An icon is a small image. It is usually used to make an text entry recognizable.
     * 
     *      -------
     *     | image |
     *      -------
     * 
     * @param {dict} params=(see_below) - A dictionary of initialization parameters. Below for details.
     * @param {boolean} [createDom=true] - To be used for inheritance of jsa elements. If set to false the HTML DOM element will not be created, e.g. CreateDom() is not called.
     *
     * @comment Icon parameters
     * @property {string} params.icon='jsa-icon-jsa' - A path to the icon file or the name of a CSS style, e.g. 'img/icon.svg' or 'jsa-icon-close'.
     * @property {Array.<string>} params.style=['jsa-icon']] - The CSS styles for the outer DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     *
     * @returns {this} Instance of the element itself to enable method chaining
     * @constructor Icon
     * @extends CustomFlatContainer
     * 
     * @example
     * app = new jsa.Application({});
     * // Create an icon from a file 
     * myIcon1 = new jsa.Icon({
     *   icon:'img/close.svg', 
     *   onClickCallback:function(evt) {
     *     alert('Icon '+this.content+' was clicked.')
     *   }
     * });
     * app.AddChild(myIcon1); 
     * // Create an icon from a style (its background image)
     * myIcon2 = new jsa.Icon({
     *   icon:'jsa-icon-close', 
     *   onClickCallback:function(evt) {
     *     alert('Icon '+this.content+' was clicked.')
     *   }
     * });
     * app.AddChild(myIcon2); 
     */
    function Icon(params,createDom=true) {
        CustomFlatContainer.call(this,params,false);
        this.elementType = 'div';
        this.style = ['jsa-icon'];
        this.icon = 'jsa-icon-jsa'; //alternatively the style can be used as a icon via background image.

        CopyParams(this,params);

        if(createDom) {
            this.CreateDom();
        }
    };
    Icon.prototype = Object.create(CustomFlatContainer.prototype);

    /**
     * Creates the HTML DOM element. In general, CreateDom is called automatically by the constructor. 
     * Please see [UIElementA.CreateDom]{@link UIElementA#CreateDom} for the general explanation.
     * @method TextCtrl.prototype.CreateDom
     * @override
     */
    Icon.prototype.CreateDom = function() {
        CustomFlatContainer.prototype.CreateDom.call(this);
        if(this.icon) {
            this.SetIcon(this.icon);
        }
        return this;
    };

    /**
     * Sets the icon dynamically.
     * @param {string} icon - The path to the new icon.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method Icon.prototype.SetIcon
     * 
     * @fires [EventSet]{@link EventSet}(eventId= [EVENT.TYPES.SET_ICON]{@link EVENT}; propertyName = 'icon')
     */
    Icon.prototype.SetIcon = function(icon) {
        let oldValue = this.icon;
        if(this.IsIconFile(icon)) {
            this.SetContent('<img id="'+this.id+'-img" src="'+icon+'" />');
        } else {
            this.SetContent('');
            this.GetDomElement().classList.remove(oldValue);
            this.GetDomElement().classList.add(icon);
        }
        this.icon = icon;
        //notify observers
        this.Notify(new EventSet(this,'icon',this.icon,oldValue));
        return this;
    };

    /**
     * Figures out if an icon string given is a file or a CSS style. Used internally.
     * @param {string} icon - The icon identifier.
     * @returns {boolean} True = icon is a file, false it is not a file string.
     * @method Icon.prototype.IsIconFile
     * 
     * @fires [EventSet]{@link EventSet}(eventId= [EVENT.TYPES.SET_ICON]{@link EVENT}; propertyName = 'icon')
     */
    Icon.prototype.IsIconFile = function(icon) {
        if(!icon) {
            return false;
        } else if (icon.match(/\.\w{3,4}$/i)) {
            return true;
        }
        return false;
    };


    /* LABEL */
    /**
     * @class Label
     * @classdesc A label is a one line text that can have optionally an icon and pre and post controls.
     * 
     *      -----------------------------------------------------------
     *     |  -------------------------------------------------------  |
     *     | | pre: Icon (optional) | Label text  | post: (optional) | |
     *     |  -------------------------------------------------------  |
     *      -----------------------------------------------------------
     * 
     * @param {dict} params=(see_below) - A dictionary of initialization parameters. Below for details.
     * @param {boolean} [createDom=true] - To be used for inheritance of jsa elements. If set to false the HTML DOM element will not be created, e.g. CreateDom() is not called.
     *
     * @comment Label parameters
     * @property {string} params.icon=null - A path to the icon file for the icon. Alternatively the icon can be set by using iconStyle. 
     * If null, no icon is shown.
     * @property {string} params.hAlign='left' - The horizontal alignment of the label. Can be left, right or center.
     * @property {string} params.vAlign='middle' - The vertical alignment of the label. Can be top, bottom or middle.
     * @property {Array.<string>} params.style=['jsa-label']] - The CSS styles for the outer DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {Array.<string>} params.containerStyle=['jsa-label-container']] - The CSS styles for the inner DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {Array.<string>} params.iconStyle=['jsa-icon-s','jsa-inline-pad-right']] - The CSS styles for the icon DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {Array.<string>} params.textStyle=['jsa-label-text']] - The CSS styles for the text DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {Array.<string>} params.containerStyle=['jsa-label-container']] - The CSS styles for the inner DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @comment subelements
     * @property {UIElementA} this.subelements.text - (readonly) The UI element of the text area (Children are added here).
     * @property {UIElementA} this.subelements.pre - (readonly) The UI element of the pre area, where the icon is added.
     * @property {UIElementA} this.subelements.post - (readonly) The UI element of the post area.
     * @property {UIElementA} this.subelements.icon - (readonly) The UI element of the icon if icon is != null.
     *
     * @returns {this} Instance of the element itself to enable method chaining
     * @constructor Label
     * @extends CustomFlatContainer
     * @extends UIElementWithIconA
     * 
     * @example
     * app = new jsa.Application({});
     * myLabel = new jsa.Label({
     *   content: 'This is a label',
     *   icon: 'img/close.svg
     *   }
     * });
     * app.AddChild(myLabel); 
     */
    function Label(params,createDom=true) {
        CustomContainer.call(this,params,false);
        UIElementWithIconA.call(this);

        this.style = ['jsa-label'];
        this.containerStyle = ['jsa-label-container'];
        this.hAlign = 'left';
        this.vAlign = 'middle';
        this.iconStyle = ['jsa-icon','jsa-icon-s','jsa-inline-pad-right'];
        this.textStyle = ['jsa-label-text'];

        CopyParams(this,params);

        //internals
        this.subelements = this.subelements || {}; //initialize if not existing
        this.subelements.text = null;
        this.subelements.pre = null;
        this.subelements.post = null;
        this.subelements.icon = null;

        if(createDom) {
            this.CreateDom();
        }
        return this;
    };
    Label.prototype = Object.create(CustomContainer.prototype);
    Mixin(Label,UIElementWithIconA);

    /**
     * Creates the HTML DOM element. In general, CreateDom is called automatically by the constructor. 
     * Please see [UIElementA.CreateDom]{@link UIElementA#CreateDom} for the general explanation.
     * @method TextCtrl.prototype.CreateDom
     * @override
     */
    Label.prototype.CreateDom = function() {
        switch(this.hAlign) {
            case 'left': this.containerStyle.push('jsa-label-h-left'); break;
            case 'right': this.containerStyle.push('jsa-label-h-left'); break;
            case 'center': this.containerStyle.push('jsa-label-h-center'); break;
            default: throw new Error('Unknown label orientation: '+ this.hAlign);
        }
        switch(this.vAlign) {
            case 'top': this.containerStyle.push('jsa-label-v-top'); break;
            case 'bottom': this.containerStyle.push('jsa-label-v-bottom'); break;
            case 'middle': this.containerStyle.push('jsa-label-v-middle'); break;
            default: throw new Error('Unknown label orientation: '+ this.hAlign);
        }
        let content = this.content; 
        this.content = '';
        CustomContainer.prototype.CreateDom.call(this);

        this.subelements.pre = new CustomFlatContainer({
            id: this.id+'-pre',
            style: ['jsa-label-pre']
        });
        this.content = content;
        this.AddChild(this.subelements.pre);
        //add an icon if desired
        if(this.icon) {
            this.subelements.icon = new Icon({
                id: this.id+'-icon',
                style: this.iconStyle,
                icon: this.icon
            });
            this.subelements.pre.AddChild(this.subelements.icon);
        }
        
        this.subelements.text = new CustomFlatContainer({
            id: this.id+'-text',
            style: this.textStyle,
            content: content
        });
        this.AddChild(this.subelements.text);

        this.subelements.post = new CustomFlatContainer({
            id: this.id+'-post',
            style: ['jsa-label-post']
        });
        this.AddChild(this.subelements.post);

        this.DefineRedirectContainer(this.subelements.text);
        this.DefineIconContainer(this.subelements.icon,'SetIcon');

        return this;
    };

    //Override
    /**
     * Sets the content of the label dynamically.
     * @param {string} content - The new content
     * @returns {this} Instance of the element itself to enable method chaining
     * @method Label.prototype.SetContent
     * 
     * @fires [EventSet]{@link EventSet}(eventId= [EVENT.TYPES.SET_ICON]{@link EVENT}; propertyName = 'content')
     */
    Label.prototype.SetContent = function(content) {
        let oldValue = this.content;
        if(this.subelements.text) {
            this.subelements.text.SetContent(content);
        }
        this.content = content;
        //notify
        this.Notify(new EventSet(this,'content',this.content,oldValue));
        return this;
    };

    //@override
    /**
     * Returns the tooltip composed of the label content and the this.tooltip
     * @returns {string} Tooltip text.
     * @method Label.prototype.GetTooltip
     * @override
     */
    Label.prototype.GetTooltip = function() {
        let tooltip = this.content;
        if(this.tooltip) tooltip+=': '+this.tooltip;
        return tooltip;
    };


    /* TEXTCTRL */
    /**
     * @class TextCtrl
     * @classdesc A text control wraps an HTML input field as a jsa UiElement 
     * with additional features such as transfer functions, error indicator,
     * and callbacks.
     * 
     *      -----------------------------
     *     |  -------------------------  |
     *     | | Input|________________  |<-- edit me
     *     |  -------------------------  |
     *      -----------------------------
     * 
     * @param {dict} params=(see_below) - A dictionary of initialization parameters. Below for details.
     * @param {boolean} [createDom=true] - To be used for inheritance of jsa elements. If set to false the HTML DOM element will not be created, e.g. CreateDom() is not called.
     *
     * @comment TextCtrl parameters
     * @property {string} params.value='' - The initial text that shall appear in the box 
     * @property {boolean} params.readonly=false - Whether the text control shall be editable or not
     * @property {string} params.placeholder='' - A placeholder texted. This text is shown if the control is empty, but it is not its value.
     * @property {string} params.elementType='div' - The elementType of the outer DOM element. Don not change if you are not knowing what you do.
     * @property {Array.<string>} params.style=['jsa-text-ctrl']] - The CSS styles for the outer DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {Array.<string>} params.ctrlStyle=['jsa-text-ctrl-input']] - The CSS styles for the input DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {Array.<string>} params.errorIndicatorStyle=['jsa-text-ctrl-error-indication']] - The CSS styles error indication DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {function} params.onChangeCallback - This function is called if the value was changed by the user. Default:
     *     function(event) {};
     * @property {function} params.inputTransferFunction - This function is called if SetValue is 
     * used to convert between an arbitrary value format and the text value of the input field. 
     * It must return a string. The default is:
     * 
     *     function(valueStr) {
     *       let  value = valueStr; 
     *       return value;
     *     };
     * 
     * @property {function} params.outputTransferFunction - This function is called if SetValue is 
     * used to convert between an arbitrary value format and the text value of the input field. 
     * It must return the data type desired. The default is:
     * 
     *     function(valueStr) {
     *       let  value = valueStr; 
     *       return value;
     *     };
     * 
     * @property {function} params.validateFunction - On every value change this function is called to see 
     * if the value is ok. If not, the error indication becomes visible. In case the value is valid, the 
     * function must return true. In case the value is invalid it shall terminate with throw new Error('
     * The message to be displayed.'). The default is:
     * 
     *     function(valueStr) {
     *       return true;
     *     };
     * 
     *
     * @returns {this} Instance of the element itself to enable method chaining
     * @constructor TextCtrl
     * @extends CustomUiElement
     * 
     * @example
     * app = new jsa.Application({});
     * myTextCtrl = new jsa.TextCtrl({
     *   placeholder:'Enter your favorite number', 
     *   validateFunction:function(valueStr) {
     *     let isNumber = valueStr.match(/[\d]+/g);
     *     if(!isNumber || !isNumber.includes(valueStr)) {
     *       throw new Error(valueStr+" is not a number.");
     *     };
     *     return true;
     *   }
     * });
     * app.AddChild(myTextCtrl); 
     * // Text Ctrl will complain on any non-number entry
     */
    function TextCtrl(params={},createDom=true) {
        CustomUiElement.call(this,params,false);
    
        //members
        this.value = '';
        this.readonly = false;
        this.placeholder = '';
        this.elementType = 'div';
        this.style = ['jsa-text-ctrl'];
        this.ctrlStyle = ['jsa-text-ctrl-input'];
        this.errorIndicatorStyle = ['jsa-text-ctrl-error-indication'];
        this.onChangeCallback = function(event) {};
        this.onInputCallback = function(event) {};
        this.inputTransferFunction = function(value) {var valueStr = value?value:''; return valueStr;};
        this.outputTransferFunction = function(valueStr) {var value = valueStr; return value;};
        this.validateFunction = function(valueStr) {return true;}; //Shall throw an Error if validation fails
    
        //copy params
        CopyParams(this,params)
    
        if(createDom) {
            this.CreateDom();
        }
    
        return this;
    };
    
    TextCtrl.prototype = Object.create(CustomUiElement.prototype);

    /**
     * Creates the HTML DOM element. In general, CreateDom is called automatically by the constructor. 
     * Please see [UIElementA.CreateDom]{@link UIElementA#CreateDom} for the general explanation.
     * @method TextCtrl.prototype.CreateDom
     */
    TextCtrl.prototype.CreateDom = function() {
        CustomUiElement.prototype.CreateDom.call(this);
    
        this.input = document.createElement('input');
        ApplyStyles(this.ctrlStyle,this.input)
        if(this.readonly) {
            this.input.readOnly = true;
        }
        this.input.placeholder = this.placeholder;
        this.domElement.appendChild(this.input);

        this.errorIndicator = document.createElement('small');
        ApplyStyles(this.errorIndicatorStyle,this.errorIndicator)
        this.domElement.appendChild(this.errorIndicator);
        
        this.SetValue(this.value);
    
        this.input.data = this;
        if(this.onChangeCallback) {
            RedirectDomCallbackToUiElement(this.input,'change',this,this.onChangeCallback);
        }

        if(this.onInputCallback) {
            RedirectDomCallbackToUiElement(this.input,'input',this,this.onInputCallback);
        }

        if(!this.startEnabled) {
            this.Disable();
        }

        return this;
    };

    /**
     * Returns the value related to the string that is within the input field.
     * The string is converted to the value with the output transfer function.
     * Before the value is returned it is validated. If validation fails, get value 
     * will not return.
     * @returns {(defined_by_outputTransferFunction)} The current value of the text control converted from the string to the user value using the outputTranferFunction.
     * @method TextCtrl.prototype.GetValue
     *
     * @example
     * //... continuing the general TextCtrl example
     * let val = myTextCtrl.GetValue(); //returns only if the value is valid.
     */
    TextCtrl.prototype.GetValue = function() {
        let  valueStr = this.input.value;
        let  value = this.outputTransferFunction(valueStr);
        return value;
    };

    /**
     * Returns the the string that is within the input field without any processing.
     * @returns {string} The raw value of the input field.
     * @method TextCtrl.prototype.GetRawValue
     */
    TextCtrl.prototype.GetRawValue = function() {
        let  valueStr = this.input.value;
        return valueStr;
    };

    /**
     * Sets a new value to the TextCtrl. This value is shown as a string and 
     * can afterwards be changed by the user, if the control is not readonly.
     * @param {(defined_by_inputTransferFunction)} value - The value that shall be represented in the TextCtrl. It is converted to a string using the inputTransferFunction.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method TextCtrl.prototype.SetValue
     *
     * @example
     * //... continuing the general TextCtrl example
     * myTextCtrl.SetValue(1234); //-> TextCtrl shows '1234'
     */
    TextCtrl.prototype.SetValue = function(value) {
        let  valueStr =  this.inputTransferFunction(value);
        this.input.value = valueStr;
        return this;
    };

    /**
     * Sets the string that is within the input field without any processing.
     * @param {string} valueStr - The string to the inserted in the field.
     * @param {boolean} notify - If true, an on change event will be caused.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method TextCtrl.prototype.SetRawValue
     */
    TextCtrl.prototype.SetRawValue = function(valueStr,notify=false) {
        this.input.value = valueStr;
        if(notify) {
            this.input.dispatchEvent(new Event('change', { 'bubbles': true })); /* Event is the JS event not jsa */
        }
        return this;
    };

    /**
     * Set the TextCtrl to readonly during runtime.
     * @param {bool} readonly - True means control becomes readonly. False means the control becomes editable.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method TextCtrl.prototype.SetReadonly
     *
     * @example
     * //... continuing the general TextCtrl example
     * myTextCtrl.SetReadonly(true); //-> TextCtrl becomes passive
     * myTextCtrl.SetReadonly(false); //-> TextCtrl becomes editable
     */
    TextCtrl.prototype.SetReadonly = function(readonly) {
        if(this.readonly!=readonly) {
            this.input.readOnly = readonly;
            this.readonly = readonly;
        }
        return this;
    };

    /**
     * Manually triggers the validation of the TextCtrl. The current string value is 
     * evaluated by the validateFunction. If validation fails, the error indication
     * is shown.
     * @returns {boolean} True if the value string is valid and false if not.
     * @method TextCtrl.prototype.Validate
     *
     * @example
     * //... continuing the general TextCtrl example
     * myTextCtrl.SetValue('abc'); 
     * myTextCtrl.Validate(); // -> false 
     * myTextCtrl.SetValue('1234'); 
     * myTextCtrl.Validate(); // -> true 
     * // Hint: Usually the inputTransferFunction should be chosen such
     * // that setting and invalid value should not be possible.
     */
    TextCtrl.prototype.Validate = function() {
        this.errorIndicator.innerHTML = ''; //delete any previous error message
        let  valid = true;
        if(this)
        try{
            let  valueStr = this.input.value;
            if(this.validateFunction) {
                valid = this.validateFunction(valueStr);
            }
        }catch(e) {
            valid = false;
            this.errorIndicator.innerHTML = e.toString();
        }
        return valid;
    };
    
    /**
     * Enables the ctrl.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method TextCtrl.prototype.Enable
     * @override
     */
    TextCtrl.prototype.Enable = function() {
        if(!this.isEnabled) {
            this.input.removeAttribute('disabled');
            CustomUiElement.prototype.Enable.call(this);
        }
        return this;
    };

     /**
     * Disables the ctrl.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method TextCtrl.prototype.Disable
     * @override
     */
    TextCtrl.prototype.Disable = function() {
        if(this.isEnabled) {
            this.input.setAttribute('disabled',true);
            CustomUiElement.prototype.Disable.call(this);
        }
        return this;
    };


    /* TEXTAREACTRL */
    /**
     * @class TextareaCtrl
     * @classdesc A text control wraps an HTML textarea field as a jsa UiElement 
     * with additional features such as transfer functions, error indicator,
     * and callbacks.
     * 
     *      -----------------------------
     *     |  -------------------------  |
     *     | | Textarea                |<-- edit me
     *     |  -------------------------  |
     *      -----------------------------
     * 
     * @param {dict} params=(see_below) - A dictionary of initialization parameters. Below for details.
     * @param {boolean} [createDom=true] - To be used for inheritance of jsa elements. If set to false the HTML DOM element will not be created, e.g. CreateDom() is not called.
     *
     * @comment TextCtrl parameters
     * @property {Array.<string>} params.style=['jsa-textarea-ctrl']] - The CSS styles for the outer DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {Array.<string>} params.ctrlStyle=['jsa-textarea-ctrl-input']] - The CSS styles for the input DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {Array.<string>} params.errorIndicatorStyle=['jsa-textarea-ctrl-error-indication']] - The CSS styles error indication DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * 
     *
     * @returns {this} Instance of the element itself to enable method chaining
     * @constructor TextareaCtrl
     * @extends TextCtrl
     * 
     * @example
     * app = new jsa.Application({});
     * myTextCtrl = new jsa.TextareaCtrl({
     *   placeholder:'Enter your favorite poetry'
     * });
     * app.AddChild(myTextCtrl); 
     */
    function TextareaCtrl(params={},createDom=true) {
        TextCtrl.call(this,params,false);
    
        //members
        this.style = ['jsa-textarea-ctrl'];
        this.ctrlStyle = ['jsa-textarea-ctrl-input'];
        this.errorIndicatorStyle = ['jsa-text-ctrl-error-indication'];
    
        //copy params
        CopyParams(this,params)
    
        if(createDom) {
            this.CreateDom();
        }
    
        return this;
    };
    
    TextareaCtrl.prototype = Object.create(TextCtrl.prototype);

    /**
     * Creates the HTML DOM element. In general, CreateDom is called automatically by the constructor. 
     * Please see [UIElementA.CreateDom]{@link UIElementA#CreateDom} for the general explanation.
     * @method TextCtrl.prototype.CreateDom
     */
    TextareaCtrl.prototype.CreateDom = function() {
        CustomUiElement.prototype.CreateDom.call(this);
    
        this.input = document.createElement('textarea');
        ApplyStyles(this.ctrlStyle,this.input)
        if(this.readonly) {
            this.input.readOnly = true;
        }
        
        this.input.placeholder = this.placeholder;
        this.domElement.appendChild(this.input);

        this.errorIndicator = document.createElement('small');
        ApplyStyles(this.errorIndicatorStyle,this.errorIndicator)
        this.domElement.appendChild(this.errorIndicator);
        
        this.SetValue(this.value);
    
        this.input.data = this;
        if(this.onChangeCallback) {
            RedirectDomCallbackToUiElement(this.input,'change',this,this.onChangeCallback);
        }

        if(this.onInputCallback) {
            RedirectDomCallbackToUiElement(this.input,'input',this,this.onInputCallback);
        }

        if(!this.startEnabled) {
            this.Disable();
        }

        return this;
    };


    /* CHECKBOX CTRL */
    /**
     * @class CheckboxCtrl
     * @classdesc A checkbox control combines a checkbox and a label. 
     * The user makes his input by adding or removing a check mark.
     * Within a group of checkboxes several can be checked.
     * 
     *                        --------------------------
     *                       |  ---                     |
     *   click to toggle --> | | x | CheckBoxCtrl       |
     *                       |  ---                     |
     *                        --------------------------
     *
     * @param {dict} params=(see_below) - A dictionary of initialization parameters. Below for details.
     * @param {boolean} createDom=true - To be used for inheritance of jsa elements. If set to false the HTML DOM element will not be created, e.g. CreateDom() is not called.
     *
     * @comment CheckboxCtrl parameters
     * @property {boolean} params.value=false - The initial value that defines the state of the checkbox. True is checked.
     * @property {string} params.name='' - A unique identifier string which is equal for all checkboxes of the same group.
     * @property {boolean} params.readonly=false - Whether the user can change the checkbox or not. 
     * @property {string} params.elementType='div' - The DOM element type of the outer DOM element. The default is div.
     * @property {Array.<string>} params.style=['jsa-checkbox-ctrl']] - The CSS styles for the outer DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {Array.<string>} params.ctrlStyle=['jsa-checkbox-ctrl-input']] - The CSS styles for the radio DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {Array.<string>} params.labelStyle=['jsa-checkbox-ctrl-label']] - The CSS styles for the label DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {Array.<string>} params.errorIndicatorStyle=['jsa-checkbox-ctrl-error-indication']] - The CSS styles for the error indication DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {function} params.onChangeCallback - This function is called if the value of the checkbox changes by user interaction.
     *
     * @returns {this} Instance of the element itself to enable method chaining
     * @constructor CheckboxCtrl
     * @extends CustomUiElement
     * 
     * @example
     * app = new jsa.Application({});
     * myCheckboxCtrl = new jsa.CheckboxCtrl({
     *   content:'Check me if you like', 
     *   name: 'my-check-group',
     *   onChangeCallback:function(evt) {
     *     if(this.GetValue()) {
     *      alert('I know you like me!');
     *     }
     *   }
     * });
     * app.AddChild(myCheckboxCtrl); 
     */
    function CheckboxCtrl(params={},createDom=true) {
        CustomUiElement.call(this,params,false);
    
        //members
        this.value = false;
        this.name = '';
        this.readonly = false;
        this.style = ['jsa-checkbox-ctrl'];
        this.ctrlStyle = ['jsa-checkbox-ctrl-input'];
        this.labelStyle = ['jsa-checkbox-ctrl-label'];
        this.errorIndicatorStyle = ['jsa-checkbox-ctrl-error-indication'];
        this.onChangeCallback = function(event) {};
        
        //copy params
        CopyParams(this,params)
    
        if(createDom) {
            this.CreateDom();
        }
    
        return this;
    };
    
    CheckboxCtrl.prototype = Object.create(CustomUiElement.prototype);

    /**
     * Creates the HTML DOM element. In general, CreateDom is called automatically by the constructor. 
     * Please see [UIElementA.CreateDom]{@link UIElementA#CreateDom} for the general explanation.
     * @method CheckboxCtrl.prototype.CreateDom
     */
    CheckboxCtrl.prototype.CreateDom = function() {
        CustomUiElement.prototype.CreateDom.call(this);
        this.domElement.innerHTML = ''; //remove possible content because the content goes to the label
    
        this.input = document.createElement('input');
        ApplyStyles(this.ctrlStyle,this.input)
        if(this.readonly||!this.isEnabled) {
            this.Disable();
        }
        this.input.type = 'checkbox';
        this.input.name = this.name;
        this.input.id = this.id + 'Input';
        this.domElement.appendChild(this.input);

        this.label = document.createElement('label');
        this.label.setAttribute("for", this.id + 'Input');
        ApplyStyles(this.labelStyle,this.label);
        this.label.innerHTML = this.content;
        this.domElement.appendChild(this.label);

        this.errorIndicator = document.createElement('small');
        ApplyStyles(this.errorIndicatorStyle,this.errorIndicator);
        this.domElement.appendChild(this.errorIndicator);
        
        this.SetValue(this.value);
    
        this.input.data = this;
        if(this.onChangeCallback) {
            RedirectDomCallbackToUiElement(this.input,'change',this,this.onChangeCallback);
        }
    };

    /**
     * Returns the actual value of the checkbox.
     * @returns {boolean} True if box is checked; false if not.
     * @method CheckboxCtrl.prototype.GetValue
     *
     * @example
     * // ... continuing CheckboxCtrl general example
     * let val = myCheckboxCtrl.GetValue();
     */
    CheckboxCtrl.prototype.GetValue = function() {
        let value = this.input.checked;
        return value;
    };

    /**
     * Set the value and appearance of the checkbox during runtime.
     * @param {boolean} value - True if box shall be checked; false if not.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method CheckboxCtrl.prototype.SetValue
     *
     * @example
     * // ... continuing CheckboxCtrl general example
     * myCheckboxCtrl.SetValue(true); //-> Check mark shows up
     * myCheckboxCtrl.SetValue(true); //-> Check disappears 
     */
    CheckboxCtrl.prototype.SetValue = function(value) {
        let boolValue = value?true:false
        this.value = boolValue;
        this.input.checked = boolValue; //mask non bool values
        return this;
    };

    /**
     * Sets the checked state of the checkbox without any processing, 
     * but optionally allows cause regular change events.
     * @param {boolean} boolValue - True to set the box checked and false to uncheck.
     * @param {boolean} notify - If true, an on change event will be caused.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method CheckboxCtrl.prototype.SetRawValue
     */
    CheckboxCtrl.prototype.SetRawValue = function(boolValue,notify=false) {
        this.value = boolValue;
        this.input.checked = boolValue; //mask non bool values
        if(notify) {
            this.input.dispatchEvent(new Event('change', { 'bubbles': true })); /* Event is the JS event not jsa */
        }
        return this;
    };

    /**
     * Changes the content of the checkbox label during run-time.
     * @param {string} content - The content to be shown. '' deletes the current content.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method CheckboxCtrl.prototype.SetContent
     * @override
     */
    CheckboxCtrl.prototype.SetContent = function(content) {
        this.content = content;
        if(this.label) {
            this.label.innerHTML = this.content;
        }
        return this;
    };

    /**
     * Set the TextCtrl to readonly during runtime.
     * @param {bool} readonly - True means control becomes readonly. False means the control becomes editable.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method TextCtrl.prototype.SetReadonly
     *
     * @example
     * //... continuing the general TextCtrl example
     * myTextCtrl.SetReadonly(true); //-> TextCtrl becomes passive
     * myTextCtrl.SetReadonly(false); //-> TextCtrl becomes editable
     */
    CheckboxCtrl.prototype.SetReadonly = function(readonly) {
        if(this.readonly!=readonly) {
            if(readonly) {
                this.Disable();
            } else {
                this.Enable();
            }
            this.readonly = readonly;
        }
        return this;
    };
    
    CheckboxCtrl.prototype.Enable = function() {
        if(!this.isEnabled) {
            this.input.removeAttribute('disabled');
            CustomUiElement.prototype.Enable.call(this);
        }
        return this;
    };

    CheckboxCtrl.prototype.Disable = function() {
        if(this.isEnabled) {
            this.input.setAttribute('disabled',true);
            CustomUiElement.prototype.Disable.call(this);
        }
        return this;
    };


    /* RADIO CTRL */
    /**
     * @class RadioCtrl
     * @classdesc A radio control combines a radio box and a label. 
     * The user makes his input by adding or removing a radio mark.
     * Within a group of radio controls only one can be marked.
     * 
     *                         --------------------------
     *                        |  ---                     |
     *     click to toggle -->| | O | RadioCtrl          |
     *                        |  ---                     |
     *                         --------------------------
     * 
     * @param {dict} params=(see_below) - A dictionary of initialization parameters. Below for details.
     * @param {boolean} [createDom=true] - To be used for inheritance of jsa elements. If set to false the HTML DOM element will not be created, e.g. CreateDom() is not called.
     *
     * @comment RadioCtrl parameters
     * @property {boolean} params.value=false - True the radio button is checked. False it is not.
     * @property {string} params.name='' - A unique group identification for the radio button. From all radio buttons in one group, only one can be active.
     * @property {boolean} params.readonly=false - If true, the radio button is passive. If false it can be changed by the user.
     * @property {string} params.elementType='div' - The DOM element type of the surrounding DOM element.
     * @property {Array.<string>} params.style=['jsa-radio-ctrl']] - The CSS styles for the outer DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {Array.<string>} params.ctrlStyle=['jsa-radio-ctrl-input']] - The CSS styles for the radio DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {Array.<string>} params.labelStyle=['jsa-radio-ctrl-label']] - The CSS styles for the label DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {Array.<string>} params.errorIndicatorStyle=['jsa-radio-ctrl-error-indication']] - The CSS styles for the error indication DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {function} params.onChangeCallback - This function is called if the value of the radio button changes by user interaction.
     *
     * @returns {this} Instance of the element itself to enable method chaining
     * @constructor RadioCtrl
     * @extends CustomUiElement
     * 
     * @example
     * // Create a radio group with two buttons of that only one can be active
     * app = new jsa.Application({});
     * myRadio1 = new jsa.RadioCtrl({
     *   content:'Radio 1',
     *   name:'my-radio-group',
     *   onChangeCallback:function(evt) {
     *     if(this.GetValue()) {
     *      alert('First radio button is active');
     *     }
     *   }
     * });
     * myRadio2 = new jsa.RadioCtrl({
     *   content:'Radio 2',
     *   name:'my-radio-group'
     * });
     * app.AddChild(myRadio1); 
     * app.AddChild(myRadio2); 
     */
    function RadioCtrl(params={},createDom=true) {
        CustomUiElement.call(this,params,false);
    
        //members
        this.value = false;
        this.readonly = false;
        this.elementType = 'div';
        this.style = ['jsa-radio-ctrl'];
        this.ctrlStyle = ['jsa-radio-ctrl-input'];
        this.labelStyle = ['jsa-radio-ctrl-label'];
        this.errorIndicatorStyle = ['jsa-radio-ctrl-error-indication'];
        this.onChangeCallback = function(event) {};
        
        //copy params
        CopyParams(this,params)
    
        if(createDom) {
            this.CreateDom();
        }
    
        return this;
    };
    
    RadioCtrl.prototype = Object.create(CustomUiElement.prototype);

    /**
     * Creates the HTML DOM element. In general, CreateDom is called automatically by the constructor. 
     * Please see [UIElementA.CreateDom]{@link UIElementA#CreateDom} for the general explanation.
     * @method RadioCtrl.prototype.CreateDom
     */
    RadioCtrl.prototype.CreateDom = function() {
        CustomUiElement.prototype.CreateDom.call(this);
        this.domElement.innerHTML = ''; //remove possible content because the content goes to the label
    
        this.input = document.createElement('input');
        ApplyStyles(this.ctrlStyle,this.input)
        if(this.readonly||!this.isEnabled) {
            this.Disable();
        }
        this.input.type = 'radio';
        this.input.name = this.name;
        this.input.id = this.id + 'Input'; // add html id to radiobox
        this.domElement.appendChild(this.input);

        this.label = document.createElement('label');
        this.label.setAttribute("for", this.id + 'Input'); // set for-attribute
        ApplyStyles(this.labelStyle,this.label);
        this.label.innerHTML = this.content;
        this.domElement.appendChild(this.label);

        this.errorIndicator = document.createElement('small');
        ApplyStyles(this.errorIndicatorStyle,this.errorIndicator);
        this.domElement.appendChild(this.errorIndicator);
        
        this.SetValue(this.value);
    
        this.input.data = this;
        if(this.onChangeCallback) {
            RedirectDomCallbackToUiElement(this.input,'change',this,this.onChangeCallback);
        }
    };

    /**
     * Gets the status of the radio button. 
     * @returns {boolean} - True if checked, false if not.
     * @method RadioCtrl.prototype.GetValue
     *
     * @example
     * // ...continuing general RadioCtrlExample
     * let status = myRadio1.GetValue();
     */
    RadioCtrl.prototype.GetValue = function() {
        let value = this.input.checked;
        return value;
    };

    /**
     * Sets the status of the desired value. If the value is true, all other radio
     * controls of the same group are unchecked.
     * @param {boolean} value - Whether the radio control shall be checked or not.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method RadioCtrl.prototype.SetValue
     *
     * @example
     * // ...continuing general RadioCtrlExample
     * myRadio1.GetValue(true);
     * let status = myRadio2.GetValue(); //must be false
     */
    RadioCtrl.prototype.SetValue = function(value) {
        let boolValue = value?true:false
        this.value = boolValue;
        this.input.checked = boolValue; //mask non bool values
        return this;
    };

    /**
     * Sets the checked state of the radio input without any processing, 
     * but optionally allows cause regular change events.
     * @param {boolean} boolValue - True to marks the radio input checked and false unmarks it.
     * @param {boolean} notify - If true, an on change event will be caused.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method RadioCtrl.prototype.SetRawValue
     */
    RadioCtrl.prototype.SetRawValue = function(boolValue,notify=false) {
        this.value = boolValue;
        this.input.checked = boolValue; //mask non bool values
        if(notify) {
            this.input.dispatchEvent(new Event('change', { 'bubbles': true })); /* Event is the JS event not jsa */
        }
        return this;
    };

    /**
     * Changes the content of the radio label during run-time.
     * @param {string} content - The content to be shown. '' deletes the current content.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method RadioCtrl.prototype.SetContent
     * @override
     */
    RadioCtrl.prototype.SetContent = function(content) {
        this.content = content;
        if(this.label) {
            this.label.innerHTML = this.content;
        }
        return this;
    };

    RadioCtrl.prototype.Enable = function() {
        if(!this.isEnabled) {
            this.input.removeAttribute('disabled');
            CustomUiElement.prototype.Enable.call(this);
        }
        return this;
    };

    RadioCtrl.prototype.Disable = function() {
        if(this.isEnabled) {
            this.input.setAttribute('disabled',true);
            CustomUiElement.prototype.Disable.call(this);
        }
        return this;
    };
    

    
    /* SELECTCTRL */
    /**
     * @class SelectCtrl
     * @classdesc A select control is a drop-down box with predefined options. 
     * 
     *      ----------------------------------
     *     |   ----------------------------   |
     *     |  | SelectCtrl             | v | <--- pick option here
     *     |  |----------------------------|  |
     *      --| Option 2                   |--
     *        |----------------------------|
     *        | ...                        |
     *         ----------------------------
     *  
     * Transfer functions allow to map between arbitrary input data and the select options.
     *
     * @param {dict} params=(see_below) - A dictionary of initialization parameters. Below for details.
     * @param {boolean} params - >parameter description<
     *
     * @comment SelectCtrl parameters
     * @property {boolean} params.value=false - The value of the initial option that shall be selected.
     * @property {Array.<any>} params.values=['yes','no']] - The value linked with each option. This can be any data type. The number of elements must be the same as in labels.
     * @property {Array.<string>} params.labels=['Yes','No']] - The label displayed for each option. The number of labels must equal the number of values.
     * @property {boolean} params.readonly=false - If true, the select control is not editable.
     * @property {string} params.elementType='div' - The DOM type of the surrounding DOM element. Only change if you know what you are doing.
     * @property {Array.<string>} params.style=['jsa-select-ctrl']] - The CSS styles for the outer DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {Array.<string>} params.ctrlStyle=['jsa-select-ctrl-input']] - The CSS styles for the select DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {Array.<string>} params.errorIndicatorStyle=['jsa-select-ctrl-error-indication']] - The CSS styles for the error indication DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {function} params.onChangeCallback - This function is called if the current selection was changed. It forwards the HTML changed event.
     * The default is:
     * 
     *     function(event) {};
     * 
     * @property {function} params.inputTransferFunction - The input transfer function converts between the params.values 
     * and the HTML option tags value, i.e. it converts between user value and string. It is for the compatibility reasons only,
     * i.e. if one has to access the selection value outside of jsa.
     * The default is:
     * 
     *     function(value) {
     *       let  valueStr = value; 
     *       return valueStr;
     *     };
     * 
     * @property {function} params.validateFunction - This function is used to validate the current selection. 
     * If it does not return true, the error indication is shown. In case of invalidity, the function must throw
     * en error with the error indication message, i.e. throw new Error('This is invalid because...')
     * 
     * The default is:
     * 
     *     function(valueStr) {return true;};
     * 
     * @comment SelectCtrl internals
     * @property {Array} this.options (readonly) The array of HTML options elements created internally
     * @returns {this} Instance of the element itself to enable method chaining
     *
     * @constructor SelectCtrl
     * @extends CustomUiElement
     * 
     * @example
     * // Create select control with three options
     * app = new jsa.Application({});
     * mySelect = new jsa.SelectCtrl({
     *   values:[1,2,3],
     *   labels:['yes','no','maybe'],
     *   onChangeCallback:function(evt) {
     *     alert('Selection changed to value: '+this.GetValue());
     *   }
     * }); 
     * app.AddChild(mySelect); 
     */
    function SelectCtrl(params={},createDom=true) {
        CustomUiElement.call(this,params,false);
    
        //members
        this.value = false; //the default value
        this.values = ['yes','no'];
        this.labels = ['Yes','No'];
        this.readonly = false;
        this.elementType = 'div';
        this.style = ['jsa-select-ctrl'];
        this.ctrlStyle = ['jsa-select-ctrl-input'];
        this.errorIndicatorStyle = ['jsa-select-ctrl-error-indication'];
        this.onChangeCallback = function(event) {};
        this.inputTransferFunction = function(value) {var valueStr = value; return valueStr;};
        this.validateFunction = function(valueStr) {return true;}; //Shall throw an Error if validation fails
    
        //copy params
        CopyParams(this,params)

        //internals
        this.options = [];

        //sanity checks
        if(this.values.length!=this.labels.length) {
            throw new Error("The numbers of values must equal the number of labels.");
        }
    
        if(createDom) {
            this.CreateDom();
        }
    
        return this;
    };
    
    SelectCtrl.prototype = Object.create(CustomUiElement.prototype);

    /**
     * Creates the HTML DOM element. In general, CreateDom is called automatically by the constructor. 
     * Please see [UIElementA.CreateDom]{@link UIElementA#CreateDom} for the general explanation.
     * @method SelectCtrl.prototype.CreateDom
     */
    SelectCtrl.prototype.CreateDom = function() {
        CustomUiElement.prototype.CreateDom.call(this);
    
        this.select = CreateDomElementWithUniqueId('select',this.id);
        ApplyStyles(this.ctrlStyle,this.select);
        if(this.readonly||!this.isEnabled) {
            this.Disable();
        }
        this.domElement.appendChild(this.select);

        let  nValues = this.values.length;
        for(let i=0;i<nValues;i++) {
            this._AddOption(this.labels[i],this.values[i]);
        }

        this.errorIndicator = document.createElement('small');
        ApplyStyles(this.errorIndicatorStyle,this.errorIndicator)
        this.domElement.appendChild(this.errorIndicator);

        this.SetValue(this.value);
    
        this.select.data = this;
        if(this.onChangeCallback) {
            RedirectDomCallbackToUiElement(this.select,'change',this,this.onChangeCallback);
        }
    };

    /**
     * Get the value of the current selected option.
     * @returns {defined_by_params.values} - The value corresponding to the currently selected option
     * @method SelectCtrl.prototype.GetValue
     *
     * @example
     * // ... continuing the general SelectCtrl example above
     * let val = mySelect.GetValue();
     */
    SelectCtrl.prototype.GetValue = function() {
        let i = this.select.selectedIndex;
        let value = this.values[i];
        return value;
    };

    /**
     * Get the raw value of the current selected option. This is added 
     * for compatibility to other ctrl UI elements. For the SelectCtrl 
     * this behaves exactly like [GetValue]{@link SelectCtrl.GetValue}.
     * @returns {defined_by_params.values} - The value corresponding to the currently selected option
     * @method SelectCtrl.prototype.GetRawValue
     */
    SelectCtrl.prototype.GetRawValue = function() {
        return this.GetValue();
    };

    /**
     * Changes the current selection during runtime. 
     * @param {defined_by_params.values} value - The value to be set. This maps to a label.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method SelectCtrl.prototype.SetValue
     *
     * @example
     * // ... continuing the general SelectCtrl example above
     * mySelect.SetValue(3); //select shows 'maybe' 
     */
    SelectCtrl.prototype.SetValue = function(value) {
        let i = this.values.findIndex( function(entry) {
            return (entry==value);
        });
        if(-1<i) {
            this.select.selectedIndex = i;
        }
        
        return this;
    };

    /**
     * Compatibility to other UI ctrl elements: Behaves the same as 
     * [SetValue]{@link SelectCtrl.SetValue}.
     * @param {defined_by_params.values} value - The value to be set. This maps to a label.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method SelectCtrl.prototype.SetRawValue
     */
    SelectCtrl.prototype.SetRawValue = function(value) {
        return this.SetValue(value);
    };
    
    SelectCtrl.prototype.Enable = function() {
        if(!this.isEnabled) {
            this.select.removeAttribute('disabled');
            CustomUiElement.prototype.Enable.call(this);
        }
        return this;
    };

    SelectCtrl.prototype.Disable = function() {    
        if(this.isEnabled) {
            this.select.setAttribute('disabled',true);
            CustomUiElement.prototype.Disable.call(this);
        }
        return this;
    };

    /**
     * Manually triggers the validation of the current selection. It calls params.validationFunction.
     * If the selection is not valid it returns false and displays the error indication.
     * @returns {boolean} True if params.validationFunction returns true and false if params.validationFunction throws and exception.
     * @method SelectCtrl.prototype.Validate
     *
     * @example
     * // Create select control with default yes/no option and a custom validateFunction
     * app = new jsa.Application({});
     * mySelect = new jsa.SelectCtrl({
     *   validateFunction: function(value) {
     *     throw new Error('Every selection is invalid!')}
     *   }
     * }); 
     * app.AddChild(mySelect); 
     * mySelect.Validate(); // -> error indication shows 'Every selection is invalid!'
     */
    SelectCtrl.prototype.Validate = function() {
        this.errorIndicator.innerHTML = ''; //delete any previous error message
        let valid = true;
        if(this)
        try{
            let value = this.values[this.select.selectedIndex];
            if(this.validateFunction) {
                valid = this.validateFunction(value);
            }
        }catch(e) {
            valid = false;
            this.errorIndicator.innerHTML = e.toString();
        }
        return valid;
    };


    /**
     * Changes the readonly property during run-time.
     * @param {boolean} readonly - If true the SelectCtrl becomes disabled. If false it is editable.
     * @method SelectCtrl.prototype.SetReadonly
     *
     * @example
     * // ... continuing the general SelectCtrl example above
     * mySelect.SetReadonly(true); //can not edit
     * mySelect.SetReadonly(false); //can edit
     */
    SelectCtrl.prototype.SetReadonly = function(readonly) {
        if(readonly) {
            this.Disable();
        } else {
            this.Enable();
        }
    };

    /**
     * Internal use only! Added a new option DOM element, but does not add value and 
     * label to the internal vars.
     * @param {string} label - label
     * @param {value} value - value
     * @private
     * @method SelectCtrl.prototype._AddOption
     */
    SelectCtrl.prototype._AddOption = function(label,value) {
        let  option = CreateDomElementWithUniqueId('option');
        option.value = this.inputTransferFunction(value);
        option.innerHTML = label;
        this.select.appendChild(option);
        this.options.push(option);
    };

    /**
     * Dynamically adds a new option to the select ctrl.
     * @param {string} label - If true the SelectCtrl becomes disabled. If false it is editable.
     * @method SelectCtrl.prototype.AddOption
     *
     * @example
     * // ... continuing the general SelectCtrl example above
     * mySelect.AddOption('unsure',null);
     */
    SelectCtrl.prototype.AddOption = function(label,value) {
        this.labels.push(label);
        this.values.push(value);
        this._AddOption(label,value);
        return this;
    };

    /**
     * Dynamically removes a new option from the select ctrl based on the index.
     * The index starts at 0 for the first entry. 
     * @param {int} i - The index of the option to be removed
     * @method SelectCtrl.prototype.RemoveOptionByIndex
     *
     * @example
     * // ... continuing the general SelectCtrl example above
     * mySelect.RemoveOptionByIndex(2);
     */
    SelectCtrl.prototype.RemoveOptionByIndex = function(i) {
        if(i>-1 && i<this.values.length) {
            //remove the option from the HTML element
            let option = this.options[i];
            this.select.removeChild(option);
            //remove it from the internal vars
            this.values.splice(i,1);
            this.labels.splice(i,1);
            this.options.splice(i,1);
        }
        return this;
    };


    /**
     * Dynamically removes an option from the select ctrl based on the value given. 
     * It only removes the first option with this value.
     * @param {Object} value - The value of the option to be removed.
     * @method SelectCtrl.prototype.RemoveOptionByValue
     *
     * @example
     * // ... continuing the general SelectCtrl example above
     * mySelect.RemoveOptionByValue(null);
     */
    SelectCtrl.prototype.RemoveOptionByValue = function(value) {
        let i = this.values.findIndex(value);
        this.RemoveOptionByIndex(i);
        return this;
    };

    /**
     * Dynamically removes an option from the select ctrl based on the label given. 
     * It only removes the first option with this label.
     * @param {string} label - The label of the option to be removed.
     * @method SelectCtrl.prototype.RemoveOptionByLabel
     *
     * @example
     * // ... continuing the general SelectCtrl example above
     * mySelect.RemoveOptionByLabel('unsure');
     */
    SelectCtrl.prototype.RemoveOptionByLabel = function(value) {
        let i = this.labels.findIndex(label);
        this.RemoveOptionByIndex(i);
        return this;
    };

    /**
     * Dynamically removes all options.
     * @method SelectCtrl.prototype.RemoveAllOptions
     *
     * @example
     * // ... continuing the general SelectCtrl example above
     * mySelect.RemoveAllOptionss();
     */
    SelectCtrl.prototype.RemoveAllOptions = function() {
        this.select.innerHTML = '';
        this.values = [];
        this.label = [];
        this.options = [];
        return this;
    };
    

    /* TABLECOL */
    /**
     * @class TableCol
     * @classdesc TableCol wraps HTML td element to build and manage tables in jsa. 
     * It belongs to [jsa.Table]{@link Table} and [jsa.TableRow]{@link TableRow}.
     * 
     *      ----------------------------------- 
     *     |    ...     | TableCol |    ...    |
     *      ----------------------------------- 
     * 
     * See [jsa.Table]{@link Table} for an example.
     *
     * @param {dict} params=(see_below) - A dictionary of initialization parameters. Below for details.
     * @param {boolean} [createDom=true] - To be used for inheritance of jsa elements. If set to false the HTML DOM element will not be created, e.g. CreateDom is not called.
     * @comment TableCol parameters
     * @property {string} params.elementType='td' - The DOM element used created or the element. Do not change.
     * @property {int} params.colSpan=1 - Sets the colspan property of the td element.
     *
     * @returns {this} Instance of the element itself to enable method chaining
     * @constructor TableCol
     * @extends CustomFlatContainer
     */
    function TableCol(params={},createDom=true) {
        CustomFlatContainer.call(this,params,false);
    
        //members
        this.elementType = 'td';
        this.colSpan = 1;
    
        //copy params
        CopyParams(this,params)
    
        if(createDom) {
            this.CreateDom();
        }
    
        return this;
    }
    
    TableCol.prototype = Object.create(CustomFlatContainer.prototype);

    /**
     * Creates the HTML DOM element. In general, CreateDom is called automatically by the constructor. 
     * Please see [UIElementA.CreateDom]{@link UIElementA#CreateDom} for the general explanation.
     * Override to set colspan property.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method TableCol.prototype.CreateDom
     */
    TableCol.prototype.CreateDom = function() {
        CustomFlatContainer.prototype.CreateDom.call(this);
        this.domElement.colSpan = this.colSpan;
        return this;
    };
    

    /* TABLEROW */
    /**
     * @class TableRow
     * @classdesc TableCol wraps HTML tr element to build and manage tables in jsa. 
     * It belongs to [jsa.Table]{@link Table} and [jsa.TableCol]{@link TableCol}.
     * 
     *      ----------------------------------- 
     *     |  TableRow                         |
     *     | --------------------------------- |
     *     ||    ...    |    ...   |    ...   ||
     *     | --------------------------------- |
     *      -----------------------------------
     * 
     * See [jsa.Table]{@link Table} for an example.
     *
     * @param {dict} params=(see_below) - A dictionary of initialization parameters. Below for details.
     * @param {boolean} [createDom=true] - To be used for inheritance of jsa elements. If set to false the HTML DOM element will not be created, e.g. CreateDom is not called.
     *
     * @comment TableRow parameters
     * @property {string} params.elementType='tr' - The DOM element type created. Do not change if you do not know what you are doing.
     * @returns {this} Instance of the element itself to enable method chaining
     *
     * @constructor TableRow
     * @extends CustomFlatContainer
     */
    function TableRow(params={},createDom=true) {
        CustomFlatContainer.call(this,params,false);
    
        //members
        this.elementType = 'tr';
    
        //copy params
        CopyParams(this,params)
    
        if(createDom) {
            this.CreateDom();
        }
    
        return this;
    }
    
    TableRow.prototype = Object.create(CustomFlatContainer.prototype);
    
    
    /* TABLE */
    /**
     * @class Table
     * @classdesc TableCol wraps HTML td element to build and manage tables in jsa. 
     * It belongs to [jsa.TableRow]{@link TableRow} and [jsa.TableCol]{@link TableCol}.
     * 
     *      -------------------------------------
     *     | Table                               |
     *     | ----------------------------------- |
     *     ||  TableRow                         ||
     *     || --------------------------------- ||
     *     |||    ...    | TableCol |    ...   |||
     *     || --------------------------------- ||
     *     ||-----------------------------------||
     *     ||                ...                ||
     *
     * @param {dict} params=(see_below) - A dictionary of initialization parameters. Below for details.
     * @param {boolean} [createDom=true] - To be used for inheritance of jsa elements. If set to false the HTML DOM element will not be created, e.g. CreateDom is not called.
     *
     * @comment Table parameters
     * @property {string} params.elementType='table' - The DOM element created. Do not change if you are no knowing what you do.
     * @returns {this} Instance of the element itself to enable method chaining
     *
     * @constructor Table
     * @extends CustomFlatContainer
     * 
     * @example
     * // Create a 4x4 table
     * app = new jsa.Application({});
     * myTable = new jsa.Table({});
     * myRow1 = new jsa.TableRow({});
     * myRow1.AddChild(new jsTableCol({content:'cell 1,1'}));
     * myRow1.AddChild(new jsTableCol({content:'cell 1,2'}));
     * myTable.AddChild(myRow1);
     * myRow2 = new jsa.TableRow({});
     * myRow2.AddChild(new jsTableCol({content:'cell 2,1'}));
     * myRow2.AddChild(new jsTableCol({content:'cell 2,2'}));
     * myTable.AddChild(myRow2);
     */
    function Table(params={},createDom=true) {
        CustomFlatContainer.call(this,params,false);
    
        //members
        this.elementType = 'table';
    
        //copy params
        CopyParams(this,params)
    
        if(createDom) {
            this.CreateDom();
        }
    
        return this;
    }
    
    Table.prototype = Object.create(CustomFlatContainer.prototype);


    /* COMMANDA */
    /**
     * @abstract
     * @class CommandA
     * @classdesc This is the abstract base class for a jsa command.
     * A command is an action that is reversible and shall be managed 
     * by the applications command manager, e.g. to show an edit history
     * and to allow to undo actions. It defines the standard interface for 
     * doing and undoing such actions and for getting textual explanations 
     * on what was done.
     *
     * @comment CommandA internals
     * @param {string} this.name - (readonly) The name of the command
     * @param {string} this.description - (readonly) A free text description on the purpose of this command.
     * @constructor CommandA
     */
    function CommandA() {
        this.name = 'CommandA';
        this.description = 'This is a command';
    };

    /**
     * Overwrite this to define the purpose of the command, i.e. this is called if a command is executed.
     * @method CommandA.prototype.Do
     * @throws {Error} An Error object indicating what went wrong.  
     */
    CommandA.prototype.Do = function() {
        throw new Error('CommandA: not implemented, is abstract.');
    };

    /**
     * Overwrite this to define how a command can be reversed, i.e. this is called if a command shall be undone.
     * @method CommandA.prototype.Undo
     * @throws {Error} An Error object indicating what went wrong.                                
     */                                                    
    CommandA.prototype.Undo = function() {
        throw new Error('CommandA: not implemented, is abstract.');
    };

    /**
     * Getter function for the command's name. Prefer this over command.name.
     * @returns {string} Returns the name
     * @method CommandA.prototype.GetName
     */
    CommandA.prototype.GetName = function() {
        return this.name;
    };

    /**
     * The getter function for the commands description. Prefer this over command.description.
     * @returns {string} Returns description string of the command.
     * @method CommandA.prototype.GetDescription
     */
    CommandA.prototype.GetDescription = function() {
        return this.description;
    };


    /* COMMANDMANAGER */
    /**
     * @class CommandManager
     * @classdesc A command manager a central point for managing commands. 
     * It manages a sequential list of commands. If a new command is executed, this 
     * is added to the list and executed commands. It also manager Undo and Redo. Undo moves 
     * backwards in the command stack and Redo moves forward.
     * Moreover, a command manager is an Observable and can inform about command executions, 
     * Undo or Redo.
     * Usually an Application has a command manager by default, i.e. app.commandManager.
     *
     * @param {Array} this.commandStack=[]] - (readonly) The list of all executed commands
     * @param {int} this.stackPointer=-1 - (readonly) The pointer to actual commands. If no Undo was issued this points to the last element in this.commandStack.
     * @returns {this} Instance of the element itself to enable method chaining
     * 
     * @constructor CommandManager
     * @extends Observable
     * 
     * @example
     * //create a new command manager
     * let myCommandManager = jsa.CommandManager();
     * myCommandManager.Execute(new jsa.CustomCommand({
     *   name:'My first Command',
     *   description:'Issues alert messages on do and Undo',
     *   doCallback:function() { alert('Command executed'); },
     *   undoCallback: function() { alert('Command undone'); }
     * })); // ->shows 'Command executed'
     * myCommandManager.Undo(); // ->shows 'Command undone'
     */
    function CommandManager() {
        Observable.call(this);

        //members
        this.commandStack = [];
        this.stackPointer = -1;

        return this;
    };

    CommandManager.prototype = Object.create(Observable.prototype);

    /**
     * Executes the given command immediately and adds it to the command stack.
     * Issues an 'EXECUTE' event.
     * @param {CommandA} - The command to be executed
     * @returns {this} Instance of the element itself to enable method chaining
     * @fires [EventMethodCall]{@link EventMethodCall}(eventId= [EVENT.TYPES.METHOD_CALL_EXECUTE]{@link EVENT}; methodName = 'Execute')
     * @method CommandManager.prototype.Execute
     *
     * @example
     * // ... continuing the general CommandManager example
     * myCommandManager.Execute(new jsa.CustomCommand({
     *   name:'My first Command',
     *   description:'Issues alert messages on do and Undo',
     *   doCallback:function() { alert('Command executed'); },
     *   undoCallback: function() { alert('Command undone'); }
     * })); // ->shows 'Command executed'
     */
    CommandManager.prototype.Execute = function(command) {
        command.Do();
        if(this.commandStack.length>this.stackPointer+1 ) {
            //Clear the commandStack if this was issued after an undo
            this.commandStack = this.commandStack.slice(0,this.stackPointer+1)
        }     
        this.commandStack.push(command)
        this.stackPointer++;
        this.Notify(new EventMethodCall(this,'Execute',command,null));
        
        return this;
    };

    /**
     * Undoes the command that is indexed by the stack pointer, i.e. the command before the last command 
     * that was undone. If no command was undone, it is the last command.
     * Issues an 'UNDO' event.
     * @returns {this} Instance of the element itself to enable method chaining
     * @fires [EventMethodCall]{@link EventMethodCall}(eventId= [EVENT.TYPES.METHOD_CALL_UNDO]{@link EVENT}; methodName = 'Undo')
     * @method CommandManager.prototype.Undo
     *
     * @example
     * // ... continuing the general CommandManager example
     * myCommandManager.Undo(); // ->shows 'Command undone'
     */
    CommandManager.prototype.Undo = function(command) {
        if(this.stackPointer>=0) {
            let command = this.commandStack[this.stackPointer];
            command.Undo();
            this.stackPointer--;
            this.Notify(new EventMethodCall(this,'Undo',command,null));
        }
    
        return this;
    };

    /**
     * Redos the command above the command stack pointer, i.e. the last command
     * that was undone. If no command was undone, redo is not possible.
     * Issues an 'REDO' event.
     * @returns {this} Instance of the element itself to enable method chaining
     * @fires [EventMethodCall]{@link EventMethodCall}(eventId= [EVENT.TYPES.METHOD_CALL_REDO]{@link EVENT}; methodName = 'Redo')
     * @method CommandManager.prototype.Redo
     *
     * @example
     * // ... continuing the general CommandManager example
     * myCommandManager.Redo(); // ->shows 'Command executed'
     */
    CommandManager.prototype.Redo = function(command) {
        if(this.stackPointer+1<this.commandStack.length) {
            let command = this.commandStack[this.stackPointer+1];
            command.Do();
            this.stackPointer++;
            this.Notify(new EventMethodCall(this,'Redo',command,null));
        }
        return this;
    };

    /**
     * Returns the last command executed. 
     * This can also be the last command that that was redone or 
     * the command before the last command that was undone.
     * @returns {CommandA} The command the stack pointer points at.
     * @method CommandManager.prototype.GetLastCommand
     *
     * @example
     * // ... continuing the general CommandManager example
     * myCommandManager.Undo(); // ->shows 'Command undone'
     * myCommandManager.Redo(); // ->shows 'Command executed'
     * myCommandManager.GetLastCommand(); // ->returns command object executed by Redo()
     */
    CommandManager.prototype.GetLastCommand = function() {
        let command = null;
        if(this.stackPointer>=0) {
            command = this.commandStack[this.stackPointer];
        }
        return command;
    };

    /**
     * The command after the last command executed. 
     * This can also be command after the last command that that was redone or 
     * the command that was undone.
     * @returns {CommandA} The command that comes next on the stack.
     * @method CommandManager.prototype.GetNextCommand
     *
     * @example
     * // ... continuing the general CommandManager example
     * myCommandManager.Undo(); // ->shows 'Command undone'
     * myCommandManager.GetLastCommand(); // ->returns command object executed by Undo()
     */
    CommandManager.prototype.GetNextCommand = function() {
        let command = null;
        if(this.stackPointer+1<this.commandStack.length) {
            command = this.commandStack[this.stackPointer+1];
        }
        return command;
    };


    /* CUSTOMCOMMAND */
    /**
     * @class CustomCommand
     * @classdesc This is a generic command class that prevents that CommandA must be subclassed 
     * every time a command shall be issued. Most properties of a command can be customized 
     * with the parameters of CustomCommand.
     *
     * @param {dict} params=(see_below) - A dictionary of initialization parameters. Below for details.
     *
     * @comment CustomCommand parameters
     * @property {string} params.name='Custom Command' - The name of the command
     * @property {Object} params.data=null - The data attached to the command. 
     * This data will be available as this.data in the Do and Undo method of the command. 
     * This can be a primitive value or a complex data structure.
     * @property {function} params.doCallback - The function to be executed when executing this command or redo.
     * @property {function} params.undoCallback - The function executed when the command is undone.
     * @property {string} params.description='This is a custom command' - The description string of the command.
     * @property {function} params.getNameCallback - Provides the possibility to dynamically create the name of the command,
     * e.g. depending on do or undo or depending on the data. By default it returns just the content of this.name:
     * 
     *     function() {return this.name};
     *
     * @returns {this} Instance of the element itself to enable method chaining
     * @constructor CustomCommand
     * @extends CommandA
     * 
     * @example
     * let myCommandManager = jsa.CommandManager();
     * // Create a new custom command
     * myCommandManager.Execute(new jsa.CustomCommand({
     *   name:'My first Command',
     *   description:'Issues alert messages on do and Undo',
     *   data: 4,
     *   doCallback:function() { alert(this.GetName()+' executed'); },
     *   undoCallback: function() { alert(this.GetName()+' undone'); }
     *   getNameCallback: function() { return 'Custom command with data = '+this.data; }
     * })); // ->shows 'Custom command with data = 4 executed'
     * myCommandManager.Undo(); // ->shows 'Custom command with data = 4 undone'
     */
    function CustomCommand(params) {
        CommandA.call(this);

        //members
        this.name = 'Custom Command';
        this.data = null;
        this.doCallback = function() {};
        this.undoCallback = function() {};
        this.getNameCallback = function() {return this.name};

        this.description = 'This is a custom command';

        //copy parameters
        CopyParams(this,params);

        return this;
    };

    CustomCommand.prototype = Object.create(CommandA.prototype);

    /**
     * Executes params.doCallback().
     * @returns {this} Instance of the element itself to enable method chaining
     * @method CustomCommand.prototype.Do
     */
    CustomCommand.prototype.Do = function() {
        this.doCallback();
        return this;
    };

    /**
     * Executes params.undoCallback().
     * @returns {this} Instance of the element itself to enable method chaining
     * @method CustomCommand.prototype.Undo
     *
     */
    CustomCommand.prototype.Undo = function() {
        this.undoCallback();
        return this;
    };

    /**
     * Executes params.getNameCallback() and returns the result.
     * @returns {string} - The (dynamically) created name of the command.
     * @method CustomCommand.prototype.GetName
     */
    CustomCommand.prototype.GetName = function() {
        return this.getNameCallback();
    };


    /* CHANGEVIEWCOMMAND */
    /**
     * @class ChangeViewCommand
     * @classdesc The ViewCommand is a command that on Do changes the view of a view manager to the desired view. 
     * If undone it changes the view back to the previous one.
     *
     * @param {ViewManager} viewManager - The ViewManager object that manages the views.
     * @param {View} newView - The View object that shall be activated. The view must be known by the view manager.
     * 
     * @comment internals
     * @property {View} this.oldView - (readonly) The view that was active before executing this command.
     * @property {string} this.name - (readonly) The commands name
     * @property {string} this.description - (readonly) The command's description string
     *
     * @returns {this} Instance of the element itself to enable method chaining
     * @constructor ChangeViewCommand
     * @extends CommandA
     * 
     * @example
     * app = new jsa.Application({});
     * let view1 = new jsa.view({content:'View 1'});
     * app.viewManager.AddChild(view1);
     * let view2 = new jsa.view({content:'View 2'});
     * app.viewManager.AddChild(view2);
     * app.commandManager.Execute(new jsa.ChangeViewCommand(app.viewManager,view1)); //-> view 1 is shown
     * app.commandManager.Execute(new jsa.ChangeViewCommand(app.viewManager,view2)); //-> view 2 is shown
     * app.commandManager.Undo(); //-> view 1 is shown
     * app.commandManager.Redo(); //-> view 2 is shown
     */
    function ChangeViewCommand(viewManager,newView) {
        CommandA.call(this);

        //members
        this.viewManager = viewManager;
        this.newView = newView;
        this.oldView = null
        this.name = 'Change to view to ' + newView.name;
        this.description = 'Changes the actual view';

        return this;
    };

    ChangeViewCommand.prototype = Object.create(CommandA.prototype);

    /**
     * Changes the view to the desired view and remembers the last active view.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method ChangeViewCommand.prototype.Do
     */
    ChangeViewCommand.prototype.Do = function() {
        this.oldView = this.viewManager.GetActiveView();
        this.viewManager.ActivateView(this.newView);
        return this;
    };

    /**
     * Changes back to the last active view.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method ChangeViewCommand.prototype.Undo
     */
    ChangeViewCommand.prototype.Undo = function() {
        this.viewManager.ActivateView(this.oldView);
        return this;
    };


    /* MENUENTRY */
    /**
     * @class MenuEntry
     * @classdesc A menu entry is a element to be clicked in a menu. 
     * It is a label. Icons can be added using fonts, custom css styles or by
     * adding html content to the label.
     * 
     *       ------------------------------------------------------------------
     *      |     ...       |   MenuEntry    |      ...        |               | 
     *       --------------------------------------------------|---------------|
     *                                                         |      ...      |
     *                                                         |---------------|
     *                                                         |   MenuEntry   |
     *                                                         |---------------|
     *                                                         |      ...      |  
     * 
     *
     * @param {dict} params=(see_below) - A dictionary of initialization parameters. Below for details.
     * @param {boolean} [createDom=true] - To be used for inheritance of jsa elements. If set to false the HTML DOM element will not be created, e.g. CreateDom() is not called.
     *
     * @comment MenuEntry parameters
     * @property {boolean} params.isEnabled=true - Whether the entry is enabled on startup.
     * @property {function} params.onClickCallback=null - A function that is called if the menu entry was clicked.
     * The function receives the HTML event, i.e. the signature must be function(evt){...}. 
     * @property {Array.<string>} params.style=['jsa-menu-entry']] - The CSS class(s) of the entry HTML element.
     * @property {Array.<string>} params.labelStyle=['jsa-menu-entry-label']] - The CSS class(s) of the entry's label's HTML element.
     * @property {bool} params.hasPopup=false - Indicates that the menu entry shall open a popup menu. 
     * If the it shall hasPopup must be true and 
     * a [Menu]{@link Menu} must be added as a child, which has isPopup set to true.
     * @comment MenuEntry internals
     * @property {Label} this.subelements.label - (readonly) The label element of the menu entry.
     * @property {Menu} this.subelements.submenu - (readonly) The (popup) submenu of the menu entry. If on was added using SetSubmenu.
     *
     * @returns {this} Instance of the element itself to enable method chaining
     * @constructor MenuEntry
     * @extends CustomFlatContainer
     * @extends UIElementWithIconA
     * 
     * @example
     * // Create a new File menu for the application
     * // containing undo and redo
     * app = new jsa.Application({});
     * let editMenuEntry = new jsa.MenuEntry( {
     *     id :'#EDIT',
     *     name : 'Edit',
     *     hasPopup : true
     * });
     * app.menu.AddChild(editMenuEntry); //adds a new entry to the main menu
     * let editMenu = new jsa.Menu( {
     *     isPopup : true,
     *     popupDirection : 'bottom'
     * });
     * editMenuEntry.SetSubmenu(editMenu); //adds a popup menu to  the new edit menu entry
     * let undoMenuEntry = new jsa.MenuEntry( {
     *     id : '#EDIT_UNDO',
     *     name : 'Undo',
     *     onClickCallback : function() {
     *         alert('Undo');
     *     }
     * });
     * editMenu.AddChild(undoMenuEntry); //adds an undo entry to the edit menu
     * let redoMenuEntry = new jsa.MenuEntry( {
     *     id : '#EDIT_REDO',
     *     name : 'Redo',
     *     onClickCallback : function() {
     *         alert('Redo');
     *     }
     * });
     * editMenu.AddChild(redoMenuEntry); //adds an redo entry to the edit menu
     * 
     */
    function MenuEntry(params,createDom=true) {
        CustomFlatContainer.call(this,params,false);
        UIElementWithIconA.call(this);

        //Members
        //this.data = null; //user data
        this.onClickCallback = null;
        this.style = ['jsa-menu-entry'];
        this.labelStyle = ['jsa-menu-entry-label'];
        this.hasPopup = false;


        //copy parameters
        CopyParams(this,params);

        //internals
        this.subelements = this.subelements || {};
        this.subelements.label = null;
        this.subelements.submenu = null;

        //Create DOM
        if(createDom) {
            this.CreateDom();
        }
        
        return this;
    };
    MenuEntry.prototype = Object.create(CustomFlatContainer.prototype);
    Mixin(MenuEntry,UIElementWithIconA);

    /**
     * Creates the HTML DOM element. In general, CreateDom is called automatically by the constructor. 
     * Please see [UIElementA.CreateDom]{@link UIElementA#CreateDom} for the general explanation.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method MenuEntry.prototype.CreateDom
     */
    MenuEntry.prototype.CreateDom = function() {
        if(this.hasPopup) {
            this.style.push('jsa-menu-entry-has-popup');
        }
        let content = this.content;
        this.content = '';
        CustomFlatContainer.prototype.CreateDom.call(this);
        this.content = content;
        //create a label container in order to make hover effects work correctly
        this.subelements.labelContainer = new CustomFlatContainer({
            style: ['jsa-menu-entry-label-container'],
        });
        //add a jsa label to the label container
        this.AddChild(this.subelements.labelContainer);
        this.subelements.label = new jsa.Label({
            content : content,
            icon : this.icon
        });
        this.subelements.labelContainer.AddChild(this.subelements.label);

        this.DefineRedirectContainer(this.subelements.label);
        this.DefineIconContainer(this.subelements.label,'SetIcon');

        if(!this.startEnabled) {
            this.Disable();
        }

        return this;
    }

    /**
     * Adds popup menu to this menu entry.
     * @param {Menu} submenu - The menu that pops up on this menu entry.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method MenuEntry.prototype.SetSubmenu
     */
    MenuEntry.prototype.SetSubmenu = function(submenu) {
        let oldValue = this.submenu;
        if(oldValue) this.RemoveChild(oldValue,false);
        this.AddChild(submenu,false);
        this.subelements.submenu = submenu;
        //notify
        this.Notify(new EventSet(this,'submenu',this.subelements.submenu,oldValue));
    };

    /**
     * Enable the menu entry during run-time.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method MenuEntry.prototype.Enable
     *
     * @example
     * // ...continuing the general MenuEntry example
     * undoMenuEntry.Enable(); // Undo menu looks active and can be clicked. 
     */
    MenuEntry.prototype.Enable = function() {
        if(!this.isEnabled) {
            this.GetDomElement().classList.remove('jsa-menu-entry-disabled');
            if(this.onClickCallback && this.domElement) {
                RedirectDomCallbackToUiElement(this.domElement,'click',this,this.onClickCallback);
            }
            CustomContainer.prototype.Enable.call(this);
        }
        return this;
    };

    /**
     * Disables a menu entry during run-time.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method MenuEntry.prototype.Disable
     *
     * @example
     * // ...continuing the general MenuEntry example
     * undoMenuEntry.Disable(); // Undo menu looks becomes inactive
     */
    MenuEntry.prototype.Disable = function() {
        if(this.isEnabled) {
            this.GetDomElement().classList.add('jsa-menu-entry-disabled');
            if(this.domElement) {
                RemoveRedirectDomCallbackFromUiElement(this.domElement,'click',this,this.onClickCallback);
            }
            CustomContainer.prototype.Disable.call(this);
        }
        return this;
    };

    //Override
    /**
     * Sets the content of the label dynamically.
     * @param {string} content - The new content
     * @returns {this} Instance of the element itself to enable method chaining
     * @method MenuEntry.prototype.SetContent
     * 
     * @fires [EventSet]{@link EventSet}(eventId= [EVENT.TYPES.SET_ICON]{@link EVENT}; propertyName = 'content')
     */
    MenuEntry.prototype.SetContent = function(content) {
        let oldValue = this.content;
        if(this.subelements.label) {
            this.subelements.label.SetContent(content);
        }
        this.content = content;
        //notify
        this.Notify(new EventSet(this,'content',this.content,oldValue));
        return this;
    };

    //@override
    /**
     * Returns the tooltip composed of the label content and the this.tooltip
     * @returns {string} Tooltip text.
     * @method MenuEntry.prototype.GetTooltip
     * @override
     */
    MenuEntry.prototype.GetTooltip = function() {
        let tooltip = this.content;
        if(this.tooltip) tooltip+=' ('+this.tooltip+')';
        return tooltip;
    };

    //@Override
    /**
     * Overrides [CustomFlatContainer.OnAdded()]{@link CustomFlatContainer#OnAdded} in order retrieve the level
     * of nesting of the menu entry. This is necessary to set the CSS style for popup menus 
     * correctly.
     * @param container {UIElementA} - The new container of this element.
     * @param app {Application} - The application object of the container, i.e. container.GetApp(). If the container is not part of an application, this is null.
     * @method MenuEntry.prototype.OnAdded
     *
     */
    MenuEntry.prototype.OnAdded = function(container,app) {
        CustomFlatContainer.prototype.OnAdded.call(this,container,app);
        if(this.hasPopup) {
            let popupLevel = this.level/2; //divided by 2, because the chain of menu entry and menu adds always two to the list
            if(popupLevel<MAX_MENU_POPUP_LEVEL) {
                let popupLevelStyle = 'jsa-menu-popup-level-'+popupLevel;
                this.domElement.classList.add(popupLevelStyle);
            } else {
                throw new Error('Menus with a higher nesting than '+MAX_MENU_POPUP_LEVEL+' are not supported. You requested: '+popupLevel);
            }
        }
        return this;
    };

    /* MENU */
    /**
     * @class Menu
     * @classdesc A menu is a horizontal or vertical menu composed from [MenuEntries]{@link MenuEntry}. 
     * A menu can be a static component that is always visible. Or a popup menu that is shown if a
     * menu entry of a parent menu is selected. Menu and MenuEntry can form nested and hierarchical menu
     * structures.
     *
     *       --------------------------------------------------------------
     *      |                       ----------------                       |
     *       ----------------------| Menu           |----------------------
     *                             |                |
     *                             |             ---------------
     *                             |            | Menu          |
     *                             |            |               |
     *                             |             ---------------  
     *                              ----------------
     * 
     * 
     * @param {dict} params=(see_below) - A dictionary of initialization parameters. Below for details.
     * @param {boolean} [createDom=true] - To be used for inheritance of jsa elements. If set to false the HTML DOM element will not be created, e.g. CreateDom is not called.
     *
     * @property {string} params.orientation='vertical' - Sets the orientation of the menu. 'horizontal' arranges the menu entries side by side. 'vertical' arranges the menu entries stacked over each other.
     * @property {Array.<string>} params.style=['jsa-menu']] - The CSS class(s) of the menu HTML element.
     * @property {bool} params.isPopup=false - Indicates that the menu shall open as a popup menu. Usually the menu is 
     * than attached to a [MenuEntry]{@link MenuEntry}, which has hasPopup set to true. 
     * @property {string} params.popupDirection='right' - Sets the location relative to the parent where the popup will show. Options are right, left, top, bottom.
     * @returns {this} Instance of the element itself to enable method chaining
     * @constructor Menu
     * @extends CustomFlatContainer
     * 
     * @example
     * // Create a new File menu for the application
     * // containing undo and redo
     * app = new jsa.Application({});
     * let editMenuEntry = new jsa.MenuEntry( {
     *     id :'#EDIT',
     *     name : 'Edit',
     *     hasPopup : true
     * });
     * app.menu.AddChild(editMenuEntry); //adds a new entry to the main menu
     * let editMenu = new jsa.Menu( {
     *     isPopup : true,
     *     popupDirection : 'bottom'
     * });
     * editMenuEntry.AddChild(editMenu); //adds a popup menu to  the new edit menu entry
     * let undoMenuEntry = new jsa.MenuEntry( {
     *     id : '#EDIT_UNDO',
     *     name : 'Undo',
     *     onClickCallback : function() {
     *         alert('Undo');
     *     }
     * });
     * editMenu.AddChild(undoMenuEntry); //adds an undo entry to the edit menu
     * let redoMenuEntry = new jsa.MenuEntry( {
     *     id : '#EDIT_REDO',
     *     name : 'Redo',
     *     onClickCallback : function() {
     *         alert('Redo');
     *     }
     * });
     * editMenu.AddChild(redoMenuEntry); //adds an redo entry to the edit menu
     * 
     */
    function Menu(params,createDom=true) {
        CustomFlatContainer.call(this,params,false);

        this.style = ['jsa-menu'];
        this.orientation = 'vertical';
        this.isPopup = false;
        this.popupDirection = 'right'; 

        //copy parameters
        CopyParams(this,params);

        //Create DOM
        if(createDom) {
            this.CreateDom();
        }

        return this;
    }
    Menu.prototype = Object.create(CustomFlatContainer.prototype);

    /**
     * Creates the HTML DOM element. In general, CreateDom is called automatically by the constructor. 
     * Please see [UIElementA.CreateDom]{@link UIElementA#CreateDom} for the general explanation.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method Menu.prototype.CreateDom
     */
    Menu.prototype.CreateDom = function() {
        //calculate the right style combination for the menu
        switch(this.orientation) {
            case 'horizontal': this.style.push('jsa-menu-horizontal'); break;
            case 'vertical': this.style.push('jsa-menu-vertical'); break;
            default: throw new Error('Unknown menu orientation: '+this.orientation);
        }
        if(this.isPopup) {
            this.style.push('jsa-menu-is-popup');
            switch(this.popupDirection) {
                case 'top': this.style.push('jsa-menu-is-popup-top'); break;
                case 'bottom': this.style.push('jsa-menu-is-popup-bottom'); break;
                case 'left': this.style.push('jsa-menu-is-popup-left'); break;
                case 'right': this.style.push('jsa-menu-is-popup-right'); break;
                default: throw new Error('Unknown menu popup direction: '+this.popupDirection);
            }
        }
        //add the custom style a the last entry to allow overriding
        CustomFlatContainer.prototype.CreateDom.call(this);
        
        return this;
    };

    //@Override
    /**
     * Overrides [CustomFlatContainer.OnAdded()]{@link CustomFlatContainer#OnAdded} in order retrieve the level
     * of nesting of the menu entry. This is necessary to set the CSS style for popup menus 
     * correctly.
     * @param parent {UIElementA} - The new container of this element.
     * @param app {Application} - The application object of the container, i.e. container.GetApp(). If the container is not part of an application, this is null.
     * @method Menu.prototype.OnAdded
     *
     */
    Menu.prototype.OnAdded = function(parent,app) {
        CustomFlatContainer.prototype.OnAdded.call(this,parent,app);
        if(this.isPopup) {
            let popupLevel = this.parent.level/2; //divided by 2, because the chain of menu entry and menu adds always two to the list
            if(popupLevel<MAX_MENU_POPUP_LEVEL) {
                let popupLevelStyle = 'jsa-menu-popup-level-'+popupLevel;
                this.domElement.classList.add(popupLevelStyle);
            } else {
                throw new Error('Menus with a higher nesting than '+MAX_MENU_POPUP_LEVEL+' are not supported. You requested: '+popupLevel);
            }
        }
        return this;
    };


    /* VIEW */
    /**
     * @class View
     * @classdesc A view is a UI container for a specific main aspect of an application, e.g. an editor. 
     * A view comprises a surrounding DOM element, an inner container element
     * as well optionally an header and a icon.
     * 
     *      ----------------------------------------------- 
     *     | --------------------------------------------- |
     *     || Header: icon+label (optional)               ||
     *     ||---------------------------------------------||
     *     || Container DOM element:                      ||
     *     ||                                             ||
     *     || (children are added here)                   ||
     *     ||                                             ||
     *     ||                                             ||
     *     | --------------------------------------------- |<-- surrounding DOM element
     *      -----------------------------------------------
     *
     * @param {dict} params=(see_below) - A dictionary of initialization parameters. Below for details.
     * @param {boolean} [createDom=true] - To be used for inheritance of jsa elements. If set to false the HTML DOM element will not be created, e.g. CreateDom is not called.
     *
     * @comment View parameters
     * @property {string} params.id='' The of the id. It is suggested set IDs with # in capital letters, e.g. #MYVIEW.
     * @property {string} params.name='' - The name of the view, which also appears in its header
     * @property {string} params.icon=null - The path to the icon of the view. The icon appears in front of the name in the header. (see. [Icon]{@link Icon})
     * @property {string} params.content='' - The content string placed on the view. 
     * @property {function} params.onFocusCallback=null - The function called if this view gets the focus of the user, e.g. it is becomes the active view in a view manager. The function gets no arguments, i.e. function(). 
     * @property {function} params.onUnfocusCallback=null - The function called if this view loses the focus of the user, e.g. it is becomes the inactive view in a view manager. The function gets no arguments, i.e. function().
     * @property {Array.<string>} params.style=['jsa-view']] - The CSS styles for the outer DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {Array.<string>} params.containerStyle=['jsa-view-container']] - The CSS styles for the inner DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {boolean} params.hasHeader=false - If true the view will show a header comprising its name and icon. If not, the header is not shown.
     * @property {Array.<string>} params.headerStyle=['jsa-view-header']] - The CSS styles for the header DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {boolean} params.isClosable=false - If true the view will have a close control.
     * @property {function} params.onCloseCallback - The function executed if the close control is clicked. By default the view is closed.
     * The default implementation is:
     *        function (event) {
     *           self.Close();
     *        }
     * @property {boolean} params.canPopup=false - Specifies if an popup icon is shown. This is useful for instance in combination
     * with the canDock property of [Bubble]{@link Bubble}.
     * @property {function} params.onPopupCallback - The function executed if the popup control is clicked.
     * @comment subelements
     * @property {UIElementA} this.subelements.container - (readonly) The Ui element of the view container (children are added here).
     * @property {UIElementA} this.subelements.header - (readonly) The Ui element of the header.
     * @property {UIElementA} this.subelements.headerLabel - (readonly) The Ui element of the header label.
     * @property {UIElementA} this.subelements.closeControl - (readonly) The Ui element of the close icon if isClosable is true.
     *
     * @constructor View
     * @extends CustomFlatContainer
     * @extends UIElementWithNameA
     * @extends UIElementWithIconA
     * 
     * @example
     * // Create a new view and add it to the default view manager of the application
     * app = new jsa.Application({});
     * let myView = new jsa.view({
     *   name:'My View',
     *   icon:'img/view-workspace.svg',
     *   onFocusCallback:function() { alert('My view activated');},
     *   onUnfocusCallback : function() { alert('My view deactivated');},
     *   hasHeader: true,
     *   headerStyle: ['jsa-view-header','my-view-workspace-header'],
     *   content:'Lore ipsum dolor...',
     *   isClosable: false
     * });
     * app.viewManager.AddChild(myView);
     * app.viewManager.ActivateView(myView);
     */
    function View(params,createDom=true) {
        CustomFlatContainer.call(this,params,false);
        UIElementWithNameA.call(this);
        UIElementWithIconA.call(this);

        //members
        this.content = '';
        this.onFocusCallback = null;
        this.onUnfocusCallback = null;
        this.style = ['jsa-view'];
        this.containerStyle = ['jsa-view-container'];
        this.hasHeader = false;
        this.headerStyle = ['jsa-view-header'];
        this.headerContainerStyle = ['jsa-view-header-container'];
        this.isClosable = false;
        let self = this;
        this.onCloseCallback = function (event) {
            self.Close();
        }
        this.canPopup = false;
        this.onPopupCallback = function(event) {};

        //copy parameters
        CopyParams(this,params);

        //internals
        this.subelements = this.subelements || {};
        this.subelements.container = null;
        this.subelements.header = null;
        this.subelements.headerLabel = null;
        this.subelements.closeControl = null;

        //Create DOM
        if(createDom) {
            View.prototype.CreateDom.call(this); //prevent calling the wrong CreateDOM function if inheriting this class
        }
    };

    View.prototype = Object.create(CustomFlatContainer.prototype);
    Mixin(View,UIElementWithNameA);
    Mixin(View,UIElementWithIconA);

    /**
     * Creates the HTML DOM element. In general, CreateDom is called automatically by the constructor. 
     * Please see [UIElementA.CreateDom]{@link UIElementA#CreateDom} for the general explanation.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method View.prototype.CreateDom
     */
    View.prototype.CreateDom = function() {
        let content = this.content;//temporarily store the content to prevent it is forwarded to the main UI element
        this.content = '';
        CustomFlatContainer.prototype.CreateDom.call(this);

        if(this.hasHeader) {
            this.subelements.header = new CustomFlatContainer({
                id : this.id+'-header',
                style : this.headerStyle
            });
            this.AddChild(this.subelements.header);
            this.subelements.headerLabel = new Label({
                id: this.id+'-header-label',
                content : this.name,
                icon : this.icon,
                hAlign : "center",
                vAlign : "middle"
            });
            this.subelements.header.AddChild(this.subelements.headerLabel);

            let self = this;
            if(this.isClosable) {
                this.subelements.closeControl = new Icon({
                    id: this.id+'-close-control',
                    icon: 'jsa-icon-close',
                    style: ['jsa-icon-s','jsa-icon-s-button','jsa-inline-pad-left'],
                    onClickCallback: function(event) {self.onCloseCallback(event);},
                    hasTooltip: true,
                    tooltip: 'Close this view.'
                });
                this.subelements.headerLabel.subelements.post.AddChild(this.subelements.closeControl);
            }

            if(this.canPopup) {
                this.subelements.popupControl = new Icon({
                    id: this.id+'-popup-control',
                    icon: 'jsa-icon-bubble',
                    style: ['jsa-icon-s','jsa-icon-s-button','jsa-inline-pad-left'],
                    onClickCallback : function(event) {self.onPopupCallback(event);},
                    hasTooltip: true,
                    tooltip: 'Popup view in a bubble.'
                });
                this.subelements.headerLabel.subelements.post.AddChild(this.subelements.popupControl);
            }
        }

        this.subelements.container = new CustomFlatContainer({
            id: this.id+'-container',
            style : this.containerStyle,
            content : content
        });
        this.AddChild(this.subelements.container);

        this.DefineRedirectContainer(this.subelements.container);
        this.DefineNameContainer(this.subelements.headerLabel,'SetName');
        this.DefineIconContainer(this.subelements.headerLabel,'SetContent');

        return this;
    };

    /**
     * Returns whether the view is active, i.e. it is in the focus of the user.
     * @returns {boolean} Returns true if it is in focus, and false otherwise.
     * @method View.prototype.IsActive
     *
     * @example
     * // ... extending the general View example
     * app.viewManager.AddChild(myView);
     * myView.IsActive(); //->false
     * app.viewManager.ActivateView(myView);
     * myView.IsActive(); //->true
     */
    View.prototype.IsActive = function() {
        let active = false;
        active = (this.viewManager && this.viewManager.GetActiveView() == this);
        return active;
    };

    /**
     * Gets the actual name of the view. This is to prefer over view.name
     * @returns {string} The name of the view.
     * @method View.prototype.GetName
     *
     * @example
     * // ... continuing the general View example
     * let name = myView.GetName(); //-> 'My View'
     * myView.SetName('New Name');
     * name = myView.GetName(); //-> 'New Name'
     *
     */
    View.prototype.GetName = function() {
        return this.name;
    };

    /**
     * Close this view. If the view is closable, this function is called 
     * if the user clicks the close control. By default it
     * will dissolve the view and all of its content. 
     * Overwrite it to have a customized close behaviour.
     * @method View.prototype.Close
     */
    View.prototype.Close = function() {
        this.Dissolve();
    };


    /* VIEW MANAGER */
    /**
     * @class ViewManager
     * @classdesc A view manager is a container for several views from that only
     * one view shall be active/visible at one moment. The view manager manages the 
     * switching of views.
     *
     *      ----------------------------------------------- 
     *     | ViewManager                                   |
     *     | ---------------------------------------       |
     *     || View 1                                |      |
     *     ||  ---------------------------------------     |
     *     || | ...                                   |    |
     *     || |  ---------------------------------------   |
     *     || | | View n                                 | |
     *     || | |                                        | |
     *     || | |                                        | |
     *     | -| |                                        | |
     *     |  | |                                        | |
     *     |   -|                                        |<-- the topmost view is active
     *     |    |                                        | |
     *     |     ----------------------------------------  |
     *      -----------------------------------------------
     * 
     * By default an [jsa.Application]{@link Application} has already one predefined view manager for the 
     * main content of the application, i.e. app.viewManager.
     * 
     * A view manager can be added with a [jsa.Tabbar]{@link Tabbar} in order to switch
     * views with tabs.
     * 
     * @param {dict} params=(see_below) - A dictionary of initialization parameters. Below for details.
     * @param {boolean} [createDom=true] - To be used for inheritance of jsa elements. If set to false the HTML DOM element will not be created, e.g. CreateDom is not called.
     *
     * @comment ViewManager parameters
     * @property {Array.<string>} params.style=['jsa-view-manager']] - The CSS styles for the outer DOM element. 
     * If the view manager is synchronized with a [tabbar]{@link Tabbar}, If this is true, style should be set to 
     * ['jsa-view-manager'] for correct sizing.
     * See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * 
     * @comment member vars
     * @property {View} this.activeView - (readonly) The view object that is currently in focus for this view manager
     * @property {Array.<View>} this.viewHistory - (readonly) The activation history of the views
     * 
     * @extends CustomContainerA
     * 
     * @example
     * // The default view manager of an application is created as 
     * // (This is for demonstration only you do not have to do this manually)
     * app.viewManager = new ViewManager({
     *      style: ['jsa-view-manager']
     *  });
     * // Now views can be added and activated.
     * let view1 = new jsa.view({content:'View 1'});
     * app.viewManager.AddChild(view1);
     * let view2 = new jsa.view({content:'View 2'});
     * app.viewManager.AddChild(view2);
     * app.viewManager.ActivateView(view1);
     */
    function ViewManager(params,createDom=true) {
        CustomContainerA.call(this,params,false);

        //members
        this.style = ['jsa-view-manager'];

        //copy parameters
        CopyParams(this,params);

        //internals
        this.activeView = null;
        this.viewHistory = [];

        //Create DOM
        if(createDom) {
            this.CreateDom();
        }
    };

    ViewManager.prototype = Object.create(CustomContainerA.prototype);

    /**
     * Creates the HTML DOM element. In general, CreateDom is called automatically by the constructor. 
     * Please see [UIElementA.CreateDom]{@link UIElementA#CreateDom} for the general explanation.
     * @returns {ViewManager}
     * @method ViewManager.prototype.CreateDom
     */
    ViewManager.prototype.CreateDom = function() {
        this.domElement = CreateDomElementWithUniqueId('div');
        ApplyStyles(this.style,this.domElement);
        //this.domElement.classList.add('jsa-view-manager');
        this.containerDomElement = this.domElement;
        return this;
    };

    //@Override
    /**
     * Add a new view to the view manager. New views are not activated by default.
     * @param {View} view - The view object to be added.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method ViewManager.prototype.AddChild
     *
     * @example
     * // ... excerpt of the general ViewManger example 
     * let view1 = new jsa.view({content:'View 1'});
     * app.viewManager.AddChild(view1);
     */
    ViewManager.prototype.AddChild = function(view,redirect=true) {
        //hide views by default
        view.Hide();
        CustomContainerA.prototype.AddChild.call(this,view,redirect);
        return this;
    };

    //@Override
    /**
     * Removes a view from the view manager. If the view was active, the new 
     * active view will be last one that was active.
     * @param {View} view - The view to be removed. If the view was not a child of the view manager, nothing happens.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method ViewManager.prototype.RemoveChild
     *
     * @example
     * // ... continuing the general ViewManger example 
     * app.viewManager.RemoveChild(view1);
     * app.viewManager.ActiveView(view1); //-> fails
     */
    ViewManager.prototype.RemoveChild = function(view,redirect=true) {
        this.viewHistory = this.viewHistory.filter(function(e){
            return e!=view;
        });
        if(this.activeView==view) { //change view if the first is removed
            let nViewsInHistory = this.viewHistory.length //activate the last active one.
            if(0<nViewsInHistory) {
                this.ActivateView(this.viewHistory[nViewsInHistory-1]);
            } else {
                this.ActivateView(null);
            }
        }
        CustomContainerA.prototype.RemoveChild.call(this,view,redirect);
        return this;
    };

    /**
     * Actives a given view. The active view will come in front and hide the others.
     * The last active view will get deactivated.
     * @param {View} view - The view to be activated
     * @returns {this} Instance of the element itself to enable method chaining
     * @fires [EventSet]{@link EventSet}(eventId= [EVENT.TYPES.SET_ACTIVE_VIEW]{@link EVENT}; propertyName = 'activeView')
     * @method ViewManager.prototype.ActivateView
     *
     * @example
     * // ... excerpt of the general ViewManger example 
     * let view1 = new jsa.view({content:'View 1'});
     * app.viewManager.AddChild(view1); //-> view is not active/shown
     * app.viewManager.ActivateView(view1); //->view is active/shown
     */
    ViewManager.prototype.ActivateView = function(view) {
        let lastActiveView = this.activeView;
        if(!view) { //disable all views. This could happen
            this.activeView = null;
        } else if(this.children.includes(view)) {
            if(view != this.activeView) {
                //hide the current active view
                for(let i=0;i<this.children.length;i++) {
                    let v = this.children[i];
                    if (v == lastActiveView){
                        if(v.onUnfocusCallback) {
                            v.onUnfocusCallback();
                        }
                        v.Hide();
                        break;
                    }
                }
                for(let i=0;i<this.children.length;i++) {
                    let v = this.children[i];
                    if(view==v) {
                        v.Show();
                        if(v.onFocusCallback) {
                            v.onFocusCallback();
                        }
                        break;
                    }
                }
                this.activeView = view;
                this.viewHistory.push(view);
            }
        } else {
            throw new Error('View is unknown to the view manager');
        }
        //notify observers
        this.Notify(new EventSet(this,'activeView',this.activeView, lastActiveView));
        return this;
    };

    /**
     * Returns the current active view.
     * @returns {View} The view object that is active, i.e. in focus.
     * @method ViewManager.prototype.GetActiveView
     *
     * @example
     * // ... continuing the general ViewManger example 
     * app.viewManager.ActiveView(view1); 
     * let activeView = app.viewManager.GetActiveView(); //-> view1
     * app.viewManager.ActiveView(view2); 
     * activeView = app.viewManager.GetActiveView(); //-> view2
     */
    ViewManager.prototype.GetActiveView = function() {
        return this.activeView;
    };


   
    /*BUBBLE*/
    /**
     * @class Bubble
     * @classdesc A bubble is a pop-up UI container. It is intended to appear 
     * temporarily to show some information or provide edit functionality
     * close to the users mouse. It provides means to automatically detect
     * the best area to open as well as pointing visually at the element
     * to be edited by an arrow. Moreover, auto-hide, minimize, and drag&drop
     * are possible. The behaviour can be strongly customized.
     * 
     *        --------------
     *      /                \
     *      |  Bubble        |
     *      |                |>  <-- points to clicked element
     *      |                |
     *      \                /
     *        --------------
     * 
     * @param {dict} params=(see_below) - A dictionary of initialization parameters. Below for details.
     * @param {boolean} [createDom=true] - To be used for inheritance of jsa elements. If set to false the HTML DOM element will not be created, e.g. CreateDom is not called.
     *
     * @comment Bubble parameters
     * @property {string} params.name='' - The name of the bubble. This is shown if minimized.
     * @property {boolean} params.isMinimizable=true - If true the bubble shows a minimize icon and can 
     * shrink to a small movable box. This also stops it from popping up on further clicks.
     * @property {boolean} params.isMinimized=false - If true the bubble starts in the minimized version, see params.isMinimizable.
     * @property {boolean} params.isResizable=true - If true the bubble has resize controls in the edges. The 
     * @property {boolean} params.isClosable=true - If true the bubble has a close icon. A click on it hides the bubble.
     * @property {boolean} params.autoHide=false - If true, the Bubble closes automatically if clicked outside of the bubble.
     * @property {int} params.autoHideDelay=100 - Defines the wait time in ms after opening before autoHide becomes active. This can prevent double click artifacts. 
     
     * @property {string} params.content='' - The string to be shown in the bubble. Leave this empty, if further UI element shall be added as children.
     * @property {Array.<string>} params.style=[]] - The CSS styles for the outer DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {Array.<string>} params.containerStyle=[]] - The CSS styles for the inner DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     *
     * @property {boolean} params.canDock=false - If true, an control is shown on the bubble that allows moving its content into a view in
     * a given view manager. Instead of the bubble the view will be shown. If desired the view can be popped out again in a bubble.
     * @property {View} params.dockView=null - A view element, which is not attached to any view manager or other parent. It will be attached to the view manager
     * if dock is clicked by the user.
     * @property {ViewManager} params.dockViewManager=null - The view manager element to attach the view with the bubble content to if the user 
     * clicks dock
     * @property {int} params.borderOffset=20 - For this area in pixels from the border of the browsers rendering area
     * is not allocated by the bubble. Even if clicked in the border area.
     * @property {int} params.arrowHeight=20 - The width of the indication mark in pixels. 
     * This value assumes a left or right pointing indication mark.
     * @property {int} params.arrowWidth=40 - The height of the indication mark in pixels. 
     * This value assumes a left or right pointing indication mark.
     * @property {int} params.borderRadius=15 - The border radius in pixels of the outer DOM element. This is necessary to prevent
     * that indication marks are shown on the rounded corner. Make sure this equals the border radius in the CSS style.
     * @property {float} params.penaltyN=0.0 - The bubble decides on the side with the most space left to pop up. 
     * To influence this is the penalty for being north of the clicked position. Chose from 0 to 1. 1 should make it impossible for 
     * the bubble to appear north of the object (depending on the other penalties).
     * @property {float} params.penaltyE=0.0 - The bubble decides on the side with the most space left to pop up. 
     * To influence this is the penalty for being east of the clicked position. Chose from 0 to 1. 1 should make it impossible for 
     * the bubble to appear east of the object (depending on the other penalties).
     * @property {float} params.penaltyS=0.0 - The bubble decides on the side with the most space left to pop up. 
     * To influence this is the penalty for being south of the clicked position. Chose from 0 to 1. 1 should make it impossible for 
     * the bubble to appear south of the object (depending on the other penalties).
     * @property {float} params.penaltyW=0.0 - The bubble decides on the side with the most space left to pop up. 
     * To influence this is the penalty for being west of the clicked position. Chose from 0 to 1. 1 should make it impossible for 
     * the bubble to appear west of the object (depending on the other penalties).
     * @property {int} params.minimizedX=0 - The desired position for the minimized bubble left.
     * @property {int} params.minimizedY=0 - The desired position for the minimized bubble top. 
     * 
     * @comment internals
     * @property {timeout} this.autoHideDelayTimeout=null - (readonly) The timeout object after which the bubble hides.
     * @property {boolean} this.autoHideLock=true - (readonly) While true, the bubble will not hide if clicked outside.
     * @property {function} this.onClickDocumentCloseBubble - (readonly) Callback 
     * @property {function} this.releaseAutoHideLockMouse - (readonly) Event listener for onmouseout events.
     * @property {function} this.releaseAutoHideLock - (readonly) Event listener for onmouseover events.
     * @property {function} this.engageAutoHideLock - (readonly) Callback after the auto-hide lock timeout.
     * @property {boolean} this.isDocked - (readonly) Whether the bubble is docked or not.
     *
     * @returns {this} Instance of the element itself to enable method chaining
     * @constructor Bubble
     * @extends CustomFlatContainer
     * 
     * @example
     * // Create a bubble that pops up when clicking a link.
     * app = new jsa.Application({});
     * bubble = new jsa.Bubble({
     *   content:'This is a link you clicked',
     *   autoHide:true,
     *   closeable: false
     * })
     * app.AddChild(bubble)
     * // Create the link an make it open the 
     * link = new jsa.CustomFlatContainer({
     *   elementType:'a',
     *   content:'Click Me',
     *   onClickCallback: function(evt) {
     *     bubble.PopupOnDomElement(this.GetDomElement());
     *   }
     * });
     * my
     */
    function Bubble(params,createDom=true) {
        CustomFlatContainer.call(this,params,false);
        //default arguments
        this.name = '';
        this.isMinimizable = false;
        this.isMinimized = false;
        this.isResizable = false;
        this.isClosable = false;
        this.autoHide = false; //if Bubble should close if clicked outside
        this.autoHideDelay = 100; //defines the wait time after opening before autoHide becomes active
        this.content = '';
        this.style = ['jsa-bubble'];
        this.containerStyle = ['jsa-bubble-container'];
        this.canDock = false;
        this.dockView = null;
        this.dockViewManager = null;
        
        this.borderOffset = 20; //px
        this.arrowHeight = 20; //px
        this.arrowWidth = 40; //px
        this.borderRadius = 15; //px
        //prefer some directions with a low penalty
        this.penaltyN = 0.0;
        this.penaltyE = 0.0;
        this.penaltyS = 0.0;
        this.penaltyW = 0.0;
        //start position for the minimized bubble
        this.minimizedX = 0;
        this.minimizedY = 0;

        this.popupOffset = 0; // Moves the position required slightly in the direction of the bubble. This can be used to prevent onmouseover events on the bubble if it opens on the mouse position.

        //copy parameters
        CopyParams(this,params);

        //internals
        this.autoHideDelayTimeout = null;
        this.isDocked = false;

        //subelements
        this.container = null;
        this.controlsContainer = null;
        this.minimizedBubble = null;
        this.button = {};
        this.button.dock = null;
        this.button.minimize = null;
        this.button.close = null;
        this.button.restore = null;

        //internal callbacks
        let self = this;
        this.autoHideLock = true;
        this.onClickDocumentCloseBubble = function(event) {
            if(!self.autoHideLock) {
                self.Hide();
            }
        };

        this.releaseAutoHideLockMouse = function(event){
            let rect = self.domElement.getBoundingClientRect();
            if(event.clientX < rect.left || event.clientX > rect.right ||
                event.clientY < rect.top || event.clientY > rect.bottom) {
                self.autoHideLock = false;
            }
        };
        this.releaseAutoHideLock = function(){
            self.autoHideLock = false;
        };
        this.engageAutoHideLock = function(){
            self.autoHideLock = true;
        };
        
        //create DOM
        if(createDom) {
            this.CreateDom();
        }
        
        return this;
    };

    Bubble.prototype = Object.create(CustomFlatContainer.prototype);

    /**
     * Creates the HTML DOM element. In general, CreateDom is called automatically by the constructor. 
     * Please see [UIElementA.CreateDom]{@link UIElementA#CreateDom} for the general explanation.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method Bubble.prototype.CreateDom
     */
    Bubble.prototype.CreateDom = function() {
        let content = this.content;
        this.content = '';
        CustomFlatContainer.prototype.CreateDom.call(this);
        this.content = content;

        //arrows
        this.arrow = {};
        this.arrow.n = CreateDomElementWithUniqueId('div');
        this.arrow.n.classList.add('jsa-bubble-arrow');
        this.arrow.n.classList.add('jsa-bubble-arrow-n');
        this.domElement.appendChild(this.arrow.n);
        this.arrow.e = CreateDomElementWithUniqueId('div');
        this.arrow.e.classList.add('jsa-bubble-arrow');
        this.arrow.e.classList.add('jsa-bubble-arrow-e');
        this.domElement.appendChild(this.arrow.e);
        this.arrow.s = CreateDomElementWithUniqueId('div');
        this.arrow.s.classList.add('jsa-bubble-arrow');
        this.arrow.s.classList.add('jsa-bubble-arrow-s');
        this.domElement.appendChild(this.arrow.s);
        this.arrow.w = CreateDomElementWithUniqueId('div');
        this.arrow.w.classList.add('jsa-bubble-arrow');
        this.arrow.w.classList.add('jsa-bubble-arrow-w');
        this.domElement.appendChild(this.arrow.w);

        this.container = new CustomFlatContainer({
            content: this.content,
            style: this.containerStyle 
        });
        this.AddChild(this.container);

        this.DefineRedirectContainer(this.container);

        //create a compartment for the buttons
        this.controlsContainer = new CustomFlatContainer({
            id: this.id+'-controls-container',
            style: ['jsa-bubble-controls-container']
        })
        this.AddChild(this.controlsContainer,false);

        //add the required controls
        this.button = {};
        let self = this;
        if(this.canDock) {
            this.button.dock = new Icon({
                id: this.id+'-dock-control',
                icon: 'jsa-icon-view',
                style: ['jsa-icon','jsa-icon-m','jsa-icon-m-button'],
                onClickCallback: function(event) {
                    self.Dock();
                },
                hasTooltip: true,
                tooltip: 'Dock this bubble as a view.'
            });
            this.controlsContainer.AddChild(this.button.dock);
        }

        if(this.isMinimizable) {
            //create the minimize controls
            this.button.minimize = new Icon({
                id: this.id+'-minimize-control',
                icon: 'jsa-icon-minimize',
                style: ['jsa-icon','jsa-icon-m','jsa-icon-m-button'],
                onClickCallback: function(event) {
                    self.Minimize();
                },
                hasTooltip: true,
                tooltip: 'Minimize (stops further popups).'
            });
            this.controlsContainer.AddChild(this.button.minimize);
            //create the minimized version, which is initially hidden ...
            this.minimizedBubble = new CustomFlatContainer({
                id: this.id+'-minimized',
                style: ['jsa-bubble-minimized'],
                content: this.name
            });
            this.AddChild(this.minimizedBubble,false);
            //... and its restore button
            this.button.restore = new Icon({
                id: this.id+'-restore-control',
                icon: 'jsa-icon-maximize',
                style: ['jsa-icon','jsa-icon-m','jsa-icon-m-button','jsa-bubble-restore'],
                onClickCallback: function(event) {
                    self.Restore();
                },
                hasTooltip: true,
                tooltip: 'Restore.'
            });
            this.minimizedBubble.AddChild(this.button.restore);
            //make it movable
            $( this.minimizedBubble.GetDomElement() ).draggable(); //jQuery UI
            this.minimizedBubble.GetDomElement().style.position = 'absolute'; //somehow draggable changes this;
        }

        if(this.isClosable) {
            this.button.close = new Icon({
                id: this.id+'-close-control',
                icon: 'jsa-icon-close',
                style: ['jsa-icon','jsa-icon-m','jsa-icon-m-button'],
                onClickCallback: function(event) {
                    self.Close();
                },
                hasTooltip: true,
                tooltip: 'Close.'   
            });
            this.controlsContainer.AddChild(this.button.close);
        }

        if(this.isResizable) {
            $( this.domElement ).resizable({handles: 'se'}); //jQuery UI
        }

        this.Hide();

        return this;
    };

    /**
     * Docks this bubble as a view in the given view manager and 
     * moves all of its content to the view. 
     * @returns {this} Instance of the element itself to enable method chaining
     * @method Bubble.prototype.Dock
     *
     * @example
     * // ... continuing the general Bubble example
     * bubble.Dock(); //Bubble becomes a view
     */
    Bubble.prototype.Dock = function() {
        
        if(this.canDock&&this.dockView&&this.dockViewManager&&!this.isDocked) {
            this.Hide();
            this.dockViewManager.AddChild(this.dockView);
            this.dockView.AddChild(this.container); //redirect the bubble container in the view
            let self = this;
            this.dockView.onPopupCallback = function(evt) {
                self.Undock();
            }
            this.dockViewManager.ActivateView(this.dockView);
            this.isDocked = true;
        }
        return this;
    };

    /**
     * Undocks this bubble from a view after being docked.  
     * Moves all of its content back to the bubble.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method Bubble.prototype.Undock
     *
     * @example
     * // ... continuing the general Bubble example
     * bubble.Dock(); //Bubble becomes active again.
     */
    Bubble.prototype.Undock = function() {
        
        if(this.canDock&&this.dockView&&this.dockViewManager&&this.isDocked) {
            this.AddChild(this.container,false); //redirect the bubble container back here. False is necessary, to prevent the container from being added to itself.
            this.dockViewManager.RemoveChild(this.dockView);
            this.isDocked = false;
            this.Show();
        }
        return this;
    };


    /**
     * Manually hides the bubble if it is popped up. In minimized mode nothing happens. 
     * @method Bubble.prototype.Hide
     *
     * @example
     * // ... continuing the general Bubble example
     * bubble.Hide(); //Bubble disappears
     */
    Bubble.prototype.Hide = function() {
        if(this.autoHide) {
            if(this.isVisible) {
                window.clearTimeout(this.autoHideDelayTimeout);
                //this.GetDomElement().removeEventListener('mousedown', this.onClickBubbleStayOpen);
                this.GetDomElement().removeEventListener('mouseout', this.releaseAutoHideLockMouse);
                this.GetDomElement().removeEventListener('mouseover', this.engageAutoHideLock);
                document.removeEventListener('mousedown', this.onClickDocumentCloseBubble);
                CustomContainerA.prototype.Hide.call(this);
            }
        } else {
            CustomContainerA.prototype.Hide.call(this);
        }
    };

    /**
     * Manually shows the bubble if it is hidden. The bobble will show on 
     * its last pop up position or the initial position. Use the Popup...
     * methods to set position and location concurrently.
     * In minimized mode nothing happens. 
     * @method Bubble.prototype.Show
     *
     * @example
     * // ... continuing the general Bubble example
     * bubble.Show(); //Bubble shows
     */
    Bubble.prototype.Show = function() {
        if(this.isDocked) {
            //do not activate this automatically
            //this.dockViewManager.ActivateView(this.dockView);
        } else {
            if(this.autoHide) {
                if(!this.isVisible) {
                    this.GetDomElement().addEventListener('mouseout', this.releaseAutoHideLockMouse);
                    this.GetDomElement().addEventListener('mouseover', this.engageAutoHideLock);
                    document.addEventListener('mousedown', this.onClickDocumentCloseBubble);
                    CustomContainerA.prototype.Show.call(this);
                    /*HACK: Delay the auto hide function, otherwise event propagation it will 
                    immediately close the bubble with the same event. 
                    Moreover, the delay prevents double click issues. */
                    this.autoHideLock = true;
                    let self = this;
                    this.autoHideDelayTimeout = window.setTimeout(function() {
                        self.releaseAutoHideLock();
                    },this.autoHideDelay);
                }
            } else {
                CustomContainerA.prototype.Show.call(this);
            }
        }
        return this;
    };

    /**
     * Let the bubble show connected to the bounding rectangle of a 
     * defined HTML DOM element. This method will automatically calculate 
     * the best area for the bubble to pop up (i.e. the one with the most 
     * screen space left), positions the bubble and the indication arrow, 
     * and shows the Bubble. It is the preferred way of using a bubble.
     * @param {HTML_DOM_ELEMENT} domElement - The DOM element this bubble refers to an pops up next to.
     * @method Bubble.prototype.PopupOnDomElement
     *
     * @example
     * // ... continuing the general Bubble example
     * // make the bubble pop on an arbitrary HTML link
     * &lt;a id="new-link" href="#"&gt;New Link&lt;/a&gt;
     * ...
     * bubble.PopupOnDomElement(document.getElementById('new-link')); //Bubble shows close to the link
     */
    Bubble.prototype.PopupOnDomElement = function(domElement) {
        let rect = domElement.getBoundingClientRect();

        let left = rect.left;
        let top = rect.top;
        let cx = left+rect.width/2;
        let cy = top+rect.height/2;

        cx = this.ClipXToBounds(cx);
        cy = this.ClipYToBounds(cy);

        let dir = this.CalcPreferredPopupDirection(cx,cy);

        //find the right border of the element
        let x = 0;
        let y = 0;
        switch(dir) {
            case 'n':
                x = cx;
                y = rect.top;
                break;
            case 'e':
                x = rect.right;
                y = cy;
                break;
            case 's':
                x = cx;
                y = rect.bottom;
                break;
            case 'w':
                x = rect.left;
                y = cy;
                break;
        }
        this.Popup(x,y,dir);
    };

    /**
     * Shows the bubble pointing at a specific screen position. This can be used if
     * no DOM element is known or exists that this bubble should point at.
     * @param {int} x - x position (left) in pixels for the bubble indicator to point at
     * @param {int} y - y position (top) in pixels for the bubble indicator to point at
     * @param {string} dir=null - One of 'n','e','s','w'. If null, the direction with the most free space is automatically chosen.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method Bubble.prototype.Popup
     * 
    * @example
     * // ... continuing the general Bubble example
     * // make the bubble pop up on pixel 200 from the top and 300 
     * // from the left and pointing to the right
     * bubble.Popup(300,200,'w'); 
     */
    Bubble.prototype.Popup = function(x,y,dir=null) {
        //bring positions within the bounds

        if(!this.isMinimized) {
            //show the dialog
            this.Show();
        }

        if(this.isDocked) {
            this.Show();
            return this; //quit here
        }


        let bw = GetBrowserWidth();
        let bh = GetBrowserHeight();

        //map x and y in the feasible region, which is the boundary + the array tip width
        x = this.ClipXToBounds(x);
        y = this.ClipXToBounds(y);


        //retrieve the current position
        let rect = this.domElement.getBoundingClientRect();
        let w = rect.width;
        let h = rect.height;
        let oldX = rect.left;
        let oldY = rect.top;
        
        if(!dir) {
            dir = this.CalcPreferredPopupDirection(x,y);
        }
        let arrowDir = DIRECTION_OPPOSITE[dir];//the arrow direction is inverse to the popup direction

        //The minimum border distance should win

        //disable all directions except the desired one
        let self = this;
        let directions = ['n','e','s','w']; 
        directions.forEach( function (element) {
            if(arrowDir==element) {
                self.arrow[element].style.visibility = 'inherit';
            } else {
                self.arrow[element].style.visibility = 'hidden';
            }
        });

        //switch case for directions
        let cornerMinDistance = this.arrowWidth/2+this.borderRadius; // //of the arrow to prevent artifacts
        let  newX = 0; //calculated below
        let  newY = 0; //calculated below
        switch(dir) {
            case 's': {
                let  offset = w/2;
                let  offsetCorrection = 0;
                if((x-this.borderOffset)<offset) {
                    offsetCorrection = -(offset-(x-this.borderOffset));
                } else if((bw-x-this.borderOffset)<offset) {
                    offsetCorrection = (offset-(bw-x-this.borderOffset));
                }
                offset += offsetCorrection;

                
                newX = (x-offset);
                newY = (y+this.arrowHeight)+this.popupOffset;

                this.domElement.style.left = newX+'px';
                this.domElement.style.top = newY+'px';

                let arrowOffset = Math.max(cornerMinDistance,Math.min(offset,w-cornerMinDistance));
                this.arrow[arrowDir].style.left = arrowOffset+'px';

                if(this.isResizable) {
                    if(offsetCorrection<0) {
                        $( this.domElement ).resizable( "option", "handles", "se" );
                    } else if(offsetCorrection>0) {
                        $( this.domElement ).resizable( "option", "handles", "sw" );
                    } else {
                        $( this.domElement ).resizable( "option", "handles", "se, sw" );
                    }
                }
                break;
            }  

            case 'w': {
                let  offset = h/2;
                let  offsetCorrection = 0;
                if((y-this.borderOffset)<offset) {
                    offsetCorrection = -(offset-(y-this.borderOffset));
                } else if((bh-y-this.borderOffset)<offset) {
                    offsetCorrection = (offset-(bh-y-this.borderOffset));
                }
                offset += offsetCorrection;

                
                newX = (x-w-this.arrowHeight)-this.popupOffset;
                newY = (y-offset);

                this.domElement.style.left = newX+'px';
                this.domElement.style.top = newY+'px';

                this.arrow[arrowDir].style.top = (offset)+'px';

                if(this.isResizable) {
                    if(offsetCorrection<0) {
                        $( this.domElement ).resizable( "option", "handles", "nw" );
                    } else if(offsetCorrection>0) {
                        $( this.domElement ).resizable( "option", "handles", "sw" );
                    } else {
                        $( this.domElement ).resizable( "option", "handles", "nw, sw" );
                    }
                }
                break;
            }
                    
            case 'n': {
                let  offset = w/2;
                let  offsetCorrection = 0;
                if((x-this.borderOffset)<offset) {
                    offsetCorrection = -(offset-(x-this.borderOffset));
                } else if((bw-x-this.borderOffset)<offset) {
                    offsetCorrection = (offset-(bw-x-this.borderOffset));
                }
                offset += offsetCorrection;

                
                newX = (x-offset);
                newY = (y-h-this.arrowHeight)-this.popupOffset;

                this.domElement.style.left = newX+'px';
                this.domElement.style.top = newY+'px';

                let arrowOffset = Math.max(cornerMinDistance,Math.min(offset,w-cornerMinDistance));
                this.arrow[arrowDir].style.left = arrowOffset+'px';

                if(this.isResizable) {
                    if(offsetCorrection<0) {
                        $( this.domElement ).resizable( "option", "handles", "ne" );
                    } else if(offsetCorrection>0) {
                        $( this.domElement ).resizable( "option", "handles", "nw" );
                    } else {
                        $( this.domElement ).resizable( "option", "handles", "ne, nw" );
                    }
                }
                break;
            }


            case 'e': {
                let  offset = h/2;
                let  offsetCorrection = 0;
                if((y-this.borderOffset)<offset) {
                    offsetCorrection = -(offset-(y-this.borderOffset));
                } else if((bh-y-this.borderOffset)<offset) {
                    offsetCorrection = (offset-(bh-y-this.borderOffset));
                }
                offset += offsetCorrection;

                
                newX = (x+this.arrowHeight)+this.popupOffset;
                newY = (y-offset);

                this.domElement.style.left = newX+'px';
                this.domElement.style.top = newY+'px';

                this.arrow[arrowDir].style.top = (offset)+'px';

                if(this.isResizable) {
                    if(offsetCorrection<0) {
                        $( this.domElement ).resizable( "option", "handles", "ne" );
                    } else if(offsetCorrection>0) {
                        $( this.domElement ).resizable( "option", "handles", "se" );
                    } else {
                        $( this.domElement ).resizable( "option", "handles", "ne, se" );
                    }
                }
                break;
            }
        }

        //correction the position of the minimized version
        if(this.isMinimizable) {
            //calculate the minimize child position as if it is a global absolute position.
            let nx = this.minimizedX-newX;
            let ny = this.minimizedY-newY;
            this.minimizedBubble.GetDomElement().style.left = nx +'px';
            this.minimizedBubble.GetDomElement().style.top = ny +'px';
        }

        return this; //returning this allows calling methods in a chain;
    };

    /**
     * Used internally to map x coordinates in the border area to the closest feasible position.
     * @param {int} x - Original x position
     * @returns {int} Clipped x position
     * @method Bubble.prototype.ClipXToBounds
     */
    Bubble.prototype.ClipXToBounds = function(x) {
        let  bw = GetBrowserWidth();
        return Math.min(Math.max(this.borderOffset+this.arrowHeight,x),bw-this.borderOffset-this.arrowHeight);
    };

    /**
     * Used internally to map y coordinates in the border area to the closest feasible position.
     * @param {int} y - Original y position
     * @returns {int} Clipped y position
     * @method Bubble.prototype.ClipYToBounds
     */
    Bubble.prototype.ClipYToBounds = function(y) {
        let  bh = GetBrowserHeight();
        return Math.min(Math.max(this.borderOffset+this.arrowHeight,y),bh-this.borderOffset-this.arrowHeight);
    };

    /**
     * Used internally to get the side of the desired popup position with the
     * most space left relative to the given penalty factors.
     * @param {int} x - Desired x position (left) in pixels
     * @param {int} y - Desired y position (top) in pixels
     * @returns {string} One of 'n','e','s','w'.
     * @method Bubble.prototype.CalcPreferredPopupDirection
     */
    Bubble.prototype.CalcPreferredPopupDirection = function(x,y) {
        let  bw = GetBrowserWidth();
        let  bh = GetBrowserHeight();

        //map x and y in the feasible region, which is the boundary + the array tip width
        x = Math.min(Math.max(this.borderOffset+this.arrowHeight,x),bw-this.borderOffset-this.arrowHeight);
        y = Math.min(Math.max(this.borderOffset+this.arrowHeight,y),bh-this.borderOffset-this.arrowHeight);

        //retrieve the current position
        let  rect = this.domElement.getBoundingClientRect();
        
        let  w = rect.width;
        let  h = rect.height;

        let dir = 'n' //north is the default popup dir
        //first check for no-go areas
        if(y<h) {
            dir = 's';
        } else if(y>bh-h) {
            dir = 'n';
        } else if(x<w) {
            dir = 'e';
        } else if(x>bw-w) {
            dir = 'w';
        } else { //if not clear decision can be made decide by the largest space left
            let nOffset = y;
            let sOffset = bh-y;
            let wOffset = x;
            let eOffset = bw-x;

            let offsets = [(-this.penaltyN*bh)+nOffset,(-this.penaltyE*bw)+eOffset,(-this.penaltyS*bh)+sOffset,(-this.penaltyW*bw)+wOffset]; //prefer north and south by adding penalities to the others
            let directions = ['n','e','s','w']; 

            let maxOffset = Math.max.apply(null,offsets);
            let maxIndex = offsets.findIndex(function(element) {
                return (maxOffset==element);
            });
            dir = directions[maxIndex];
        }

        return dir;
    };

    /**
     * Manually minimizes the bubble. In minimized mode, it stays always visible, but hides
     * its content. The minimized version can be dragged around.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method Bubble.prototype.Minimize
     *
     * @example
     * // ... continuing the general Bubble example
     * bubble.Popup(300,200,'w');
     * bubble.Minimize(); //-> Bubble changes in minimized mode
     */
    Bubble.prototype.Minimize = function() {
        if(!this.isMinimized) {
            this.domElement.style.visibility = 'hidden';
            this.container.Hide()
            this.minimizedBubble.GetDomElement().style.visibility = 'visible';
            this.isMinimized = true;
        }
        return this; //returning this allows calling methods in a chain;
    };

    /**
     * Manually sets the bubble back to the normal mode after it was minimized.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method Bubble.prototype.Restore
     *
     * @example
     * // ... continuing the general Bubble example
     * bubble.Popup(300,200,'w');
     * bubble.Minimize(); //-> Bubble changes in minimized mode
     * bubble.Restore(); //-> Bubble changes to normal (full) mode
     */
    Bubble.prototype.Restore = function() {
        if(this.isMinimized) {
            this.domElement.style.visibility = 'visible';
            this.container.Show()
            this.minimizedBubble.GetDomElement().style.visibility = 'hidden';
            this.isMinimized = false;
        }
        return this; //returning this allows calling methods in a chain;
    };

    /**
     * Manually closes the bubble. By default this has the same effect as 
     * [Hide()]{@link Bubble#Hide}. This function is called if the close icon 
     * of the bubble is clicked. Overwrite it to implement a custom close 
     * behaviour.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method Bubble.prototype.Close
     *
     * @example
     * // ... continuing the general Bubble example
     * bubble.Popup(300,200,'w');
     * bubble.Close(); //-> Bubble hides
     */
    Bubble.prototype.Close = function() {
        this.Hide();
        return this; //returning this allows calling methods in a chain;
    };

    /**
     * Changes the content of the bubble during runtime.
     * @param {string} content - The content to be shown. '' deletes the current content.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method Bubble.prototype.SetContent
     * 
     * @fires [EventSet]{@link EventSet}(eventId= [EVENT.TYPES.SET_CONTENT]{@link EVENT}; propertyName = 'content')
     *
     * @example
     * // ... continuing the general Bubble example
     * bubble.SetContent('I am the new popup message!');
     */
    Bubble.prototype.SetContent = function(content) {
        let oldValue = this.content;
        if(this.container) this.container.SetContent(content);
        this.content = content;
        //notify observers
        this.Notify(new EventSet(this,'name',this.content,oldValue));
        return this;
    };

    /**
     * Backup function to restore the bubble and its functionality if the bubble gets lost, e.g. it was 
     * dragged in minimized mode outside the screen. It resets the bubble position to (0,0) and shows the
     * bubble.
     * @method Bubble.prototype.Reset
     */
    Bubble.prototype.Reset = function() {
        this.domElement.style.left = '0px';
        this.domElement.style.top = '0px';
        this.minimizedBubble.GetDomElement().style.left = '0px'; 
        this.minimizedBubble.GetDomElement().style.top = '0px'; 
        this.Show();
    };


    /*STICKY*/
    /**
     * @class Sticky
     * @classdesc The sticky is a UI element that sticks to the screen in one of the corners. 
     * It is visualized by an icon and has a content area attached to it. The content area 
     * can be shown and hidden by clicking the sticky icon.
     * 
     *       ____                                       ____    
     *      /icon\--------------          -------------/icon\   
     *      \____/ Sticky NW    |        | Sticky NE   \____/    
     *         |   container    |        |   container    |     
     *          ----------------          ----------------     
     *                                                
     *          ----------------          ----------------
     *         |  Sticky SW     |        | Sticky SE      |
     *        ____   container  |        | container     ____  
     *       /icon\-------------          --------------/icon\
     *       \____/                                     \____/
     *
     * @param {dict} params=(see_below) - A dictionary of initialization parameters. Below for details.
     * @param {boolean} [createDom=true] - To be used for inheritance of jsa elements. If set to false the HTML DOM element will not be created, e.g. CreateDom is not called.
     *
     * @comment Sticky parameters
     * @property {string} params.direction='nw' - One of 'nw','ne','se','sw'. Defines the location of the content of the sticky relative to its icon.
     * It defines also the position by automatically applying the CSS class jsa-sticky-<dir>.
     * @property {string} params.icon='' - Path to the icon of the sticky.
     * @property {boolean} params.startEnabled=true - If disabled the icon is shown, but the content area does not open on clicking.
     * @property {boolean} params.startCollapsed=false - Whether the sticky shall start in the collapsed or uncollapsed state.
     * @property {boolean} params.isResizable=true - Whether the content area of the sticky can be resized or not. 
     * Resizing is always only possible in the directions pointing away from the stick icon.
     * @property {string} params.content='' - The content of the sticky. Leave empty, if you would like to add child controls via AddChild(...).
     * @property {Array.<string>} params.style=['jsa-sticky']] - The CSS styles for the outer DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {Array.<string>} params.containerStyle=['jsa-sticky-container']] - The CSS styles for the inner DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {Array.<string>} params.togglerStyle=['jsa-icon','jsa-icon-l','jsa-icon-l-button','jsa-sticky-toggler']] - The CSS styles for the toggler DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @comment Sticky internals
     * @property {string} this.actualContainerDisplayStyle - (readonly) Internal storage to remember the CSS style of the container DOM element
     * @property {boolean} this.isCollapsed - (readonly) If the sticky is currently collapsed or not.
     * stickies content DOM element in collapsed mode.
     * @comment subelements
     * @property {UIElementA} this.subelements.container - (readonly) The  UI element of the container (Children are added here).
     * @property {UIElementA} this.subelements.toggler - (readonly) The UI element of the toggle icon.
     *
     * @returns {this} Instance of the element itself to enable method chaining
     * @constructor Sticky
     * @extends CustomContainerA
     * @extends UIElementWithIconA
     * 
     * @example
     * //creating a sticky in the lower left corner showing a globe symbol.
     * let  stickySe = new jsa.Sticky( {
     *     direction : 'se',
     *     icon : 'img/globe.svg',
     *     content : 'I am a sticky SE!!',
     * });
     * app.AddChild(stickySe)
     */
    function Sticky(params,createDom=true) {
        CustomFlatContainer.call(this,params,false);
        UIElementWithIconA.call(this);
        //default arguments
        this.direction = 'nw';
        this.startCollapsed = false;
        this.isResizable = true;
        this.content = '';
        this.style = ['jsa-sticky'];
        this.containerStyle = ['jsa-sticky-container'];
        this.togglerStyle = ['jsa-icon','jsa-icon-l','jsa-icon-l-button','jsa-sticky-toggler'];

        //copy parameters
        CopyParams(this,params);
        

        //internals
        this.actualContainerDisplayStyle = 'inherit';
        this.isCollapsed = false;
        this.subelements = this.subelements || {};
        this.subelements.toggler = null;
        this.subelements.container = null;

        //create DOM
        if(createDom) {
            this.CreateDom();
        }
        
        return this;
    };

    Sticky.prototype = Object.create(CustomFlatContainer.prototype);
    Mixin(Sticky,UIElementWithIconA);

    /**
     * Creates the HTML DOM element. In general, CreateDom is called automatically by the constructor. 
     * Please see [UIElementA.CreateDom]{@link UIElementA#CreateDom} for the general explanation.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method Sticky.prototype.CreateDom
     */
    Sticky.prototype.CreateDom = function() {
        //adapt style according to the direction
        //sanity checks
        if(!['nw','ne','se','sw'].includes(this.direction)) {
            throw new Error('direction must be nw, ne, se or sw, but got '+this.direction);
        }
        this.style.push('jsa-sticky-'+this.direction);
        this.togglerStyle.push('jsa-sticky-toggler-'+this.direction);

        //create elements
        let content = this.content;
        this.content = '';
        CustomFlatContainer.prototype.CreateDom.call(this);
        this.content = content;

        //container
        this.subelements.container = new CustomFlatContainer({
            id: this.id+'-container',
            style: this.containerStyle,
            content: this.content
        });
        this.AddChild(this.subelements.container);

        //toggler
        this.subelements.toggler = new Icon({
            id: this.id+'-toggler',
            icon: this.icon,
            style: this.togglerStyle,
            onClickCallback: function(event) {
                this.parent.Toggle();
            }
        });
        this.AddChild(this.subelements.toggler);

        //enable resizing
        let self = this;
        if(this.isResizable) {
            $( this.GetDomElement() ).resizable({
                handles: DIRECTION_OPPOSITE[this.direction],
                start: function(event,ui) {
                        //preserve borders
                        self.bordersBeforeResize = {
                        left: self.GetDomElement().style.left,
                        right: self.GetDomElement().style.right,
                        top: self.GetDomElement().style.top,
                        bottom: self.GetDomElement().style.bottom,
                    }
                },
                stop: function(event,ui) {
                    //restore borders
                    self.GetDomElement().style.left = self.bordersBeforeResize.left;
                    self.GetDomElement().style.right = self.bordersBeforeResize.right;
                    self.GetDomElement().style.top = self.bordersBeforeResize.top;
                    self.GetDomElement().style.bottom = self.bordersBeforeResize.bottom;
                }
            });
        }

        //see if default is collapsed
        if(this.startCollapsed) {
            this.Collapse();
        }
        //enable dialog
        if(!this.startEnabled) {
            this.Disable();
        }

        this.DefineRedirectContainer(this.subelements.container);
        this.DefineIconContainer(this.subelements.toggler,'SetIcon');

        return this;
    };

    /**
     * Manually enable the sticky. 
     * @returns {this} Instance of the element itself to enable method chaining
     * @method Sticky.prototype.Enable
     * @override
     *
     * @example
     * // ... continuing general Sticky example
     * stickySe.Enable(); //-> sticky can be opened and closed
     */
    Sticky.prototype.Enable = function() {
        if(!this.isEnabled) {
            this.subelements.toggler.Enable();
            CustomFlatContainer.prototype.Enable.call(this);
        };
        return this; //returning this allows calling methods in a chain;
    };

    /**
     * Manually disable the sticky. 
     * @returns {this} Instance of the element itself to enable method chaining
     * @method Sticky.prototype.Disable
     * @override
     *
     * @example
     * // ... continuing general Sticky example
     * stickySe.Disable(); //-> sticky behaves passive
     */
    Sticky.prototype.Disable = function() {
        if(this.isEnabled) {
            this.subelements.toggler.Disable();
            CustomFlatContainer.prototype.Disable.call(this);
        }
        return this; //returning this allows calling methods in a chain;
    };

    /**
     * Manually uncollapses a closed sticky.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method Sticky.prototype.Uncollapse
     *
     * @example
     * // ... continuing general Sticky example
     * stickySe.Uncollapse(); //-> sticky's content is shown
     * stickySe.Collapse(); //-> sticky's content is hidden
     */
    Sticky.prototype.Uncollapse = function() {
        if(this.isCollapsed) {
            this.GetDomElement().style.visibility = 'visible';
            this.subelements.container.GetDomElement().style.display = this.actualContainerDisplayStyle;
            this.subelements.toggler.GetDomElement().classList.remove('jsa-sticky-toggler-collapsed');
            this.isCollapsed = false;
        }
        return this; //returning this allows calling methods in a chain;
    };

    /**
     * Manually collapses an open sticky.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method Sticky.prototype.Collapse
     *
     * @example
     * // ... continuing general Sticky example
     * stickySe.Uncollapse(); //-> sticky's content is shown
     * stickySe.Collapse(); //-> sticky's content is hidden
     */
    Sticky.prototype.Collapse = function() {
        if(!this.isCollapsed) {
            this.GetDomElement().style.visibility = 'hidden';
            this.actualContainerDisplayStyle = this.subelements.container.GetDomElement().style.display;
            this.subelements.container.GetDomElement().style.display = 'none';
            this.subelements.toggler.GetDomElement().classList.add('jsa-sticky-toggler-collapsed');
            this.isCollapsed = true;
        }
        return this; //returning this allows calling methods in a chain;
    };

    /**
     * Manually change between the collapsed and uncollapsed state of the sticky. 
     * It it is collapsed it becomes uncollapsed and vise versa.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method Sticky.prototype.Toggle
     *
     * @example
     * // ... continuing general Sticky example
     * stickySe.Uncollapse(); //-> sticky's content is shown
     * stickySe.Toggle(); //-> sticky's content is hidden
     */
    Sticky.prototype.Toggle = function() {
        if(this.isCollapsed) {
            this.Uncollapse();
        } else {
            this.Collapse();
        }
        return this; //returning this allows calling methods in a chain;
    };


    /*MODAL*/
    /**
     * @class Modal
     * @classdesc A modal is a modal dialog, i.e a dialog that pops in front of 
     * the application, blocks all other elements and must be answered by 
     * the use before other elements become accessible again.
     * The jsa modal is a UI container, which has a container DOM as well as an 
     * area for buttons and a header. By default and OK and a CANCEL button is shown.
     * 
     *       ------------------------------------------
     *      | Header  (name here)                      |
     *      |------------------------------------------| <-- Modal
     *      | Content / user container                 | 
     *      |                                          | 
     *      |                                          | 
     *      |                                          | 
     *      |                                          |
     *      |------------------------------------------|
     *      |                         ----   --------  |
     *      | Button container       | OK | | CANCEL | <-- Default buttons can be customized
     *      |                         ----   --------  |
     *       ------------------------------------------
     * 
     * Other than in some other programming languages and UI frameworks a modal dialog will not stop any 
     * calculation. It just block the user's interaction with the application. Use the callbacks to get 
     * informed on which button the user pressed. 
     *
     * @param {dict} params=(see_below) - A dictionary of initialization parameters. Below for details.
     * @param {boolean} [createDom=true] - To be used for inheritance of jsa elements. If set to false the HTML DOM element will not be created, e.g. CreateDom is not called.
     *
     * @comment Modal parameters
     * @property {string} params.name='' - The name of the modal shown in the header
     * @property {string} params.content='' - The textual content of the modal dialog. Otherwise also AddChild can be used to add further jsa UI elements.
     * @property {Array.<string>} params.style=['jsa-modal']] - The CSS styles for the outer DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {Array.<string>} params.backgroundStyle = ['jsa-modal-background']] - The CSS styles for the background DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {Array.<string>} params.dialogStyle = ['jsa-modal-dialog']] - The CSS styles for the dialog DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {Array.<string>} params.dialogPaneStyle = ['jsa-modal-dialog-container']] - The CSS styles for the dialogs inner DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {Array.<string>} params.headerContainerStyle = ['jsa-modal-title-container']] - The CSS styles for the dialogs title DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {Array.<string>} params.userContainerStyle = ['jsa-modal-user-container']] - The CSS styles for the user container DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {Array.<string>} params.buttonContainerStyle = ['jsa-modal-button-container']] - The CSS styles for the button container DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {Object} params.buttons - This defines the number, label and callbacks of the buttons of the modal dialog. 
     * Use this only, if you wish to have other buttons as OK and CANCEL. The default is:
     * 
     *     {
     *         ok: {
     *             name: 'Ok',
     *             startEnabled: true,
     *             onClickCallback: function(event) {
     *                 self.onOkCallback();
     *             }
     *         },
     *         cancel: {
     *             name: 'Cancel',
     *             startEnabled: true,
     *             onClickCallback: function(event) {
     *                 self.onCancelCallback();
     *             }
     *         }
     *      }
     * 
     * @property {function} this.onOkCallback - The function that is called if the default OK button is clicked. It has no parameters, i.e. function().
     * @property {function} this.onCancelCallback - The function that is called if the default CANCEL button is clicked. It has no parameters, i.e. function().
     * @comment subelements
     * @property {UIElementA} this.subelements.background - (readonly) The  UI element of the background.
     * @property {UIElementA} this.subelements.dialog - (readonly) The  UI element of the dialog.
     * @property {UIElementA} this.subelements.dialogPane - (readonly) The  UI element of the dialog's pane.
     * @property {UIElementA} this.subelements.headerContainer - (readonly) The  UI element of the header area.
     * @property {UIElementA} this.subelements.userContainer - (readonly) The  UI element of the container (Children are added here).
     * @property {UIElementA} this.subelements.buttonContainer - (readonly) The  UI element of the button area.
     * 
     * @returns {this} Instance of the element itself to enable method chaining
     * @constructor Modal
     * @extends CustomFlatContainer
     * @extends UIElementWithNameA
     * 
     * @example
     * let app = new jsa.Application({});
     * let modal = new jsa.Modal({
     *   name:'My Modal Dialog',
     *   content: 'Please pay attention to this important text...'
     * });
     * app.AddChild(modal); //-> by default the modal is shown when added. To prevent this use visible=false or modal.Hide();
     * 
     */
    function Modal(params,createDom=true) {
        CustomFlatContainer.call(this,params,false);
        UIElementWithNameA.call(this);
        //default arguments
        this.content = '';
        this.style = ['jsa-modal'];
        this.backgroundStyle = ['jsa-modal-background'];
        this.dialogStyle = ['jsa-modal-dialog'];
        this.dialogPaneStyle = ['jsa-modal-dialog-container'];
        this.headerContainerStyle = ['jsa-modal-title-container'];
        this.userContainerStyle = ['jsa-modal-user-container'];
        this.buttonContainerStyle = ['jsa-modal-button-container'];

        //let self = this;
        this.buttons = {
            ok: {
                name: 'Ok',
                startEnabled: true,
                data: this,
                onClickCallback: function(event) {
                    this.data.onOkCallback();
                }
            },
            cancel: {
                name: 'Cancel',
                startEnabled: true,
                data: this,
                onClickCallback: function(event) {
                    this.data.onCancelCallback();
                }
            }
        }
        this.onOkCallback = function() {
            this.Hide();
        };
        this.onCancelCallback = function() {
            this.Hide();
        };

        //copy parameters
        CopyParams(this,params);

        //internals
        this.subelements = this.subelements || {};
        this.subelements.background = null;
        this.subelements.dialog = null;
        this.subelements.dialogPane = null;
        this.subelements.headerContainer = null;
        this.subelements.userContainer = null;
        this.subelements.buttonContainer = null;

        //create DOM
        if(createDom) {
            this.CreateDom();
        }
        
        return this;
    };

    Modal.prototype = Object.create(CustomFlatContainer.prototype);
    Mixin(Modal,UIElementWithNameA);

    /**
     * Creates the HTML DOM element. In general, CreateDom is called automatically by the constructor. 
     * Please see [UIElementA.CreateDom]{@link UIElementA#CreateDom} for the general explanation.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method Modal.prototype.CreateDom
     */
    Modal.prototype.CreateDom = function() {
        let content = this.content;
        this.content = '';
        CustomFlatContainer.prototype.CreateDom.call(this);
        this.content = content;

        //Create a background that shields side clicks
        this.subelements.background = new CustomFlatContainer({
            id: this.id+'-background',
            style: this.backgroundStyle
        });
        this.AddChild(this.subelements.background);

        //Create the dialog with its container
        this.subelements.dialog = new CustomFlatContainer({
            id: this.id+'-dialog',
            style: this.dialogStyle
        });
        this.AddChild(this.subelements.dialog);
        this.subelements.dialogPane = new CustomFlatContainer({
            id: this.id+'-dialog-pane',
            style: this.dialogPaneStyle
        });
        this.subelements.dialog.AddChild(this.subelements.dialogPane);

        //The modal is composed of header, user area, and button area
        this.subelements.headerContainer = new CustomFlatContainer({
            id: this.id+'-header-container',
            content: this.name,
            style: this.headerContainerStyle
        });
        this.subelements.dialogPane.AddChild(this.subelements.headerContainer);
        this.subelements.userContainer = new CustomFlatContainer({
            id: this.id+'-user-container',
            content: this.content,
            style: this.userContainerStyle
        });
        this.subelements.dialogPane.AddChild(this.subelements.userContainer);
        this.subelements.buttonContainer = new CustomFlatContainer({
            id: this.id+'-button-container',
            style: this.buttonContainerStyle
        });
        this.subelements.dialogPane.AddChild(this.subelements.buttonContainer);

        for(buttonId in this.buttons) {
            let  buttonDef = this.buttons[buttonId];

            buttonDef.uielement = new Button({
                content: buttonDef.name,
                startEnabled: buttonDef.startEnabled,
                onClickCallback: buttonDef.onClickCallback,
                style: ['jsa-button','jsa-inline-pad-left'],
                data: buttonDef.data
            });

            this.subelements.buttonContainer.AddChild(buttonDef.uielement);
        }

        this.DefineRedirectContainer(this.subelements.userContainer);
        this.DefineNameContainer(this.subelements.headerContainer,'SetContent');
        
        return this;
    };

    /**
     * Enables a button with a specific ID.
     * @param {string} buttonId - The ID of the button to be enabled. This is the key of the button structure, 
     * i.e. for the default buttons this is 'ok' and 'cancel'.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method Modal.prototype.EnableButton
     *
     * @example
     * // Enable the default CANCEL button
     * modal.EnableButton('cancel');
     */
    Modal.prototype.EnableButton = function(buttonId) {
        let  button = this.buttons[buttonId];
        if(button){
            button.uielement.Enable();
        }
        return this;
    };

    /**
     * Enables a button with a specific ID.
     * @param {string} buttonId - The ID of the button to be disabled. This is the key of the button structure, 
     * i.e. for the default buttons this is 'ok' and 'cancel'.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method Modal.prototype.DisableButton
     *
     * @example
     * // Disable the default CANCEL button
     * modal.DisableButton('cancel');
     */
    Modal.prototype.DisableButton = function(buttonId) {
        let  button = this.buttons[buttonId];
        if(button){
            button.uielement.Disable();
        }
        return this;
    };

    //Override
    /**
     * Sets the content of the label dynamically.
     * @param {string} content - The new content
     * @returns {this} Instance of the element itself to enable method chaining
     * @method Modal.prototype.SetContent
     * 
     * @fires [EventSet]{@link EventSet}(eventId= [EVENT.TYPES.SET_CONTENT]{@link EVENT}; propertyName = 'content')
     */
    Modal.prototype.SetContent = function(content) {
        let oldValue = this.content;
        if(this.subelements.userContainer) {
            this.subelements.userContainer.SetContent(content);
        }
        this.content = content;
        //notify
        this.Notify(new EventSet(this,'content',this.content,oldValue));
        return this;
    };


    /* MSGBOX */
    /**
     * @class MsgBox
     * @classdesc A message box is a special [modal dialog]{@link Modal} that is supposed 
     * to contain text only and by default only an OK button. When clicking OK the 
     * message box closes. All element can be customized. 
     * 
     *       --------------------------------
     *      | Header (name here)             |
     *      |--------------------------------| <-- MsgBox
     *      | Content (message here)         | 
     *      |                                | 
     *      |--------------------------------|
     *      |                         ----   |
     *      | Button Area            | OK | <-- Default button can be customized
     *      |                         ----   |
     *       --------------------------------
     * 
     * The message box does not pause any calculations. Use the callback function
     * to be informed about the user interaction.
     *
     * @param {dict} params=(see_below) - A dictionary of initialization parameters. Below for details.
     * @param {boolean} [createDom=true] - To be used for inheritance of jsa elements. If set to false the HTML DOM element will not be created, e.g. CreateDom is not called.
     * @property {function} params.onCloseCallback - The callback function that is called if the user clicks the default OK button. It has no arguments, e.g. function().
     * @property {Object} params.buttons - This defines the number, label and callbacks of the buttons of the modal dialog. 
     * Use this only, if you wish to have other buttons as OK. The default is:
     * 
     *     {
     *        ok: {
     *           name: 'Ok',
     *           startEnabled: true,
     *           data: this,
     *           onClickCallback: function(event) {
     *             self.onCloseCallback();
     *             self.data.Dissolve(); 
     *           }
     *        }
     *     }
     *
     * @constructor MsgBox
     * @extends Modal
     * 
     * @example
     * //Open a message box on clicking a button
     * let app = new jsa.Application({});
     * let button = new jsa.Button({
     *   content: 'Show MsgBox',
     *   onClickCallback : function(event) {
     *     app.AddChild(new jsa.MsgBox({
     *         content: 'Button was clicked!'
     *     }));
     *   }
     * });
     */
    function MsgBox(params,createDom=true) {
        Modal.call(this,params,false);

        //parameters
        this.onCloseCallback = function() {}; //on default the box will only close
        
        let self = this;
        this.buttons = {
            ok: {
                name: 'Ok',
                startEnabled: true,
                onClickCallback: function(event) {
                self.onCloseCallback();
                self.Dissolve(); 
                }
            }
        };

        //CopyParams
        CopyParams(this,params);

        if(createDom) {
            this.CreateDom();
        }
    };

    MsgBox.prototype = Object.create(Modal.prototype);


    /*SPLASH*/
    /**
     * @class Splash
     * @classdesc A splash screen is intended for longer application start-ups 
     * or longer loading sequences. It hides the underlying UI elements and 
     * prevents any interaction with them. It creates a content container
     * that is centered on the current screen or parent element. 
     * It is suggested to be filled with 
     * animation and status text, but any content or jsa element can be added 
     * to it. Jsa comes with a default loading animation that purely 
     * created by CSS keyframes. See example below.
     * 
     *      ------------------------------------------------
     *     | (blocks interaction here)                      | <-- Screen (or any other dom element)
     *     |                                                |
     *     |            ----------------------              |
     *     |           |      ||      ||      |             |
     *     |           |  --||||||--||||||-- <-- can show e.g. a loading animation
     *     |           |      ||      ||      |             |
     *     |           |                      |<- Content   |
     *     |           | Loading...           |   container |
     *     |            ----------------------              |
     *     |                                                |
     *     |                                                |     
     *      ------------------------------------------------
     *
     * @param {dict} params=(see_below) - A dictionary of initialization parameters. Below for details.
     * @param {boolean} [createDom=true] - To be used for inheritance of jsa elements. If set to false the HTML DOM element will not be created, e.g. CreateDom is not called.
     * @property {string} params.content='' - The content to be shown below the loading animation.
     *
     * @returns {this} Instance of the element itself to enable method chaining
     * @constructor Splash
     * @extends CustomContainerA
     * 
     * @example
     * // Show the a splash screen with the default
     * // jsa loading animation and hide it after
     * // one second.
     * let app = jsa.Application({});
     * let splash = new jsa.Splash({
     *     content: '&lt;div class="jsa-loading">&lt;/div&gt;'+
     *              '&lt;div&gt;Loading...&lt;/div&gt;'
     * });
     * app.AddChild(splash);
     * window.setTimeout(function() {
     *     splash.Hide();
     * },1000);
     */
    function Splash(params,createDom=true) {
        CustomContainerA.call(this,params,false);
        //default arguments
        this.content = '';
       
        //copy parameters
        CopyParams(this,params);
        
        //create DOM
        if(createDom) {
            this.CreateDom();
        }
        
        return this;
    };

    Splash.prototype = Object.create(CustomContainerA.prototype);

    /**
     * Creates the HTML DOM element. In general, CreateDom is called automatically by the constructor. 
     * Please see [UIElementA.CreateDom]{@link UIElementA#CreateDom} for the general explanation.
     * @method Splash.prototype.CreateDom
     * @returns {this} Instance of the element itself to enable method chaining
     */
    Splash.prototype.CreateDom = function() {
        this.domElement = CreateDomElementWithUniqueId('div');
        this.domElement.classList.add('jsa-splash');

        this.background = CreateDomElementWithUniqueId('div');
        this.background.classList.add('jsa-splash-background');
        this.domElement.appendChild(this.background);

        this.containerDomElement = CreateDomElementWithUniqueId('div');
        this.containerDomElement.classList.add('jsa-splash-container');
        this.containerDomElement.innerHTML = this.content;
        this.domElement.appendChild(this.containerDomElement);
        
        return this;
    };


    /* DASHBOARDVIEW */
    /**
     * @class DashboardView
     * @classdesc A dashboard view is a view that arranges several [dashes]{@link Dash}
     * in a regular pattern. Dashes are small pieces of information
     * or user interaction, that can have an individual width measured 
     * in tiles. 12 tiles is a full line. 6 tiles are half the width.
     * If multiple rows are desired, rows must be added manually and 
     * as seen in the example.
     * 
     *      ----------------------------------------------- 
     *     | DashboardView                                 |
     *     |-----------------------------------------------|
     *     |                                               |
     *     |   --------------   -------------------------  |
     *     |  |  Dash        | | Dash                    | |
     *     |  |  (4 tiles)   | | (8 tiles)               | |
     *     |  |              | |                         | |
     *     |  |              | |                         | |
     *     |   --------------   -------------------------  |
     *      -----------------------------------------------
     *
     * @param {dict} params=(see_below) - A dictionary of initialization parameters. Below for details.
     * @param {boolean} [createDom=true] - To be used for inheritance of jsa elements. If set to false the HTML DOM element will not be created, e.g. CreateDom is not called.
     *
     * @comment DashboardView parameters
     * @property {array.string} params.containerStyle=['jsa-view-container','jsa-dashboard-view']] - The CSS styles for the inner DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @returns {this} Instance of the element itself to enable method chaining
     *
     * @constructor DashboardView
     * @extends View
     * 
     * @example
     * // Create a dashboard view and add it to the 
     * // application's default view manager
     * let app = new jsa.Application({});
     * let dashboardView = new jsa.DashboardView({
     *     name: 'Dashboard',
     *     icon: 'img/view-home.svg',
     *     hasHeader: true,
     *     headerStyle: ['jsa-view-header','my-view-dashboard-header']
     * });
     * app.AddChild(dashboardView);
     * // Add a row and two dashes
     * let dashboardRow = new jsa.CustomFlatContainer({
     *     style: ['row','jsa-dashboard-row']
     * })
     * dashboardView.AddChild(dashboardRow);
     * dashboardRow.AddChild(new jsa.Dash({
     *   name: 'Dash 1,1',
     *   content: 'Hello world.',
     *   tiles: 4
     * }));
     * dashboardRow.AddChild(new jsa.Dash({
     *   name: 'Dash 1,2',
     *   content: 'Hello world.',
     *   tiles, 8
     * }));
     */
    function DashboardView(params,createDom=true) {
        View.call(this,params,false);
        //params
        this.containerStyle = ['jsa-view-container','jsa-dashboard-view'];
        CopyParams(this,params);

        if(createDom) {
            this.CreateDom();
        }

        return this;
    };
    DashboardView.prototype = Object.create(View.prototype);

    /**
     * Creates the HTML DOM element. In general, CreateDom is called automatically by the constructor. 
     * Please see [UIElementA.CreateDom]{@link UIElementA#CreateDom} for the general explanation.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method DashboardView.prototype.CreateDom
     */
    DashboardView.prototype.CreateDom = function() {
        View.prototype.CreateDom.call(this);
        return this;
    };

    /* Dash */
    /**
     * @class Dash
     * @classdesc A dash is an UI element to be placed on a [dash view]{@link DashboardView}. 
     * It is composed of an optional title and a content are. The content can be textual or other 
     * UI elements
     * 
     *      -------------------
     *     | Title             |
     *     |-------------------|
     *     | Content           |
     *     |                   |
     *     |                   |
     *      -------------------
     * 
     *
     * @param {dict} params=(see_below) - A dictionary of initialization parameters. Below for details.
     * @param {boolean} [createDom=true] - To be used for inheritance of jsa elements. If set to false the HTML DOM element will not be created, e.g. CreateDom is not called.
     *
     * @comment Dash parameters
     * @property {string} params.name='' - The name of the dash. It is shown on the top.
     * @property {Array.<string>} params.style=['jsa-dash']] - The CSS styles for the outer DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {Array.<string>} params.containerStyle=['jsa-dash-container']] - The CSS styles for the inner DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {Array.<string>} params.titleStyle=['jsa-dash-title']] - The CSS styles for the title DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {string} params.content='' - The textual content of the dash. Content can also be added with AddChild().
     * @property {int} params.tiles=4 - The width measured in tiles. 1 tiles is the maximum. See also [DashboardView]{@link DashboardView}.
     *
     * @constructor Dash
     * @extends CustomFlatContainer
     * @extends UIElementWithNameA
     */
    function Dash(params,createDom=true) {
        CustomFlatContainer.call(this,params,false);
        UIElementWithNameA.call(this);

        //members
        // this.name = '';
        this.style = ['jsa-dash'];
        this.containerStyle = ['jsa-dash-container'];
        this.titleStyle = ['jsa-dash-title']; 
        this.content = '';
        this.tiles = 4; //how many tiles are allocated on a row ranges from 1 to 12
        this.hasTitle = true;
        
        //copy parameters
        CopyParams(this,params);

        //Create DOM
        if(createDom) {
            this.CreateDom(); //prevent calling the wrong CreateDOM function if inheriting this class
        }
    };

    Dash.prototype = Object.create(CustomFlatContainer.prototype);
    Mixin(Dash,UIElementWithNameA);

    /**
     * Creates the HTML DOM element. In general, CreateDom is called automatically by the constructor. 
     * Please see [UIElementA.CreateDom]{@link UIElementA#CreateDom} for the general explanation.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method Dash.prototype.CreateDom
     */
    Dash.prototype.CreateDom = function() {
        let content = this.content;
        this.content = '';
        this.style.push('jsa-col-'+this.tiles+'t'); 
        CustomFlatContainer.prototype.CreateDom.call(this);
        this.content = content;

        
        // this.domElement = CreateDomElementWithUniqueId('div',this.id);
        // ApplyStyles(this.style,this.domElement);

        if(this.hasTitle) {
            // this.title = CreateDomElementWithUniqueId('h3');
            this.title = new CustomFlatContainer({
                style: this.titleStyle,
                content: this.name
            });
            this.AddChild(this.title);
            // ApplyStyles(this.titleStyle,this.title);
            // this.domElement.appendChild(this.title);
            this.DefineNameContainer(this.title,'SetName');
        }

        // this.containerDomElement = CreateDomElementWithUniqueId('div');
        // ApplyStyles(this.containerStyle,this.containerDomElement);
        // this.containerDomElement.innerHTML = this.content;
        // this.domElement.appendChild(this.containerDomElement);
        this.container = new CustomFlatContainer({
            style: this.containerStyle,
            content: this.content
        });
        this.AddChild(this.container);

        this.DefineRedirectContainer(this.container)

        return this;
    };

    // /**
    //  * Dynamically sets the title of the dash
    //  * @param {string} name - The new title
    //  * @returns {this} Instance of the element itself to enable method chaining
    //  * @method Dash.prototype.SetName
    //  */
    // Dash.prototype.SetName = function(name) {
    //     this.name = name;
    //     if(this.hasTitle) {
    //         this.title.innerHTML = this.name;
    //     }
    //     return this;
    // };




    /* SELECTION */
    /**
     * @class Selection
     * @classdesc A selection is a is a data structure to manage user selections in the application,
     * e.g. text, or objects. It is the quantity used by the [selection manager]{@link SelectionManager}.
     *
     * @param {dict} params=(see_below) - A dictionary of initialization parameters. Below for details.
     *
     * @comment Selection parameters
     * @property {Array.<object>} params.elements=[]] - The actual selection. If only one object is selected, it shall be a one-element array.
     * @property {UiElementA} params.eventSource=null - The origin of the selection
     * @property {HTML_DOM_ELEMENT} params.domElement=null - (optional) The DOM element of the selection
     * @property {int} params.positionX=0 - (optional)The x position in pixels, where this selection took place 
     * @property {int} params.positionY=0 - (optional)The y position in pixels, where this selection took place 
     *
     * @constructor Selection
     * 
     * @example
     * // Create a new text selection
     * let selection = new jsa.Selection({
     *   elements: ['selected text'],
     *   eventSource: myInputCtrl,
     *   domElement: myInputCtrl.GetDomElement()
     * });
     */
    function Selection(params) {
        //members
        this.elements = []; //selection shall always be an array
        this.eventSource = null; //the object causing the event, e.g. a uielement
        this.domElement = null; //the selected dom element. This could be used to attache an effect to it
        this.positionX = 0; // screen coordinates of the selection event
        this.positionY = 0;

        //copy params
        CopyParams(this,params);
    };


    /* SELECTION MANAGER */
    /**
     * @class SelectionManager
     * @classdesc A selection manager manages centrally the selection within the application.
     * It is an observable that can inform others about the current selection and the related objects.
     * related data. An [jsa.Application]{@link Application} has by default a selection manager, 
     * i.e. app.selectionManager.
     *
     * @property {Application} this.app - (readonly) The application for this selection manager
     * @property {Object} this.currentSelection=null - (readonly) The current selection, but use GetSelection().
     *
     * @returns {this} Instance of the element itself to enable method chaining
     * @constructor SelectionManager
     * @extends Observable
     */
    function SelectionManager(app) {
        Observable.call(this);

        this.app = app

        this.currentSelection = null;

        return this;
    };

    SelectionManager.prototype = Object.create(Observable.prototype);

    /**
     * Set the current selection of the application and informs all observers about the new
     * selection.
     * @param {Selection} selection - The current selection object.
     * @returns {this} Instance of the element itself to enable method chaining
     * @fires [EventSet]{@link EventSet}(eventId= [EVENT.TYPES.SET]{@link EVENT}+'/currentSelection'; propertyName = 'currentSelection')
     * @method SelectionManager.prototype.SetSelection
     *
     * @example
     * // Set the current selection to a text
     * app.selectionManager.SetSelection(new jsa.Selection({
     *   elements: ['selected text']
     * }));
     */
    SelectionManager.prototype.SetSelection = function(selection) {
        //check if the selection has really changed 
        if(this.IsSelectionNew(selection)) {
            let oldSelection = this.currentSelection;
            this.currentSelection = selection;

            //notify observers, but exclude the source from receiving a notification on its own event
            this.Notify(new EventSet(this,"currentSelection",this.currentSelection,oldSelection)); 
        }
        return this;
    };

    /**
     * Returns the actual selection object or null if nothing is selected.
     * @returns {Selection} - The selection object or null.
     * @method SelectionManager.prototype.GetSelection
     *
     * @example
     * // Set the current selection to a text
     * app.selectionManager.SetSelection(new jsa.Selection({
     *   elements: ['selected text']
     * }));
     * let selection = app.selectionManager.GetSelection();
     * selection.elements[0]; //-> 'selected text'
     */
    SelectionManager.prototype.GetSelection = function() {
        return this.currentSelection;
    };


    /* TOOLBAR */
    /**
     * @class Toolbar
     * @classdesc A toolbar is a horizontal arrangement of icons called [tools]{@link Tool}.
     * It can for instance be part of the menu bar of an [application]{@link Application}.
     * 
     *      ---------------------------------------------------------------------------------
     *     |  -----   -----   -----   -----                                                  | 
     *     | |Tool1| |Tool2| |Tool3| |Tool4| ....                                            |
     *     |  -----   -----   -----   -----                                                  |
     *      ---------------------------------------------------------------------------------
     *
     * @param {dict} params=(see_below) - A dictionary of initialization parameters. Below for details.
     * @param {boolean} [createDom=true] - To be used for inheritance of jsa elements. If set to false the HTML DOM element will not be created, e.g. CreateDom() is not called.
     *
     * @comment Toolbar parameters
     * @property {string} params.elementType='ul' - The DOM element type of the toolbar. Do not change if you want to use the default toolbar style.
     * @property {Array.<string>} params.style=['navbar-nav','ml-auto','jsa-toolbar']] - The CSS styles for the DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     *
     * @returns {this} Instance of the element itself to enable method chaining
     * @constructor Toolbar
     * @extends CustomFlatContainer
     * 
     * @example 
     * // The default toolbar of jsa.Application
     * // is created as follows if hasToolbar=true
     * // (this is for explanation only, you do not have to do this by hand)
     * app.toolbar = new Toolbar();
     * app.menuContainer.AddChild(app.toolbar);
     */
    function Toolbar(params={},createDom=true) {
        CustomFlatContainer.call(this,params,false);

        //params
        this.style = ['jsa-toolbar'];

        CopyParams(this,params);

        if(createDom) {
            this.CreateDom();
        }

        return this;
    };
    Toolbar.prototype = Object.create(CustomFlatContainer.prototype);


    /* TOOL */
    /**
     * @class Tool
     * @classdesc A tool is an icon that appears in a [toolbar]{@link Toolbar}.
     * Usually it provides quick access to a larger action or to some information
     * when clicked by the user. It can also be used to display status information
     * by changing its text or icon, e.g. loading status, current db activity, or
     * the number of new notes.
     *
     * @param {dict} params=(see_below) - A dictionary of initialization parameters. Below for details.
     * @param {boolean} [createDom=true] - To be used for inheritance of jsa elements. If set to false the HTML DOM element will not be created, e.g. CreateDom() is not called.
     *
     * @comment Tool parameters
     * @property {Array.<string>} params.style=['jsa-tool']] - The CSS styles for the outer DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {Array.<string>} params.containerStyle=['jsa-tool-container']] - The CSS styles for the inner DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {function} params.onClickCallback - The function that gets called if the user clicks the tool icon. This gets forwarded the HTML click event, i.e. the signature is function(evt).
     *
     * @returns {this} Instance of the element itself to enable method chaining
     * @constructor Tool
     * @extends CustomContainer
     * 
     * @example
     * // Add a tool to the default toolbar
     * // and open a MsgBox if the tool is clicked.
     * let  tool = new jsa.Tool({
     *     onClickCallback : function(event) {
     *         app.AddChild(new jsa.MsgBox({
     *             content: 'Tool activated'
     *         }));
     *     }
     * });
     * app.toolbar.AddChild(tool);
     */
    function Tool(params={},createDom=true) {
        CustomContainer.call(this,params,false);

        //params
        this.style = ['jsa-tool'];
        this.containerStyle = ['jsa-tool-container'];

        this.onClickCallback = function(event) {};

        CopyParams(this,params);

        if(createDom) {
            this.CreateDom();
        }

        return this;
    };
    Tool.prototype = Object.create(CustomContainer.prototype);


    /* TABBAR */
    /**
     * @class Tabbar
     * @classdesc A tabbar is the classical UI element to manage multiple 
     * content pages/container on the same parent container. It shows a line 
     * of [tabs}{@link Tab} on top or below and a click on the tab brings the 
     * related content container in front. The jsa.Tabbar can be coupled with 
     * a [view manager]{@link ViewManager}. It is, however, generic such that 
     * an arbitrary action can take place when clicking a tab.
     * 
     *         ------    ------    ------    ------  
     *        / Tab1 \  / Tab2 \  / Tab3 \  / .... \   <-- CSS style jsa-tabbar-top
     *     ---         ---------------------------------------------------
     * 
     *                                    or
     * 
     *     ---         ---------------------------------------------------
     *        \ Tab1 /  \ Tab2 /  \ Tab3 /  \ .... /   <-- CSS style jsa-tabbar-bottom
     *         ------    ------    ------    ------  
     * 
     * @param {dict} params=(see_below) - A dictionary of initialization parameters. Below for details.
     * @param {boolean} [createDom=true] - To be used for inheritance of jsa elements. If set to false the HTML DOM element will not be created, e.g. CreateDom() is not called.
     *
     * @comment Tabbar parameters
     * @property {string} params.elementType='div' - The DOM element type of the tool. Do not change if you want to use the default style.
     * @property {Array.<string>} params.style=['jsa-tabbar']] - The CSS styles for the DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @comment Tabbar internals
     * @property {ViewManager} this.viewManager - (readonly) Used if synced with a view manager
     * @property {Observer} this.viewManagerObserver - (readonly) sed if synced with a view manager
     * @property {boolean} this.syncWithHeaderStyles - (readonly) Used if synced with a view manager
     * @property {boolean} this.syncWithCommands - (readonly) Used if synced with a view manager
     *
     * @returns {this} Instance of the element itself to enable method chaining
     * @constructor Tabbar
     * @extends CustomFlatContainer
     * 
     * @example
     * // Create a tabbar, which controls the tabs of default view manager
     * let  app = new jsa.Application( {
     *     viewManagerStyle: ['jsa-view-manager']
     * });
     * let tabbar = new jsa.Tabbar({
     *     style: ['jsa-tabbar','jsa-tabbar-top']
     * });
     * app.AddChild(tabbar);
     * tabbar.SyncWithViewManager(app.viewManager,true);
     */
    function Tabbar(params={},createDom=true) {
        CustomFlatContainer.call(this,params,false);

        //params
        this.style = ['jsa-tabbar'];

        CopyParams(this,params);

        if(createDom) {
            this.CreateDom();
        }

        //internals
        this.viewManager = null; //used if synced with a view manager
        this.viewManagerObserver = null; //used if synced with a view manager
        this.syncWithHeaderStyles = false;
        this.syncWithCommands = false;

        return this;
    };
    Tabbar.prototype = Object.create(CustomFlatContainer.prototype);

    /**
     * Manually sets a tab active, which means that its visual appearance changes, e.g. tab.activeStyle
     * becomes visible. There can only be one active tab. All other tabs become inactive.
     * @param {Tab} tab - The tab to be set active
     * @returns {this} Instance of the element itself to enable method chaining
     * @method Tabbar.prototype.SetActiveTab
     *
     * @example
     * // Create a tabbar
     * let tabbar = new jsa.Tabbar({
     *     style : ['jsa-tabbar','jsa-tabbar-bottom']
     * });
     * // Add two children
     * let tab1 = new jsa.Tab({
     *     content : 'Tab 1'
     * });
     * tabbar.AddChild(tab1);
     * let tab2 = new jsa.Tab({
     *     content : 'Tab 2'
     * });
     * tabbar.AddChild(tab2);
     * // Toggle the active tabs
     * tabbar.SetActiveTab(tab1); //-> tab1: active: tab2 inactive
     * tabbar.SetActiveTab(tab2); //-> tab1: inactive: tab2 active
     */
    Tabbar.prototype.SetActiveTab = function(tab) {
        
        let tabId = this.children.findIndex( function(t) {
            return (t==tab);
        });
        if(-1<tabId) {
            //deactivate all, but the given one.
            for(let i=0;i<this.children.length;i++) {
                let t = this.children[i];
                if(tabId == i) {
                    t.GetDomElement().classList.add(t.activeStyle);
                } else {
                    t.GetDomElement().classList.remove(t.activeStyle);
                }
            }
        }
        return this;
    };

    //@Override
    /**
     * Adds a new tab to the tabbar.
     * @param {Tab} tab - The tab object to be added
     * @returns {this} Instance of the element itself to enable method chaining
     * @method Tabbar.prototype.AddChild
     *
     * @example
     * // Create a tabbar and add a child
     * let tabbar = new jsa.Tabbar({
     *     style : ['jsa-tabbar','jsa-tabbar-bottom']
     * });
     * let tab1 = new jsa.Tab({
     *     content : 'Tab 1'
     * });
     * tabbar.AddChild(tab1);
     */
    Tabbar.prototype.AddChild = function(tab,redirect=true) {
        CustomFlatContainer.prototype.AddChild.call(this,tab,redirect);
        tab.tabbar = this;
        return this;
    };

    //@Override
    /**
     * Removes a tab from the tabbar. If it is the active tab, no tab will 
     * be active any more.
     * @param {Tab} tab - The tab object to be removed
     * @returns {this} Instance of the element itself to enable method chaining
     * @method Tabbar.prototype.RemoveChild
     *
     * @example
     * // Create a tabbar and add a child and remove it afterwards
     * let tabbar = new jsa.Tabbar({
     *     style : ['jsa-tabbar','jsa-tabbar-bottom']
     * });
     * let tab1 = new jsa.Tab({
     *     content : 'Tab 1'
     * });
     * tabbar.AddChild(tab1); //-> tab1 appears
     * tabbar.Remove(tab1); //-> tab1 vanishes
     */
    Tabbar.prototype.RemoveChild = function(tab,redirect=true) {
        CustomFlatContainer.prototype.RemoveChild.call(this,tab,redirect);
        return this;
    };

    /**
     * Syncs a tabbar with a [view manager]{@link ViewManager}. That means, all views in view manager
     * automatically appear as tabs on the tabbar. If views are added or removed the tabs will change.
     * Moreover, clicking the tabs changes the active view. 
     * @param {ViewManager} viewManager - The view manager object this tabbar shall control
     * @param {boolean} syncWithHeaderStyles=false - If true, the background color of the view's header is copied to the tab background.
     * @param {boolean} syncWithCommands=false - If true, all tab click issue a [ChangeViewCommand]{@link ChangeViewCommand} in the apps commandManager,
     * such that observers of the command listener get informed.
     *
     * @method Tabbar.prototype.SyncWithViewManager
     *
     * @example
     * // ... excerpt from the general Tabbar example
     * tabbar.SyncWithViewManager(app.viewManager,true);
     */
    Tabbar.prototype.SyncWithViewManager = function(viewManager,syncWithHeaderStyles=false,syncWithCommands=false) {
        this.viewManager = viewManager;
        this.app = viewManager.GetApp();
        this.syncWithHeaderStyles = syncWithHeaderStyles;
        this.syncWithCommands = syncWithCommands;

        //build initial tabs based on existing views
        let  views = this.viewManager.children;
        if(views.length>0) {
            for(let i=0;i<views.length;i++) {
                let  view = views[i];
                this.CreateNewTabForView(view);
            }
        }

        //start observing the view manager
        let self = this;
        this.viewManagerObserver = new Observer({
            onNotifyCallback: function(event,source) {self.OnViewManagerChanges(event,source);}
        });
        this.viewManager.StartObserving(this.viewManagerObserver);  
    };

    /**
     * Used internally to catch view add, remove or activate events from the 
     * attached view manager if using view manager synchronization.
     * @param {Event} event - The view manager event
     * @param {ViewManager} source - The view manager object
     * @method Tabbar.prototype.OnViewManagerChanges
     */
    Tabbar.prototype.OnViewManagerChanges = function(event,source) {
        if(EVENT.IS_INSTANCE(event,EVENT.TYPES.ADD_CHILD)) {
            let view = event.value;
            this.CreateNewTabForView(view);
        } else if(EVENT.IS_INSTANCE(event,EVENT.TYPES.REMOVE_CHILD)) {
            let view = event.value;
            this.RemoveTabForView(view);
        } else if(EVENT.IS_INSTANCE(event,EVENT.TYPES.SET_ACTIVE_VIEW)) {
            let view = event.value;
            let tab = this.children.find(function(t){
                return (view==t.data.view);
            });
            if(tab) {
                this.SetActiveTab(tab);
            }
        }
    };

    /**
     * Used internally to create a new tab that is related to a view in 
     * a view manager if view manager synchronization is used.
     * @param {View} view - The view object the tab represents
     * @method Tabbar.prototype.CreateNewTabForView
     */
    Tabbar.prototype.CreateNewTabForView = function(view) {
        let onTabClickCallback = null;
        if(this.syncWithCommands) {
            onTabClickCallback = function(event) {
                this.app.commandManager.Execute(new jsa.ChangeViewCommand(this.data.viewManager,this.data.view));
            };
        } else {
            onTabClickCallback = function(event) {
                this.data.viewManager.ActivateView(this.data.view);
            };
        }

        let viewTab = new Tab({
            content: view.GetName(),
            icon: view.icon,
            data: {
                view: view,
                viewManager: this.viewManager,
                viewObserver: null
            },
            onClickCallback : onTabClickCallback
        });
        //add a close control if the view is closable
        if(view.isClosable) {
            viewTab.subelements.label.subelements.post.AddChild(new Icon({
                icon : 'jsa-icon-close',
                style : ['jsa-icon-s','jsa-inline-pad-left','jsa-icon-s-button'],
                onClickCallback: function(event) {
                    view.Close();
                },
                hasTooltip: true,
                tooltip: 'Close this tab.'
            }));
        }
        //copy header colors if it shall be synced
        if(this.syncWithHeaderStyles) {
            let color = window.getComputedStyle( view.subelements.header.GetDomElement() ,null).getPropertyValue('color');  
            viewTab.GetDomElement().style.color = color;
            let bgColor = window.getComputedStyle( view.subelements.header.GetDomElement() ,null).getPropertyValue('background-color');  
            viewTab.GetDomElement().style.backgroundColor = bgColor;
        }
        this.AddChild(viewTab);


        //Observe name change events of tabs
        let nameChangeObserver = new jsa.Observer({
            onNotifyCallback: function(event,source) {
                if(EVENT.IS_INSTANCE(event,EVENT.TYPES.SET)) {
                    switch(event.propertyName) {
                        case 'name':
                            viewTab.SetContent(event.value);
                            break;
                        case 'icon':
                            viewTab.SetIcon(event.value);
                            break;
                    }
                }
            }
        });
        view.StartObserving(nameChangeObserver);
        viewTab.data.viewObserver = nameChangeObserver;
    };

    /**
     * Used internally to remove a tab that is related to a view in 
     * a view manager if view manager synchronization is used.
     * @param {View} view - The view object
     * @method Tabbar.prototype.RemoveTabForView
     */
    Tabbar.prototype.RemoveTabForView = function(view) {
        let tab = this.children.find(function(t){
            return (view==t.data.view);
        });
        if(tab) {
            tab.data.view.StopObserving(tab.data.viewObserver);
            tab.Dissolve();
            //this.RemoveChild(tab);
        }
    };


    /* TAB */
    /**
     * @class Tab
     * @classdesc A tab is a child of a [tabbar]{@link Tabbar}. It is 
     * usually used to active some thing below or above the tabbar.
     * Tabs have a content are usually used for a label and or icon.
     * 
     *         ----------
     *        /          \ 
     *       /  Content   \
     *      /              \       
     *     ------------------
     *
     * @param {dict} params=(see_below) - A dictionary of initialization parameters. Below for details.
     * @param {boolean} [createDom=true] - To be used for inheritance of jsa elements. If set to false the HTML DOM element will not be created, e.g. CreateDom is not called.
     *
     * @comment Tab parameters
     * @property {string} params.elementType='div' - The DOM element type of the tab. Do not change if you want to use the default style.
     * @property {Array.<string>} params.style=['jsa-tab']] - The CSS styles for the outer DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {Array.<string>} params.containerStyle=['jsa-tab-container']] - The CSS styles for the inner DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {Array.<string>} params.activeStyle=['jsa-tab-active']] - The CSS styles for the DOM element when the tab is active. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {function} params.onClickCallback - The function called when the tab is clicked. This function gets the HTML click event forwarded. Its signature is function(evt).
     *
     * @returns {this} Instance of the element itself to enable method chaining
     * @constructor Tab
     * @extends CustomContainer
     * @extends UIElementWithIconA
     * 
     * @example
     * // Create an tab that pops a message box if clicked
     * let tab = new jsa.Tab({
     *   content : 'My Tab',
     *   onClickCallback : function(event) {
     *     app.AddChild(new jsa.MsgBox({
     *        content: 'Tool activated'
     *     }));
     *   }
     * };
     */
    function Tab(params={},createDom=true) {
        CustomContainer.call(this,params,false);
        UIElementWithIconA.call(this);

        //params
        this.style = ['jsa-tab'];
        this.activeStyle = ['jsa-tab-active'];
        this.containerStyle = ['jsa-tab-container'];
        this.icon = null;

        CopyParams(this,params);

        //internals
        this.subelements = this.subelements || {};
        this.subelements.label = null;

        if(createDom) {
            this.CreateDom();
        }

        return this;
    };
    Tab.prototype = Object.create(CustomContainer.prototype);
    Mixin(Tab,UIElementWithIconA);

    /**
     * Creates the HTML DOM element. In general, CreateDom is called automatically by the constructor. 
     * Please see [UIElementA.CreateDom]{@link UIElementA#CreateDom} for the general explanation.
     * @method Tab.prototype.CreateDom
     */
    Tab.prototype.CreateDom = function() {
        let content = this.content;
        this.content = '';
        CustomContainer.prototype.CreateDom.call(this);
        this.content = content;

        this.subelements.label = new Label({
            content: this.content,
            icon: this.icon,
            hAlign: 'center',
            vAlign: 'middle'
        });
        this.AddChild(this.subelements.label)

        //attach on click
        RedirectDomCallbackToUiElement(this.GetDomElement(),'click',this,this.OnClick);

        this.DefineRedirectContainer(this.subelements.label);
        this.DefineIconContainer(this.subelements.label,'SetIcon');
    };

    //Override
    /**
     * Sets the content of the label dynamically.
     * @param {string} content - The new content
     * @returns {this} Instance of the element itself to enable method chaining
     * @method Tab.prototype.SetContent
     * 
     * @fires [EventSet]{@link EventSet}(eventId= [EVENT.TYPES.SET_CONTENT]{@link EVENT}; propertyName = 'content')
     */
    Tab.prototype.SetContent = function(content) {
        let oldValue = this.content;
        if(this.subelements.label) {
            this.subelements.label.SetContent(content);
        }
        this.content = content;
        //notify
        this.Notify(new EventSet(this,'content',this.content,oldValue));
        return this;
    };

    /**
     * Is called if the tab was clicked and forwards the event 
     * By default it sets this tab as the active tab. Overwrite this
     * function if a different behaviour is desired.
     * @param {HTML_event} event - The HTML clicked event
     * @method Tab.prototype.OnClick
     */
    Tab.prototype.OnClick = function(event) {
        //activate the current active tab
        if(this.parent) {
            let tabbar = this.parent;
            tabbar.SetActiveTab(this); 
        }
    };

    //@Override
    /**
     * Cleaning up the on click for activation listener
     * @method Tab.prototype.Dissolve
     */
    Tab.prototype.Dissolve = function() {
        //attach on click
        RemoveRedirectDomCallbackFromUiElement(this.GetDomElement(),'click',this,this.OnClick);
        CustomContainer.prototype.Dissolve.call(this);
    };

    /* PROGRESS BAR */
    /**
     * @class Progressbar
     * @classdesc A progressbar is a visualization of a progress. It shows a bar with 
     * a width corresponding to the progress and shows the percentage. Optionally 
     * a info text can be shown.
     * 
     *       ----------------------------------------------
     *      | ----------------------------                 |
     *      ||                        70% |                |  
     *      | ----------------------------                 |
     *      | Info text
     *       ----------------------------------------------
     *
     * @param {dict} params=(see_below) - A dictionary of initialization parameters. Below for details.
     * @param {boolean} [createDom=true] - To be used for inheritance of jsa elements. If set to false the HTML DOM element will not be created, e.g. CreateDom is not called.
     *
     * @comment Progressbar parameters
     * @property {Array.<string>} params.style=['jsa-progressbar']] - The CSS styles for the outer DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {Array.<string>} params.containerStyle=['jsa-progressbar-container']] - The CSS styles for the bar and percentage container DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {Array.<string>} params.barStyle=['jsa-progressbar-bar']] - The CSS styles for the bar DOM element when the tab is active. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {Array.<string>} params.percentageStyle=['jsa-progressbar-percentage']] - The CSS styles for the percentage DOM element when the tab is active. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {bool} params.hasInfo=false - Whether an info field shall be shown below the bar or not.
     * @property {Array.<string>} params.infoStyle=['jsa-progressbar-info']] - The CSS styles for the info fields DOM element when the tab is active. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {bool} params.isAnimated=false - Whether the progressbar shall be animated even if progress does not change, or not.
     * @property {Array.<string>} params.animatedStyle='jsa-progressbar-bar-animated' - The CSS styles for the animated bar DOM element. 
     * @property {Array.<string>} params.succesStyle='jsa-progressbar-bar-success' - The CSS styles for the success bar DOM element.
     * @property {Array.<string>} params.errorStyle='jsa-progressbar-bar-error' - The CSS styles for the error bar DOM element.
     * @comment Progressbar internals
     * @property {int} this.progress - (readonly) The current progress. Use SetProgress to change it.
     * @property {string} this.infoText - (readonly) The current info text. Use SetInfo to change it. 
     * @property {CustomFlatContainer} this.barContainer - (readonly) The bar container UI element.
     * @property {CustomFlatContainer} this.bar - (readonly) The bar UI element.
     * @property {CustomFlatContainer} this.percentage - (readonly) The percentage UI element.
     * @property {CustomFlatContainer} this.info - (readonly) The info field UI element. Only set if hasInfo was true.
     * @returns {this} Instance of the element itself to enable method chaining
     * @constructor Progressbar
     * @extends CustomFlatContainer
     * 
     * @example
     * // Create an tab that pops a message box if clicked
     * let progressbar = new jsa.Progressbar({
     *   progress: 22,
     *   hasInfo: true,
     *   infoText: 'Tasks completed by 22%'
     *   isAnimated: true
     * };
     * this.app.AddChild(progressbar);
     */

    function Progressbar(params, createDom=true) {
        CustomFlatContainer.call(this,params,false);
        //params
        this.style = ['jsa-progressbar'];
        this.containerStyle = ['jsa-progressbar-container'];
        this.barStyle = ['jsa-progressbar-bar'];
        this.percentageStyle = ['jsa-progressbar-percentage'];
        this.infoStyle = ['jsa-progressbar-info'];
        this.progress = 0;
        this.hasInfo = false;
        this.infoText = '';
        this.isAnimated = false;
        this.animatedStyle = 'jsa-progressbar-bar-animated';
        this.errorStyle = 'jsa-progressbar-bar-error';
        this.successStyle = 'jsa-progressbar-bar-success';
       
        CopyParams(this,params);

        //internals
        this.barContainer=null;
        this.bar = null;
        this.percentage = null;
        this.info = null;

        if(createDom) {
            this.CreateDom();
        }

        return this;
    };
    Progressbar.prototype = Object.create(CustomFlatContainer.prototype);

    /**
     * Creates the HTML DOM element. In general, CreateDom is called automatically by the constructor. 
     * Please see [UIElementA.CreateDom]{@link UIElementA#CreateDom} for the general explanation.
     * @method Progressbar.prototype.CreateDom
     */
    Progressbar.prototype.CreateDom = function() {
        CustomFlatContainer.prototype.CreateDom.call(this);
        //add a container for the bar and percentage
        this.barContainer = new CustomFlatContainer({
            style : this.containerStyle
        });
        this.AddChild(this.barContainer);
        this.bar = new CustomFlatContainer({
            style : this.barStyle
        });
        this.barContainer.AddChild(this.bar);
        this.percentage = new CustomFlatContainer({
            style : this.percentageStyle,
            content : this.progress + " %"
        });
        this.barContainer.AddChild(this.percentage);
        if(this.hasInfo) {
            this.info = new CustomFlatContainer({
                elementType : 'small',
                style : this.infoStyle,
                content : this.infoText
            });
            this.AddChild(this.info);
        }
        if(this.isAnimated) {
            this.SetAnimated(true);
        }
        return this;
    };

    /**
     * Dynamically enables or disables the annimation. 
     * @param {boolean} b - true=enable, false=disable.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method Progressbar.prototype.SetAnimated
     */
    Progressbar.prototype.SetAnimated = function(b) {
        if(b) {
            this.bar.GetDomElement().classList.add(this.animatedStyle);
        } else {
            this.bar.GetDomElement().classList.remove(this.animatedStyle);
        }
        return this;
    };

    /**
     * Dynamically enables or disables the the success style. 
     * @param {boolean} b - true=enable, false=disable.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method Progressbar.prototype.SetAnimated
     */
    Progressbar.prototype.SetSuccess = function(b) {
        if(b) {
            this.bar.GetDomElement().classList.add(this.successStyle);
        } else {
            this.bar.GetDomElement().classList.remove(this.successStyle);
        }
        return this;
    };

    /**
     * Dynamically enables or disables the the error style. 
     * @param {boolean} b - true=enable, false=disable.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method Progressbar.prototype.SetAnimated
     */
    Progressbar.prototype.SetError = function(b) {
        if(b) {
            this.bar.GetDomElement().classList.add(this.errorStyle);
        } else {
            this.bar.GetDomElement().classList.remove(this.errorStyle);
        }
        return this;
    };

    /**
     * Dynamically sets the progress of the progressbar. 
     * @param {int} progress - The new progress between 0 and 100.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method Progressbar.prototype.SetProgress
     * @example
     * // ...continues the main progressbar example
     * progressbar.SetProgress(33); //sets 33%
     * progressbar.SetProgress(33.4); //sets 33%
     * progressbar.SetProgress(120); //sets 100%
     * progressbar.SetProgress(-10); //sets 0%
     */
    Progressbar.prototype.SetProgress = function(progress) {
        //limit the progress value to integer an 0 to 100
        progress = Math.round(progress);
        progress = Math.min(100,progress); 
        progress = Math.max(0,progress);
        //if it is different than the old progress, it becomes effective
        if(this.progress != progress) {
            this.bar.GetDomElement().style.width = progress+'%';
            this.percentage.SetContent(progress + ' %');
            this.progress = progress;
        }
        return this;
    };

    /**
     * Dynamically sets the info text of the progressbar. 
     * This is only shown if hasInfo was true on creation.
     * @param {string} infoText - The new info field content.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method Progressbar.prototype.SetInfo
     * @example
     * // ...continues the main progressbar example
     * progressbar.SetInfo('Execution pending...');
     */
    Progressbar.prototype.SetInfo = function(infoText) {
        if(this.hasInfo && (this.infoText != infoText)) {
            this.info.SetContent(infoText);
            this.infoText = infoText;
        }
        return this;
    };


    /* NOTES MANAGER */
    /**
     * @class NotesManager
     * @classdesc A notes manager is a central entity to manage notes.
     * It manages the sequence of notes. Notes can be issued with PutNote and 
     * read with GetNote. Moreover, statistics on notes can be obtained. 
     * The notes manager is an observable that can inform a about new notes.
     * By default an [application]{@link Application} has a default
     * notes manager.  
     * 
     * See [PutNote]{@link NotesManager#PutNote} for the internal notes format.
     *
     * @param {int} this.totalNumberOfNotes - (readonly) The absolute counter of notes. This becomes als the ID of a new note.
     * @param {Array.<Note>} this.notes - (readonly) List of all current notes. Preferably use GetNotes() to get it.
     * @returns {this} Instance of the element itself to enable method chaining
     * @constructor NotesManager
     * @extends Observable
     * 
     * @example
     * // Listen to notes on the default notes manager
     * let app = new jsa.Application({});
     * app.notesManager.StartObserving(jsa.Observer({
     *   onNotifyCallback: function(event,source) {
     *     if(jsa.EVENT.IS_INSTANCE(event,jsa.EVENT.TYPES.ADD_NOTES)) {
     *       let note = event.value;
     *       alert('New note received: '+note.level+': '+note.message);
     *   }
     * });
     * //Issue a new note that cause then an alert message
     * app.notesManager.PutNote('Hello world!'); //-> alert('New note received: info: Hello world!')
     */
    function NotesManager() {
        Observable.call(this);
    
        this.notes = [];
        this.totalNumberOfNotes = 0;
    
        return this;
    };
    
    NotesManager.prototype = Object.create(Observable.prototype);

    /**
     * Returns the list of all notes in the notes manager.  
     * See [PutNote]{@link NotesManager#PutNote} for the internal notes format.
     * @returns {Array.<Note>} - The list of all current notes.
     * @method NotesManager.prototype.GetNotes
     *
     * @example
     * // Get all current notes of the notes manager and write them to the console
     * let notes = app.notesManager.GetNotes(),;
     * for(let i=0;i&lt;notes.length;i++)
     *   let note = notes[i];
     *   console.log(note.level+': '+note.message);
     * }
     */
    NotesManager.prototype.GetNotes = function() {
      return this.notes;  
    };

    /**
     * Adds a new note to the notes manager. A note is a text message and a optionally
     * a category. Moreover, it stores a unique id and the issuing time and informs all 
     * observers on the new note. Internally notes are managed as the following structure:
     * 
     *     {
     *         id: totalNumberOfNotes++,
     *         date: new Date(),
     *         message: message,
     *         level: level,
     *         new: true
     *     }
     * 
     * @param {string} message - The message to be added to the notes manager
     * @param {string} level='info' - A the category of the message. This can be used by the observers for filtering.
     * @returns {this} Instance of the element itself to enable method chaining
     * @fires [EventAdd]{@link EventAdd}(eventId= [EVENT.TYPES.ADD]{@link EVENT}+'/notes'; propertyName = 'notes')
     * @method NotesManager.prototype.PutNote
     *
     * @example
     * // Add an error message to the default notes manager
     * app.notesManager.PutNote('Something went seriously wrong, because...','error');
     */
    NotesManager.prototype.PutNote = function(message,level='info') {
        let note = {
            id: this.totalNumberOfNotes,
            date: new Date(),
            message: message,
            level: level,
            new: true
        };
    
        this.notes.push(note);
    
        this.totalNumberOfNotes++;
    
        this.Notify(new EventAdd(this,'notes',note));
    
        return this;
    };

    /**
     * Removes all existing notes from the notes manager and informs 
     * observers on that.
     * @returns {this} Instance of the element itself to enable method chaining
     * @fires [EventMethodCall]{@link EventMethodCall}(eventId= [EVENT.TYPES.METHOD_CALL]{@link EVENT}+'/ClearNotes'; methodName = 'ClearNotes')
     * @method NotesManager.prototype.ClearNotes
     *
     * @example
     * // Clear all notes from the default notes manager
     * app.notesManager.ClearNotes();
     */
    NotesManager.prototype.ClearNotes = function() {
        this.notes = [];
    
        this.Notify(new EventMethodCall(this,'ClearNotes',null,null));
    
        return this;
    };
    
    /* the current number of notes */

    /**
     * Get the current number of notes, i.e. GetNotes().length. 
     * @returns {int} - The number of notes currently within the notes manager.
     * @method NotesManager.prototype.GetNumberOfNotes
     *
     * @example
     * // Get the number of notes in default notes manager
     * let n = app.notesManager.GetNumberOfNotes();
     * alert('There are currently '+n+' notes in the notes manager');
     */
    NotesManager.prototype.GetNumberOfNotes = function() {
        return this.notes.length;
    };

    /**
     * Get the number of notes since start-up including the deleted/cleared ones.
     * @returns {int} - The total number of notes issued since the notes manager creation.
     * @method NotesManager.prototype.GetTotalNumberOfNotes
     *
     * @example
     * // Get the number of notes in default notes manager
     * let n = app.notesManager.GetTotalNumberOfNotes();
     * alert(n+' notes were issued since the app was created.');
     */
    NotesManager.prototype.GetTotalNumberOfNotes = function() {
        return this.totalNumberOfNotes;
    };

    /* SETTINGSMANAGER */
    /**
     * @class SettingsManager
     * @classdesc A settings manager stores key value pairs over 
     * multiple sessions of a programm, i.e. the values are 
     * persitantly stored such that they are available after 
     * a restart of the application. By default the settings manager
     * stores values as localStorage value.
     * By default an [application]{@link Application} has a default
     * settings manager.  
     *
     * @param {string} name='jsa' - The name of this settings set, i.e. the name of the storage item.
     * @param {Object} this.settings - (readonly) The settings object including all settings.
     * @returns {this} Instance of the element itself to enable method chaining
     * @constructor SettingsManager
     * @extends Observable
     * 
     * @example
     * // Listen to default settings manager
     * let app = new jsa.Application({});
     * app.settingsManager.StartObserving(jsa.Observer({
     *   onNotifyCallback: function(event,source) {
     *     if('CHANGED' == event.eventId) {
     *       console.log('Setting changed: '+event.data.key+'='+event.data.value);
     *     } else if('DELETED' == event.eventId) {
     *       console.log('Setting deleted: '+event.data.key);
     *     } else if('CLEARED' == event.eventId) {
     *       console.log('All settings have been deleted');
     *     }
     *   }
     * }));
     * // Work with the settings manager
     * console.log(app.settingsManager.Has('user.name','mike')); //-> false
     * app.settingsManager.Set('user.name','mike');
     * app.settingsManager.Set('user.expertMode',false);
     * console.log(app.settingsManager.Has('user.name','mike')); //-> true
     * app.settingsManager.Delete('user.name','mike');
     * console.log(app.settingsManager.Has('user.name','mike')); //-> false
     * app.settingsManager.Clear();
     */
    
    function SettingsManager(name='jsa') {
        Observable.call(this);
        this.name = name;
        this.settings = {}; //empty dictionary
    };
    SettingsManager.prototype = Object.create(Observable.prototype);

    /**
     * Persistently stores all settings values. This is usually called on every
     * set operation. No need to call it manually.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method SettingsManager.prototype.Store
     */
    SettingsManager.prototype.Store = function() {
        localStorage.setItem(this.name, JSON.stringify(this.settings));
        return this;
    };

    /**
     * Loads settings value from the local storage and restores them
     * to the internal data structure. Should be called after 
     * initiating the settings manager.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method SettingsManager.prototype.Restore
     */
    SettingsManager.prototype.Restore = function() {
        this.settings = {}; //initialize the storage
        let storedStr = localStorage.getItem(this.name);
        if (storedStr) {
            let storedObjects = JSON.parse(localStorage.getItem(this.name));
            if(storedObjects instanceof Object) {
                this.settings = JSON.parse(localStorage.getItem(this.name))
            }
        }
        return this;
    };
    
    /**
     * Empties the settings structure completely and 
     * removes all references to it from the computer.
     * @returns {this} Instance of the element itself to enable method chaining
     * @fires [EventMethodCall]{@link EventMethodCall}(eventId= [EVENT.TYPES.METHOD_CALL]{@link EVENT}+'/Clear'; methodName = 'Clear')
     * @method SettingsManager.prototype.Clear
     */
    SettingsManager.prototype.Clear = function() {
        this.settings = {};
        localStorage.removeItem(this.name);
        //inform observers
        this.Notify(new EventMethodCall(this,"Clear",null,null));
        return this;
    };

     /**
     * Sets or creates a value inside the settings manager, which is identified
     * with a unique key.
     * @param {string} key - A key under which the value shall be stored. 
     * A key can be a path separated by '.', which describes then a substructure 
     * inside the settings object, i.e. 'user.settings.name' refers to this.user.settings.name.
     * @param {Object} value - The value to be stored at the key. It can be a primitive value or an object.
     * @returns {this} Instance of the element itself to enable method chaining
     * @fires [EventAdd]{@link EventAdd}(eventId= [EVENT.TYPES.ADD]{@link EVENT}+key; propertyName = key)
     * @method SettingsManager.prototype.Set
     */
    SettingsManager.prototype.Set = function(key,value) {
        let keySequence = key.split('.');
        let container = this.settings;
        //iterate until the second last key
        for(let i=0;i<keySequence.length-1;i++) {
            let k = keySequence[i];
            if(!(container instanceof Object)) {
                let handledKeys = keySequence.slice(0,i);
                throw new Error("Error setting value for "+key+": path "+handledKeys.join('.')+" is a primitive value and can not have subkeys");
            }
            if(!(k in container)) {
                newContainer = {};
                container[k] = newContainer;
            }
            container = container[k];
        }
        //the last element is set to the value
        if(!(container instanceof Object)) {
            let handledKeys = keySequence.slice(0,keySequence.length-1);
            throw new Error("Error setting value for "+key+": path "+handledKeys.join('.')+" is a primitive value and can not have subkeys");
        }
        let finalKey = keySequence[keySequence.length-1];
        container[finalKey] = value;
        this.Store();
        //inform observers
        this.Notify(new EventAdd(this,key,value));
        return this;
    };

    /**
     * Gets value for a key from the settings manager.
     * @param {string} key - A key under which the value shall be stored. 
     * A key can be a path separated by '.', which describes then a substructure 
     * inside the settings object, i.e. 'user.settings.name' refers to this.user.settings.name.
     * @param {Object} def=undefined - (optional) The value to be returned if the key does not exist.
     * @returns {Object} The value stored for the key or def if the key is unknown.
     * @method SettingsManager.prototype.Get
     */
    SettingsManager.prototype.Get = function(key,def=undefined) {
        let value = def;
        let keySequence = key.split('.');
        try {
            let container = this.settings;
            //iterate until the second last key
            for(let i=0;i<keySequence.length-1;i++) {
                let k = keySequence[i];
                container = container[k];
            }
            //the last element is set to the value
            let finalKey = keySequence[keySequence.length-1];
            if(finalKey in container) { //if is necessary to prevent returning undefined although a def value was given.
                value = container[finalKey];
            }
        } catch(e) {
            //Nothing, since this means the value is not included
        }
        return value;
    };

    /**
     * Checks if a specific key exists inside the settings manager, e.g. a value 
     * for that key was set before.
     * @param {string} key - A key under which the value shall be stored. 
     * A key can be a path separated by '.', which describes then a substructure 
     * inside the settings object, i.e. 'user.settings.name' refers to this.user.settings.name.
     * @returns {boolean} True, if the key exists and false if not.
     * @method SettingsManager.prototype.Has
     */
    SettingsManager.prototype.Has = function(key) {
        let has = false;
        let keySequence = key.split('.');
        try {
            let container = this.settings;
            for(let i=0;i<keySequence.length;i++) {
                let k = keySequence[i];
                container = container[k];
            }
            has = container!==undefined;
        } catch(e) {
            //Nothing, since this means the value is not included
        }
        return has;
    };

    /**
     * Removes a key from the settings manager.
     * @param {string} key - A key under which the value shall be stored. 
     * A key can be a path separated by '.', which describes then a substructure 
     * inside the settings object, i.e. 'user.settings.name' refers to this.user.settings.name.
     * @returns {this} Instance of the element itself to enable method chaining
     * @fires [EventRemove]{@link EventRemove}(eventId= [EVENT.TYPES.REMOVE]{@link EVENT}+key; propertyName = key)
     * @method SettingsManager.prototype.Delete
     */
    SettingsManager.prototype.Delete = function(key) {
        let keySequence = key.split('.');
        //iterate until the second last key
        let i=0;
        try {
            let container = this.settings;
            for(;i<keySequence.length-1;i++) {
                let k = keySequence[i];
                container = container[k];
            }
            //the last element is set to the value
            let finalKey = keySequence[keySequence.length-1];
            let value = container[finalKey];
            delete container[finalKey];
            this.Store();
            //inform observers
            this.Notify(new EventRemove(this,key,value));
        } catch(e) {
            let handledKeys = keySequence.slice(0,i);
            throw new Error("Settings path "+handledKeys.join('.')+" can not be deleted, because it does not exist.");
        }
        return this;
    };


    /* APPLICATION */
    /**
     * @class Application
     * @classdesc The application is the central object of a jsApplication. It is assumed that there 
     * is exactly on instance of an Application whose DOM element is document.body, i.e. all other
     * jsa elements are children of the application. In addition, an application initializes a 
     * menubar and a main [view manager]{@link ViewManager}, such that all other elements of the application shall 
     * take place in [views]{@link View}. It uses the full browser rendering area.
     * 
     *      ----------------------------------------------------------------------------
     *     | Browser: http://myjsaapplication.html //////////////////////////////////// |
     *     |----------------------------------------------------------------------------|
     *     | -------------------------------------------------------------------------- |
     *     || Label     | Menu                             | Toolbar (optional)        |<- jsApplication
     *     ||--------------------------------------------------------------------------||
     *     || Default view manager: app.viewManager                                  |^||
     *     ||                                                                        |-||
     *     ||                                                                        | ||
     *     ||                                                                        | ||
     *     ||                                                                        |x||
     *     ||                                                                        |x||
     *     ||                (add new views and UI elements here)                    |x|<- Scrollbar if view gets to large
     *     ||                                                                        |x||
     *     ||                                                                        |x||
     *     ||                                                                        | ||
     *     ||                                                                        |_||
     *     ||                                                                        |v||
     *     ||--------------------------------------------------------------------------||
     *     || Statusbar (optional)                                                     ||
     *     | -------------------------------------------------------------------------- |
     *      ----------------------------------------------------------------------------
     * 
     * Besides visual elements the application also offers a [selection]{@link SelectionManager},
     * [command]{@link CommandManager}, a [settings]{@link SettingsManager}, and a 
     * [notes manager]{@link NotesManager}.
     *
     * @param {dict} params=(see_below) - A dictionary of initialization parameters. Below for details.
     * @param {boolean} [createDom=true] - To be used for inheritance of jsa elements. If set to false the HTML DOM element will not be created, e.g. CreateDom is not called.
     *
     * @comment Application parameters
     * @property {string} params.name='jsApplication' - The name of application to be shown as the label.
     * @property {string} params.version='1.0' - The version of your application. User jsa.version when looking for the jsa version.
     * @property {Array.<string>} params.style=['jsa-app']] - The CSS class(s) of the applications main HTML element. 
     * @property {HTML_DOM_ELEMENT} params.containerDom=document.body - The parent HTML DOM element under which the js application
     * shall be created. By default this is the body element, but other options like a dedicated div container are possible. If null is 
     * given the application is not automatically attached to the website, but it must be added manually by retrieving its DOM element 
     * with app.GetDomElement(). 
     * @property {dict} params.settings={} - A storage for application wide settings. This can be completely customized
     * @property {boolean} params.hasTitlebar=true - Whether the application shall have a titlebar/menubar or not.
     * @property {boolean} params.hasLabel=true - Whether the application shall show its label in the upper left corner.
     * @property {boolean} params.hasMenu=true - Whether the application has a drop down menu in the titlebar.
     * @property {boolean} params.hasToolbar=true - Whether the application has a toolbar right of the menu in the titlebar.
     * @property {boolean} params.hasTabbar=false - Whether the application has a tabbar to control the main view manager. 
     * By default this is created on top of the view manager.
     * @property {boolean} params.enableTooltips=true - Enables tooltips globaly for the appliation. In addition, each element must enable its own tooltip to show it.
     * Bt if tooltips are off for the application, no tooltip will be shown never.
     * @property {int} params.tooltipDelay=1000 - The time the mouse must hover over the UI element before the tooltip is shown. Is given in milli seconds.
     * @property {boolean} params.syncTabbarStyleWithViewHeaders=false - Whether the color of the tabbar's tabs shall be taken from the view headers. 
     * This can be used to create colorful tabs.
     * @property {boolean} params.hasStatusbar=false - Whether the application has a statusbar to show information below the view manager. 
     * @property {Array.<string>} params.viewManagerStyle=['jsa-view-manager']] - The CSS styles for view managers outer DOM element. See [CustomUiElement]{@link CustomUiElement} for details on style arrays.
     * @property {HTML_DOM_ELEMENT} params.domElement=document.body - The basic DOM element. Usually keep this on the default value. All other options are untested!
     * @property {boolean} params.hasSettingsManager=true - Whether a default settings manager shall be created or not.
     * @comment Application internals
     * @property {Application} this.app - (readonly) This is the app itself
     * @property {CustomFlatContainer} this.mainUi - The UI element that contains all the main UI elements of the application.
     * It is usually a top to bottom stack of titlebar, (tabbar,) and view manager.
     * @property {CustomFlatContainer} this.titlebar - The UI element of the titlebar of the application if hasTitlebar was true on creation.
     * @property {CustomFlatContainer} this.label - The UI element of the application label if hasLabel was true on creation.
     * @property {Menu} this.menu - The UI element of the main menu of the application if hasMenu was true on creation.
     * @property {CustomFlatContainer} this.toolbar - The UI element of the main toolbar of the application if hasToolbar was true on creation.
     * @property {CustomFlatContainer} this.statusbar - The UI element of the statusbar of the application if hasStatusbar was true on creation.
     * @property {CommandManager} this.commandManager - (readonly) The default command manager
     * @property {NotesManager} this.notesManager - (readonly) The default notes manager
     * @property {SelectionManager} this.selectionManager - (readonly) The default selection manager
     * @property {KeyManager} this.keyManager - (readonly) Not implemented. Placeholder for central key management.
     * @property {SettingsManager} this.settingsManager - (readonly) The default settings manager of the application. 
     * @property {string} this.startupLevel - (readonly) The current startup level of the application.
     * Use it to store and receive settings.
     *
     * @returns {this} Instance of the element itself to enable method chaining
     * @constructor Application
     * @extends CustomFlatContainer
     * 
     * @example 
     * // Create basic application and add a main view.
     * // Most of the following parameters are set to their 
     * // default values. This is for demonstration and can 
     * // normally be omitted.
     * let app = new jsa.Application( {
     *     name:'My First Application',
     *     hasLabel:true,
     *     hasTitlebar:true,
     *     hasToolbar:true,
     * });
     * let myView = new jsa.View({
     *   name:'Welcome',
     *   content:'Hello World!'
     * });
     * app.viewManager.AddChild(myView);
     * app.viewManager.ActivateView(myView);
     */
    function Application(params,createDom=true) {
        CustomFlatContainer.call(this,params,false);

        //members
        this.name = 'jsApplication';
        this.version = '1.0';
        this.settings = {}; //storage for application wide settings
        this.hasTitlebar = true;
        this.hasLabel = true;
        this.hasMenu = true;
        this.hasToolbar = true;
        this.hasTabbar = false;
        this.enableTooltips = true;
        this.tooltipDelay = 1000; //ms
        this.syncTabbarStyleWithViewHeaders = false;
        this.hasStatusbar = false;
        this.style = ['jsa-app'];
        this.viewManagerStyle = ['jsa-view-manager'];
        this.tabbarStyle = ['jsa-tabbar','jsa-tabbar-top','jsa-app-tabbar'];
        this.hasSettingsManager = true;
        this.containerDom = document.body;
        

        //copy parameters
        CopyParams(this,params);

        this.app = this; //this is the app itself
        this.hasTooltip = false; //must be false for the app itself.
        this.mainUi = null;
        this.titlebar = null;
        this.label = null;
        this.menu = null;
        this.toolbar = null;
        this.viewManager = null;
        this.statusbar = null;
        this.commandManager = new CommandManager();
        this.notesManager = new NotesManager();
        this.selectionManager = new SelectionManager();
        this.settingsManager = null;
        this.keyManager = null;
        this.startupLevel = null;
        this.currentTooltip = {
            UiElement : null,
            timeout : null,
            position: {
                x : 0,
                y : 0
            }
        }

        //Create DOM 
        if(createDom) {
            this.CreateDom();
        }

        return this;
    };
    Application.prototype = Object.create(CustomFlatContainer.prototype);

    /**
     * Creates the HTML DOM element. In general, CreateDom is called automatically by the constructor. 
     * Please see [UIElementA.CreateDom]{@link UIElementA#CreateDom} for the general explanation.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method Application.prototype.CreateDom
     */
    Application.prototype.CreateDom = function() {
        CustomFlatContainer.prototype.CreateDom.call(this);
        //if a container exists, the app is automatically to the given 
        if(this.containerDom) {
            this.containerDom.appendChild(this.GetDomElement());
        }

        this.mainUi = new CustomFlatContainer({
            id: this.id+'-main-ui',
            style: ['jsa-app-main-ui']
        })
        this.AddChild(this.mainUi);

        this.titlebar = null;
        this.toolbar = null;
        if(this.hasTitlebar) {

            this.titlebar = new CustomFlatContainer({
                id: this.id+'-titlebar',
                style: ['jsa-app-titlebar']
            })
            this.mainUi.AddChild(this.titlebar);
            
            if(this.hasLabel) {
                if(this.settings.logo) {
                    this.label = new CustomFlatContainer({
                        id: this.id+'-label',
                        content : '<img height="20" src="'+this.settings.logo+'">',
                        style: ['jsa-app-label']
                    });
                } else {
                    this.label = new CustomFlatContainer({
                        id: this.id+'-label',
                        content : this.name,
                        style: ['jsa-app-label']
                    });
                }            
                this.titlebar.AddChild(this.label);
            }

            if(this.hasMenu) {
                this.menu = new Menu({
                    id: this.id+'-menu',
                    orientation: 'horizontal'
                })
                this.titlebar.AddChild(this.menu);

                if(this.hasToolbar) {
                    id: this.id+'-toolbar',
                    this.toolbar = new Toolbar({
                        style: ['jsa-toolbar','jsa-app-toolbar']
                    });
                    this.titlebar.AddChild(this.toolbar);
                }
            }
        }
        if(this.hasTabbar) {
            this.tabbar = new Tabbar({
                id: this.id+'-tabbar',
                style: this.tabbarStyle
            });
            this.mainUi.AddChild(this.tabbar);
        }

        this.viewManager = new ViewManager({
            id: this.id+'-view-manager',
            style: this.viewManagerStyle
        });
        this.mainUi.AddChild(this.viewManager);

        if(this.hasStatusbar) {
            this.statusbar = this.label = new CustomFlatContainer({
                id: this.id+'-statusbar',
                style: ['jsa-app-statusbar']
            });
            this.mainUi.AddChild(this.statusbar);
        }

        if(this.hasTabbar) {
            this.tabbar.SyncWithViewManager(this.viewManager,this.syncTabbarStyleWithViewHeaders,true);
        }

        if(this.hasSettingsManager) {
            this.settingsManager = new SettingsManager();
            this.settingsManager.Restore(); //load settings by default
        }

        if(this.enableTooltips) {
            this.tooltipBubble = new Bubble({
                id: this.id+'-tooltip',
                name: 'Tooltip',
                isResizable: false,
                content: '',
                isMinimized: false,
                isMinimizable: false,
                isCloseable: false,
                canDock: false,
                style: ['jsa-bubble','jsa-app-tooltip'],
            });
            this.AddChild(this.tooltipBubble);
        }

        return this;
    };

    /**
     * Adds a new note to the central notes manager of the application.
     * See also [NotesManager.PutNote]{@link NotesManager#PutNote}.
     * @param {string} message - The message to be added to the notes manager
     * @param {string} level='info' - A the category of the message. This can be used by the observers for filtering.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method Application.prototype.Note
     *
     * @example
     * // Add an error message to the default notes manager
     * app.Note('Something went seriously wrong, because...','error');
     */
    Application.prototype.Note = function(message,level='info') {
        if(this.notesManager) {
            this.notesManager.PutNote(message,level);
        } else {
            console.log(level + ": " + message);
        }
        return this;
    };

    /**
     * Initiates displaying a tooltip on some of the UI elements of the application. 
     * This function does not show the tooltip, but starts the timer to show it.
     * If StopTooltip is not called before the timeout, the tooltip will be shown.
     * @param {UIElementA} uielement - The UI element of the tooltip.
     * @param {int} x - x position for the tooltip to point at
     * @param {int} y - y position for the tooltip to point at
     * @returns {this} Instance of the element itself to enable method chaining
     * @method Application.prototype.TriggerTooltip
     */
    Application.prototype.TriggerTooltip = function(uielement,x,y) {
        if(this.enableTooltips && (!this.currentTooltip.uielement || !this.currentTooltip.uielement.IsChildOf(uielement))) {  
            //x and y are the same it is probably a parent of the original tooltip, so it shall be prevented to show the parent tooltip
            //stop any previous timeout
            if(this.currentTooltip.timeout) window.clearTimeout(this.currentTooltip.timeout);
            this.currentTooltip.uielement = uielement
            this.currentTooltip.position.x = x;
            this.currentTooltip.position.y = y;
            let self = this;
            this.currentTooltip.timeout = window.setTimeout(function() {
                self.tooltipBubble.SetContent(self.currentTooltip.uielement.GetTooltip());
                self.tooltipBubble.PopupOnDomElement(self.currentTooltip.uielement.GetDomElement());
            },this.tooltipDelay);
        } 
        return this;
    };

    /**
     * Stops any current tooltip which was triggered from beeing shown. 
     * If still within the tooltip timeout, the tooltip will not be shown.
     * If it is already shown, it will be hidden again.
     * @returns {this} Instance of the element itself to enable method chaining
     * @method Application.prototype.StopTooltip
     */
    Application.prototype.StopTooltip = function() {
        if(this.enableTooltips) {
            //stop any previous timeout
            this.tooltipBubble.Hide();
            if(this.currentTooltip.timeout) window.clearTimeout(this.currentTooltip.timeout);
            this.currentTooltip.uielement = null
            this.currentTooltip.position.x = 0;
            this.currentTooltip.position.y = 0;
            this.currentTooltip.timeout = null;
        } 
        return this;
    };


    /**
     * Sets the current startup level of the application. This is intended for a 
     * longer loading process also containing asynchroneous initialization tasks. 
     * This enables to react on specific start-up stages of the application.
     * This is an internal function. [InitReady()]{@link Application#InitReady}, 
     * [DataReady()]{@link Application#DataReady}, [MenuReady()]{@link Application#MenuReady},
     * [ToolsReady()]{@link Application#ToolsReady}, [ViewsReady()]{@link Application#ViewsReady},
     * and [AppReady()]{@link Application#AppReady} should be used.
     * See also [APPLICATION_STARTUP_LEVELS]{@link APPLICATION_STARTUP_LEVELS}.
     * @param {string} level - An start-up level as defined in [APPLICATION_STARTUP_LEVELS]{@link APPLICATION_STARTUP_LEVELS}.
     * @fires [EventSet]{@link EventSet}(eventId= [EVENT.TYPES.SET_STARTUP_LEVEL]{@link EVENT}; propertyName = 'startupLevel')
     * @returns {this} Instance of the element itself to enable method chaining
     * @method Application.prototype.SetStartupLevel
     *
     * @example
     * // The regular initialization phase of an application
     * // The follwing sequence can be used, but is not a must.
     * // If no start-up level information is necessary, non of 
     * // the following functions must be called.
     * app = new jsa.Application({});
     * app.InitReady();
     * ...
     * app.DataReady();
     * ...
     * app.MenuReady();
     * ...
     * app.ToolsReady();
     * ...
     * app.ViewsReady();
     * ...
     * app.AppReady();
     * //Done
     */
    Application.prototype.SetStartupLevel = function(level) {
        let oldLevel = this.startupLevel;
        this.startupLevel = level;
        this.Notify(new EventSet(this,'startupLevel',this.startupLevel,oldLevel));
        return this;
    };

    /**
     * Indicate to the observers that the initialization of the application
     * has just begone. The app object is ready but nothing else.
     * See [SetStartupLevel]{@link Application#SetStartupLevel} for examples.
     * @returns {this} Instance of the element itself to enable method chaining
     * @fires [EventSet]{@link EventSet}(eventId= [EVENT.TYPES.SET_STARTUP_LEVEL]{@link EVENT}; propertyName = 'startupLevel')
     * @method Application.prototype.InitReady
     */
    Application.prototype.InitReady = function() {
        this.SetStartupLevel(APPLICATION_STARTUP_LEVELS.INIT);
        return this;
    };

    /**
     * Indicate to the observers that the data is ready, e.g.
     * one or several data base connections have been initialized.
     * See [SetStartupLevel]{@link Application#SetStartupLevel} for examples.
     * @returns {this} Instance of the element itself to enable method chaining
     * @fires [EventSet]{@link EventSet}(eventId= [EVENT.TYPES.SET_STARTUP_LEVEL]{@link EVENT}; propertyName = 'startupLevel')
     * @method Application.prototype.DataReady
     */
    Application.prototype.DataReady = function() {
        this.SetStartupLevel(APPLICATION_STARTUP_LEVELS.DATA);
        return this;
    };

    /**
     * Indicate to the observers that the basic menus are ready, e.g.
     * for adding menus views afterwards. 
     * See [SetStartupLevel]{@link Application#SetStartupLevel} for examples.
     * @returns {this} Instance of the element itself to enable method chaining
     * @fires [EventSet]{@link EventSet}(eventId= [EVENT.TYPES.SET_STARTUP_LEVEL]{@link EVENT}; propertyName = 'startupLevel')
     * @method Application.prototype.MenuReady
     */
    Application.prototype.MenuReady = function() {
        this.SetStartupLevel(APPLICATION_STARTUP_LEVELS.MENU);
        return this;
    };

    /**
     * Indicate to the observers that the basic tools are ready, e.g.
     * for adding custom tools afterwards.
     * See [SetStartupLevel]{@link Application#SetStartupLevel} for examples.
     * @returns {this} Instance of the element itself to enable method chaining
     * @fires [EventSet]{@link EventSet}(eventId= [EVENT.TYPES.SET_STARTUP_LEVEL]{@link EVENT}; propertyName = 'startupLevel')
     * @method Application.prototype.ToolsReady
     */
    Application.prototype.ToolsReady = function() {
        this.SetStartupLevel(APPLICATION_STARTUP_LEVELS.TOOLS);
        return this;
    };

    /**
     * Indicate to the observers that the basic views are ready, e.g.
     * for adding custom views afterwards.
     * See [SetStartupLevel]{@link Application#SetStartupLevel} for examples.
     * @returns {this} Instance of the element itself to enable method chaining
     * @fires [EventSet]{@link EventSet}(eventId= [EVENT.TYPES.SET_STARTUP_LEVEL]{@link EVENT}; propertyName = 'startupLevel')
     * @method Application.prototype.ViewsReady
     */
    Application.prototype.ViewsReady = function() {
        this.SetStartupLevel(APPLICATION_STARTUP_LEVELS.VIEWS);
        return this;
    };

    /**
     * Indicate to observers that the application is completely initialized.
     * See [SetStartupLevel]{@link Application#SetStartupLevel} for examples.
     * @returns {this} Instance of the element itself to enable method chaining
     * @fires [EventSet]{@link EventSet}(eventId= [EVENT.TYPES.SET_STARTUP_LEVEL]{@link EVENT}; propertyName = 'startupLevel')
     * @method Application.prototype.AppReady
     */
    Application.prototype.AppReady = function() {
        this.SetStartupLevel(APPLICATION_STARTUP_LEVELS.END);
        return this;
    };

    
    /* CREATE AND RETURN NAMESPACE */
    return {
        VERSION : VERSION,
        DIRECTION_OPPOSITE : DIRECTION_OPPOSITE,
        APPLICATION_STARTUP_LEVELS : APPLICATION_STARTUP_LEVELS,
        allRedirectedDomCallbacks : allRedirectedDomCallbacks,
        Mixin : Mixin,
        GetBrowserWidth : GetBrowserWidth,
        GetBrowserHeight : GetBrowserHeight,
        RedirectDomCallbackToUiElement : RedirectDomCallbackToUiElement,
        RemoveRedirectDomCallbackFromUiElement : RemoveRedirectDomCallbackFromUiElement,
        CopyParams : CopyParams,
        CreateDomElementWithUniqueId : CreateDomElementWithUniqueId,
        MultiKeyMap : MultiKeyMap,
        Observer : Observer,
        Observable : Observable,
        EVENT : EVENT,
        EventA : EventA,
        UIElementA : UIElementA,
        CustomContainerA : CustomContainerA,
        CustomUiElement : CustomUiElement,
        CustomContainer : CustomContainer,
        CustomFlatContainer : CustomFlatContainer,
        Button : Button,
        Icon : Icon,
        Label : Label,
        TextCtrl : TextCtrl,
        TextareaCtrl : TextareaCtrl,
        CheckboxCtrl : CheckboxCtrl,
        RadioCtrl : RadioCtrl,
        SelectCtrl : SelectCtrl,
        TableCol : TableCol,
        TableRow : TableRow,
        Table : Table,
        CommandA : CommandA,
        CustomCommand : CustomCommand,
        ChangeViewCommand : ChangeViewCommand,
        Menu : Menu,
        MenuEntry : MenuEntry,
        View : View,
        ViewManager : ViewManager,
        Bubble : Bubble,
        Sticky : Sticky,
        Modal : Modal,
        MsgBox : MsgBox,
        Splash : Splash,
        DashboardView : DashboardView,
        Dash : Dash,
        Tool : Tool,
        Tabbar : Tabbar,
        Tab : Tab,
        Progressbar : Progressbar,
        Selection : Selection,
        SelectionManager : SelectionManager,
        SettingsManager : SettingsManager,
        Application : Application
    };

})();

window.jsa = jsa; //make sure jsa is not removed during minify