You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lo...@apache.org on 2019/09/19 09:15:43 UTC

[myfaces-tobago] branch master updated (7762b5e -> 089ad5e)

This is an automated email from the ASF dual-hosted git repository.

lofwyr pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/myfaces-tobago.git.


    from 7762b5e  docs
     new 230b47f  docs/typo
     new 25f49b4  Introducing <tobago-behavior> instead of data-tobago-command attribute. Renaming command attribute "transition" to NOT "decoupled". Tests: call events with .dispatchEvent(new Event(..., {bubbles: true}));
     new 089ad5e  typo

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../renderkit/renderer/CommandRendererBase.java    |   7 +-
 .../renderer/DecodingCommandRendererBase.java      |   3 +-
 .../renderer/DecodingInputRendererBase.java        |   3 +-
 .../internal/renderkit/renderer/FileRenderer.java  |   7 +-
 .../internal/renderkit/renderer/InRenderer.java    |   5 +-
 .../internal/renderkit/renderer/PageRenderer.java  |   4 +-
 .../internal/renderkit/renderer/PanelRenderer.java |   6 +-
 .../renderkit/renderer/ProgressRenderer.java       |   4 +-
 .../renderer/SelectBooleanCheckboxRenderer.java    |   9 +-
 .../renderer/SelectManyCheckboxRenderer.java       |   5 +-
 .../renderer/SelectManyListboxRenderer.java        |   7 +-
 .../renderkit/renderer/SelectManyRendererBase.java |   3 +-
 .../renderer/SelectManyShuttleRenderer.java        |   6 +-
 .../renderer/SelectOneChoiceRenderer.java          |   7 +-
 .../renderer/SelectOneListboxRenderer.java         |   7 +-
 .../renderkit/renderer/SelectOneRadioRenderer.java |   7 +-
 .../renderkit/renderer/SelectOneRendererBase.java  |   3 +-
 .../internal/renderkit/renderer/SheetRenderer.java |  38 +--
 .../internal/renderkit/renderer/StarsRenderer.java |   5 +-
 .../renderkit/renderer/TabGroupRenderer.java       |  20 +-
 .../renderkit/renderer/TextareaRenderer.java       |   4 +-
 .../renderer/TobagoClientBehaviorRenderer.java     |   4 +-
 .../renderkit/renderer/TreeSelectRenderer.java     |   6 +-
 .../taglib/component/SuggestTagDeclaration.java    |   2 +-
 .../taglib/declaration/HasPlaceholder.java         |   4 -
 .../myfaces/tobago/internal/util/RenderUtils.java  |  12 +
 .../myfaces/tobago/renderkit/RendererBase.java     | 175 ++++++++++
 .../tobago/renderkit/html/CustomAttributes.java    |  16 +-
 .../tobago/renderkit/html/DataAttributes.java      |  11 -
 .../tobago/renderkit/html/HtmlElements.java        |   1 +
 .../tobago/webapp/TobagoResponseWriter.java        |  13 +-
 .../tobago/example/demo/TextareaController.java    |  20 ++
 .../50-migration/96-migration/3.0_to_4.0.xhtml     |   2 +-
 .../20-component/010-input/10-in/In.test.js        |   2 +-
 .../content/20-component/010-input/10-in/In.xhtml  |   2 +
 .../010-input/20-suggest/Suggest.test.js           |  12 +-
 .../010-input/30-textarea/Textarea.xhtml           |  13 +-
 .../20-component/010-input/40-date/Date.test.js    |  18 +-
 .../010-input/50-input-group/Group.test.js         |  22 +-
 .../10-selectBooleanCheckbox/Checkbox.test.js      |  12 +-
 .../15-selectBooleanToggle/Toggle.test.js          |  12 +-
 .../030-select/20-selectOneChoice/Dropdown.test.js |   8 +-
 .../030-select/30-selectOneRadio/Radio.test.js     |   8 +-
 .../030-select/40-selectOneListbox/Listbox.test.js |   8 +-
 .../50-selectManyCheckbox/Multi_Checkbox.test.js   |  16 +-
 .../content/20-component/060-popup/Popup.test.js   |  36 +--
 .../content/20-component/070-tab/Tab_Group.test.js |   6 +-
 .../080-sheet/10-sort/Sheet_Sorting.test.js        | 108 +++----
 .../080-sheet/30-event/Sheet_Event.test.js         |  38 +--
 .../080-sheet/70-tree/Sheet_Tree.test.js           |   2 +-
 .../090-tree/01-select/Tree_Select.test.js         |  46 +--
 .../06-validation/00/Content_Validation.test.js    |  26 +-
 .../30-concept/06-validation/01/JSR_303.test.js    |  10 +-
 .../08-form/10-required/Required.test.js           |  14 +-
 .../30-concept/08-form/20-ajax/Ajax.test.js        |  22 +-
 .../webapp/content/30-concept/08-form/Form.test.js |   4 +-
 .../30-concept/51-for-each/For_Each.test.js        |   6 +-
 .../00-collapsible-box/Collapsible_Box.test.js     |  50 +--
 .../10-collapsible-popup/Collapsible_Popup.test.js |  34 +-
 .../20-collapsible-panel/Collapsible_Panel.test.js |  40 +--
 .../Collapsible_Section.test.js                    |  40 +--
 .../content/30-concept/75-resize/Resize.xhtml      |  17 +-
 .../15-suggest-method/Suggest_Method.test.js       |   4 +-
 .../1020-suggest-quotMark/Suggest_QuotMark.test.js |   2 +-
 .../webapp/content/40-test/1040-date/Date.test.js  |   2 +-
 .../Date_TobagoConverter.test.js                   |   2 +-
 .../4050-ajax-dropdown/Ajax_Dropdown.test.js       |   4 +-
 .../40-test/4000-button-link/Button_Link.test.js   |   6 +-
 .../40000-style/100-headings/Headings.test.js      |   2 +-
 .../4600-gridLayout/90-style-tag/Style_Tag.test.js |   2 +-
 .../content/40-test/4950-severity/Severity.test.js |   2 +-
 .../20-ajax-execute/Ajax_Execute.test.js           |   6 +-
 .../Ajax_Special_Character.test.js                 |   2 +-
 .../content/40-test/6000-event/Event.test.js       |   2 +-
 .../content/40-test/6500-behavior/Behavior.test.js |  16 +-
 .../src/main/npm/ts/tobago-calendar.ts             |   6 +-
 .../src/main/npm/ts/tobago-command.test.ts         |  40 ---
 .../src/main/npm/ts/tobago-command.ts              | 356 +++++++++------------
 .../src/main/npm/ts/tobago-core.ts                 |   6 +-
 .../src/main/npm/ts/tobago-popup.ts                |  20 +-
 .../src/main/npm/ts/tobago-scroll.ts               |   6 +-
 .../src/main/npm/ts/tobago-sheet.ts                |   6 +-
 .../src/main/npm/ts/tobago-tab.ts                  |  12 +-
 83 files changed, 837 insertions(+), 725 deletions(-)
 delete mode 100644 tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-command.test.ts


[myfaces-tobago] 03/03: typo

Posted by lo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

lofwyr pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/myfaces-tobago.git

commit 089ad5e5ab7bf319f77ae6e562b84a46679eb4f4
Author: Udo Schnurpfeil <lo...@apache.org>
AuthorDate: Thu Sep 19 11:15:25 2019 +0200

    typo
---
 .../webapp/content/10-intro/50-migration/96-migration/3.0_to_4.0.xhtml  | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/10-intro/50-migration/96-migration/3.0_to_4.0.xhtml b/tobago-example/tobago-example-demo/src/main/webapp/content/10-intro/50-migration/96-migration/3.0_to_4.0.xhtml
index d37dc54..fa3d7c5 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/10-intro/50-migration/96-migration/3.0_to_4.0.xhtml
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/10-intro/50-migration/96-migration/3.0_to_4.0.xhtml
@@ -203,7 +203,7 @@
     <tc:section id="crlf" label="CRLF in textarea">
       <p>
         CRLF in textarea will be converted to LF automatically to avoid inconsistencies with length validation.
-        If you need the old behaviour, set <code>&lt;decode-line-feed>false&lt;/decode-line-feed></code>
+        If you need the old behavior, set <code>&lt;decode-line-feed>false&lt;/decode-line-feed></code>
         in the <code>tobago-config.xml</code>.
       </p>
     </tc:section>


[myfaces-tobago] 01/03: docs/typo

Posted by lo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

lofwyr pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/myfaces-tobago.git

commit 230b47ffd58fd4134c01988b2cc34750fd423300
Author: Udo Schnurpfeil <lo...@apache.org>
AuthorDate: Wed Sep 18 15:51:13 2019 +0200

    docs/typo
---
 .../internal/renderkit/renderer/TobagoClientBehaviorRenderer.java     | 4 ++--
 .../tobago/internal/taglib/component/SuggestTagDeclaration.java       | 2 +-
 .../myfaces/tobago/internal/taglib/declaration/HasPlaceholder.java    | 4 ----
 3 files changed, 3 insertions(+), 7 deletions(-)

diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TobagoClientBehaviorRenderer.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TobagoClientBehaviorRenderer.java
index ff36e12..ac2933c 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TobagoClientBehaviorRenderer.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TobagoClientBehaviorRenderer.java
@@ -64,7 +64,7 @@ public class TobagoClientBehaviorRenderer extends javax.faces.render.ClientBehav
     final UIComponent uiComponent = behaviorContext.getComponent();
     final ClientBehaviors eventName = ClientBehaviors.valueOf(behaviorContext.getEventName());
 
-    //// TBD: is this nice? May be implemented with a JSF behaviour?
+    //// TBD: is this nice? May be implemented with a JSF behavior?
     Collapse collapse = createCollapsible(facesContext, uiComponent);
 
     String executeIds = null;
@@ -199,7 +199,7 @@ public class TobagoClientBehaviorRenderer extends javax.faces.render.ClientBehav
    */
   @Deprecated
   public static Collapse createCollapsible(final FacesContext facesContext, final UIComponent component) {
-    //// TBD: is this nice? May be implemented with a JSF behaviour?
+    //// TBD: is this nice? May be implemented with a JSF behavior?
     //// BEGIN
 
     // XXX too complicated
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SuggestTagDeclaration.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SuggestTagDeclaration.java
index 14821b9..439576e 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SuggestTagDeclaration.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SuggestTagDeclaration.java
@@ -147,7 +147,7 @@ public interface SuggestTagDeclaration extends HasIdBindingAndRendered {
   /**
    * TODO: not implemented yet
    * <p>
-   * Should the list be updated while typing (via AJAX). This is the default behaviour.
+   * Should the list be updated while typing (via AJAX). This is the default behavior.
    * If you set this value to <code>false</code>, please set the <code>minimumCharacters="0"</code>.
    * </p>
    */
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasPlaceholder.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasPlaceholder.java
index ee896cf..41e03de 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasPlaceholder.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasPlaceholder.java
@@ -27,10 +27,6 @@ public interface HasPlaceholder {
   /**
    * <p>
    * Displays a short text in the input field, that describes the meaning of this field.
-   * This is part of HTML 5, the theme should emulate the behaviour, when the browser doesn't support it.
-   * </p>
-   * <p>
-   * The text will not be displayed, when the input field is readonly or disabled.
    * </p>
    * @param placeholder The text to display
    */


[myfaces-tobago] 02/03: Introducing instead of data-tobago-command attribute. Renaming command attribute "transition" to NOT "decoupled". Tests: call events with .dispatchEvent(new Event(..., {bubbles: true}));

Posted by lo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

lofwyr pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/myfaces-tobago.git

commit 25f49b4d37a58bb3fa0a8bc02622fdce74564658
Author: Udo Schnurpfeil <lo...@apache.org>
AuthorDate: Thu Sep 19 11:14:47 2019 +0200

    Introducing <tobago-behavior> instead of data-tobago-command attribute.
    Renaming command attribute "transition" to NOT "decoupled".
    Tests: call events with .dispatchEvent(new Event(..., {bubbles: true}));
    
    issue: TOBAGO-1633: TS refactoring
---
 .../renderkit/renderer/CommandRendererBase.java    |   7 +-
 .../renderer/DecodingCommandRendererBase.java      |   3 +-
 .../renderer/DecodingInputRendererBase.java        |   3 +-
 .../internal/renderkit/renderer/FileRenderer.java  |   7 +-
 .../internal/renderkit/renderer/InRenderer.java    |   5 +-
 .../internal/renderkit/renderer/PageRenderer.java  |   4 +-
 .../internal/renderkit/renderer/PanelRenderer.java |   6 +-
 .../renderkit/renderer/ProgressRenderer.java       |   4 +-
 .../renderer/SelectBooleanCheckboxRenderer.java    |   9 +-
 .../renderer/SelectManyCheckboxRenderer.java       |   5 +-
 .../renderer/SelectManyListboxRenderer.java        |   7 +-
 .../renderkit/renderer/SelectManyRendererBase.java |   3 +-
 .../renderer/SelectManyShuttleRenderer.java        |   6 +-
 .../renderer/SelectOneChoiceRenderer.java          |   7 +-
 .../renderer/SelectOneListboxRenderer.java         |   7 +-
 .../renderkit/renderer/SelectOneRadioRenderer.java |   7 +-
 .../renderkit/renderer/SelectOneRendererBase.java  |   3 +-
 .../internal/renderkit/renderer/SheetRenderer.java |  38 +--
 .../internal/renderkit/renderer/StarsRenderer.java |   5 +-
 .../renderkit/renderer/TabGroupRenderer.java       |  20 +-
 .../renderkit/renderer/TextareaRenderer.java       |   4 +-
 .../renderkit/renderer/TreeSelectRenderer.java     |   6 +-
 .../myfaces/tobago/internal/util/RenderUtils.java  |  12 +
 .../myfaces/tobago/renderkit/RendererBase.java     | 175 ++++++++++
 .../tobago/renderkit/html/CustomAttributes.java    |  16 +-
 .../tobago/renderkit/html/DataAttributes.java      |  11 -
 .../tobago/renderkit/html/HtmlElements.java        |   1 +
 .../tobago/webapp/TobagoResponseWriter.java        |  13 +-
 .../tobago/example/demo/TextareaController.java    |  20 ++
 .../20-component/010-input/10-in/In.test.js        |   2 +-
 .../content/20-component/010-input/10-in/In.xhtml  |   2 +
 .../010-input/20-suggest/Suggest.test.js           |  12 +-
 .../010-input/30-textarea/Textarea.xhtml           |  13 +-
 .../20-component/010-input/40-date/Date.test.js    |  18 +-
 .../010-input/50-input-group/Group.test.js         |  22 +-
 .../10-selectBooleanCheckbox/Checkbox.test.js      |  12 +-
 .../15-selectBooleanToggle/Toggle.test.js          |  12 +-
 .../030-select/20-selectOneChoice/Dropdown.test.js |   8 +-
 .../030-select/30-selectOneRadio/Radio.test.js     |   8 +-
 .../030-select/40-selectOneListbox/Listbox.test.js |   8 +-
 .../50-selectManyCheckbox/Multi_Checkbox.test.js   |  16 +-
 .../content/20-component/060-popup/Popup.test.js   |  36 +--
 .../content/20-component/070-tab/Tab_Group.test.js |   6 +-
 .../080-sheet/10-sort/Sheet_Sorting.test.js        | 108 +++----
 .../080-sheet/30-event/Sheet_Event.test.js         |  38 +--
 .../080-sheet/70-tree/Sheet_Tree.test.js           |   2 +-
 .../090-tree/01-select/Tree_Select.test.js         |  46 +--
 .../06-validation/00/Content_Validation.test.js    |  26 +-
 .../30-concept/06-validation/01/JSR_303.test.js    |  10 +-
 .../08-form/10-required/Required.test.js           |  14 +-
 .../30-concept/08-form/20-ajax/Ajax.test.js        |  22 +-
 .../webapp/content/30-concept/08-form/Form.test.js |   4 +-
 .../30-concept/51-for-each/For_Each.test.js        |   6 +-
 .../00-collapsible-box/Collapsible_Box.test.js     |  50 +--
 .../10-collapsible-popup/Collapsible_Popup.test.js |  34 +-
 .../20-collapsible-panel/Collapsible_Panel.test.js |  40 +--
 .../Collapsible_Section.test.js                    |  40 +--
 .../content/30-concept/75-resize/Resize.xhtml      |  17 +-
 .../15-suggest-method/Suggest_Method.test.js       |   4 +-
 .../1020-suggest-quotMark/Suggest_QuotMark.test.js |   2 +-
 .../webapp/content/40-test/1040-date/Date.test.js  |   2 +-
 .../Date_TobagoConverter.test.js                   |   2 +-
 .../4050-ajax-dropdown/Ajax_Dropdown.test.js       |   4 +-
 .../40-test/4000-button-link/Button_Link.test.js   |   6 +-
 .../40000-style/100-headings/Headings.test.js      |   2 +-
 .../4600-gridLayout/90-style-tag/Style_Tag.test.js |   2 +-
 .../content/40-test/4950-severity/Severity.test.js |   2 +-
 .../20-ajax-execute/Ajax_Execute.test.js           |   6 +-
 .../Ajax_Special_Character.test.js                 |   2 +-
 .../content/40-test/6000-event/Event.test.js       |   2 +-
 .../content/40-test/6500-behavior/Behavior.test.js |  16 +-
 .../src/main/npm/ts/tobago-calendar.ts             |   6 +-
 .../src/main/npm/ts/tobago-command.test.ts         |  40 ---
 .../src/main/npm/ts/tobago-command.ts              | 356 +++++++++------------
 .../src/main/npm/ts/tobago-core.ts                 |   6 +-
 .../src/main/npm/ts/tobago-popup.ts                |  20 +-
 .../src/main/npm/ts/tobago-scroll.ts               |   6 +-
 .../src/main/npm/ts/tobago-sheet.ts                |   6 +-
 .../src/main/npm/ts/tobago-tab.ts                  |  12 +-
 79 files changed, 833 insertions(+), 717 deletions(-)

diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/CommandRendererBase.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/CommandRendererBase.java
index 5acd280..2e6b5bc 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/CommandRendererBase.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/CommandRendererBase.java
@@ -32,7 +32,6 @@ import org.apache.myfaces.tobago.internal.component.AbstractUISeparator;
 import org.apache.myfaces.tobago.internal.component.AbstractUIStyle;
 import org.apache.myfaces.tobago.internal.util.AccessKeyLogger;
 import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
-import org.apache.myfaces.tobago.internal.util.JsonUtils;
 import org.apache.myfaces.tobago.internal.util.RenderUtils;
 import org.apache.myfaces.tobago.renderkit.LabelWithAccessKey;
 import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
@@ -95,8 +94,6 @@ public abstract class CommandRendererBase extends DecodingCommandRendererBase {
         command.setOmit(true);
       }
 
-      writer.writeCommandMapAttribute(JsonUtils.encode(RenderUtils.getBehaviorCommands(facesContext, command)));
-
       if (label.getAccessKey() != null) {
         writer.writeAttribute(HtmlAttributes.ACCESSKEY, Character.toString(label.getAccessKey()), false);
         AccessKeyLogger.addAccessKey(facesContext, label.getAccessKey(), clientId);
@@ -136,6 +133,10 @@ public abstract class CommandRendererBase extends DecodingCommandRendererBase {
       }
     }
 
+    if (!disabled) {
+      encodeBehavior(writer, facesContext, command);
+    }
+
     final String image = ComponentUtils.getStringAttribute(command, Attributes.image);
     HtmlRendererUtils.encodeIconOrImage(writer, image);
 
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/DecodingCommandRendererBase.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/DecodingCommandRendererBase.java
index 2c3716c..f5e9144 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/DecodingCommandRendererBase.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/DecodingCommandRendererBase.java
@@ -19,7 +19,6 @@
 
 package org.apache.myfaces.tobago.internal.renderkit.renderer;
 
-import org.apache.myfaces.tobago.internal.util.RenderUtils;
 import org.apache.myfaces.tobago.renderkit.RendererBase;
 import org.apache.myfaces.tobago.util.ComponentUtils;
 import org.slf4j.Logger;
@@ -53,7 +52,7 @@ public abstract class DecodingCommandRendererBase extends RendererBase {
       commandActivated(component);
     }
 
-    RenderUtils.decodeClientBehaviors(facesContext, component);
+    decodeClientBehaviors(facesContext, component);
 
   }
 
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/DecodingInputRendererBase.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/DecodingInputRendererBase.java
index 8542a3f..c1e61a7 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/DecodingInputRendererBase.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/DecodingInputRendererBase.java
@@ -20,7 +20,6 @@
 package org.apache.myfaces.tobago.internal.renderkit.renderer;
 
 import org.apache.myfaces.tobago.component.Attributes;
-import org.apache.myfaces.tobago.internal.util.RenderUtils;
 import org.apache.myfaces.tobago.internal.util.StringUtils;
 import org.apache.myfaces.tobago.renderkit.RendererBase;
 import org.apache.myfaces.tobago.util.ComponentUtils;
@@ -61,7 +60,7 @@ public abstract class DecodingInputRendererBase extends RendererBase {
       setSubmittedValue(facesContext, (EditableValueHolder) component, newValue);
     }
 
-    RenderUtils.decodeClientBehaviors(facesContext, component);
+    decodeClientBehaviors(facesContext, component);
   }
 
   protected void setSubmittedValue(
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/FileRenderer.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/FileRenderer.java
index e29695e..2ae1a24 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/FileRenderer.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/FileRenderer.java
@@ -23,9 +23,7 @@ import org.apache.myfaces.tobago.context.TobagoContext;
 import org.apache.myfaces.tobago.internal.component.AbstractUIFile;
 import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
 import org.apache.myfaces.tobago.internal.util.HttpPartWrapper;
-import org.apache.myfaces.tobago.internal.util.JsonUtils;
 import org.apache.myfaces.tobago.internal.util.PartUtils;
-import org.apache.myfaces.tobago.internal.util.RenderUtils;
 import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
 import org.apache.myfaces.tobago.renderkit.css.TobagoClass;
 import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
@@ -109,7 +107,7 @@ public class FileRenderer extends MessageLayoutRendererBase implements Component
       LOG.warn("Unsupported request type: " + request.getClass().getName());
     }
 
-    RenderUtils.decodeClientBehaviors(facesContext, component);
+    decodeClientBehaviors(facesContext, component);
   }
 
   @Override
@@ -164,9 +162,10 @@ public class FileRenderer extends MessageLayoutRendererBase implements Component
     if (title != null) {
       writer.writeAttribute(HtmlAttributes.TITLE, title, true);
     }
-    writer.writeCommandMapAttribute(JsonUtils.encode(RenderUtils.getBehaviorCommands(facesContext, file)));
     writer.endElement(HtmlElements.INPUT);
 
+    encodeBehavior(writer, facesContext, file);
+
     writer.startElement(HtmlElements.LABEL);
     writer.writeClassAttribute(
         BootstrapClass.CUSTOM_FILE_LABEL,
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/InRenderer.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/InRenderer.java
index 55a48e5..ab26bbc 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/InRenderer.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/InRenderer.java
@@ -29,7 +29,6 @@ import org.apache.myfaces.tobago.internal.component.AbstractUIOut;
 import org.apache.myfaces.tobago.internal.component.AbstractUISelectOneChoice;
 import org.apache.myfaces.tobago.internal.util.AccessKeyLogger;
 import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
-import org.apache.myfaces.tobago.internal.util.JsonUtils;
 import org.apache.myfaces.tobago.internal.util.RenderUtils;
 import org.apache.myfaces.tobago.internal.util.StringUtils;
 import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
@@ -149,10 +148,10 @@ public class InRenderer extends MessageLayoutRendererBase {
     HtmlRendererUtils.renderFocus(clientId, input.isFocus(), ComponentUtils.isError(input), facesContext, writer);
     writeAdditionalAttributes(facesContext, writer, input);
 
-    writer.writeCommandMapAttribute(JsonUtils.encode(RenderUtils.getBehaviorCommands(facesContext, input)));
-
     writer.endElement(HtmlElements.INPUT);
 
+    encodeBehavior(writer, facesContext, input);
+
     encodeGroupAddon(facesContext, writer, after, true);
 
     if (after != null || before != null) {
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/PageRenderer.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/PageRenderer.java
index ba1b9d0..bbb39aa 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/PageRenderer.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/PageRenderer.java
@@ -36,8 +36,6 @@ import org.apache.myfaces.tobago.internal.component.AbstractUIStyle;
 import org.apache.myfaces.tobago.internal.util.AccessKeyLogger;
 import org.apache.myfaces.tobago.internal.util.CookieUtils;
 import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
-import org.apache.myfaces.tobago.internal.util.JsonUtils;
-import org.apache.myfaces.tobago.internal.util.RenderUtils;
 import org.apache.myfaces.tobago.internal.util.ResponseUtils;
 import org.apache.myfaces.tobago.internal.util.StringUtils;
 import org.apache.myfaces.tobago.portlet.PortletUtils;
@@ -247,7 +245,7 @@ public class PageRenderer extends RendererBase {
     writer.writeIdAttribute(clientId);
     HtmlRendererUtils.writeDataAttributes(facesContext, writer, page);
 
-    writer.writeCommandMapAttribute(JsonUtils.encode(RenderUtils.getBehaviorCommands(facesContext, page)));
+    encodeBehavior(writer, facesContext, page);
 
     writer.startElement(HtmlElements.FORM);
     writer.writeClassAttribute(spread);
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/PanelRenderer.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/PanelRenderer.java
index e20b004..71f3f7d 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/PanelRenderer.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/PanelRenderer.java
@@ -23,8 +23,6 @@ import org.apache.myfaces.tobago.context.Markup;
 import org.apache.myfaces.tobago.internal.component.AbstractUIPanel;
 import org.apache.myfaces.tobago.internal.component.AbstractUIReload;
 import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
-import org.apache.myfaces.tobago.internal.util.JsonUtils;
-import org.apache.myfaces.tobago.internal.util.RenderUtils;
 import org.apache.myfaces.tobago.model.CollapseMode;
 import org.apache.myfaces.tobago.renderkit.css.TobagoClass;
 import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
@@ -68,11 +66,11 @@ public class PanelRenderer extends PanelRendererBase {
       writer.writeAttribute(DataAttributes.RELOAD, reload.getFrequency());
     }
 
-    writer.writeCommandMapAttribute(JsonUtils.encode(RenderUtils.getBehaviorCommands(facesContext, panel)));
-
     if (panel.getCollapsedMode() != CollapseMode.none) {
       encodeHidden(writer, clientId, collapsed);
     }
+
+    encodeBehavior(writer, facesContext, panel);
   }
 
   @Override
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ProgressRenderer.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ProgressRenderer.java
index 470a1a7..cd53ee8 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ProgressRenderer.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ProgressRenderer.java
@@ -25,8 +25,6 @@ import org.apache.myfaces.tobago.context.Markup;
 import org.apache.myfaces.tobago.internal.component.AbstractUIProgress;
 import org.apache.myfaces.tobago.internal.component.AbstractUIStyle;
 import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
-import org.apache.myfaces.tobago.internal.util.JsonUtils;
-import org.apache.myfaces.tobago.internal.util.RenderUtils;
 import org.apache.myfaces.tobago.internal.util.StyleRenderUtils;
 import org.apache.myfaces.tobago.layout.Measure;
 import org.apache.myfaces.tobago.renderkit.RendererBase;
@@ -79,7 +77,7 @@ public class ProgressRenderer extends RendererBase {
     style.setWidth(new Measure(percent * 100, Measure.Unit.PERCENT));
     progress.getChildren().add(style);
 
-    writer.writeCommandMapAttribute(JsonUtils.encode(RenderUtils.getBehaviorCommands(facesContext, progress)));
+    encodeBehavior(writer, facesContext, progress);
   }
 
   @Override
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectBooleanCheckboxRenderer.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectBooleanCheckboxRenderer.java
index 7f542ff..8d2dd4c 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectBooleanCheckboxRenderer.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectBooleanCheckboxRenderer.java
@@ -23,8 +23,6 @@ import org.apache.myfaces.tobago.context.Markup;
 import org.apache.myfaces.tobago.internal.component.AbstractUISelectBoolean;
 import org.apache.myfaces.tobago.internal.util.AccessKeyLogger;
 import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
-import org.apache.myfaces.tobago.internal.util.JsonUtils;
-import org.apache.myfaces.tobago.internal.util.RenderUtils;
 import org.apache.myfaces.tobago.renderkit.LabelWithAccessKey;
 import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
 import org.apache.myfaces.tobago.renderkit.css.CssItem;
@@ -65,7 +63,7 @@ public class SelectBooleanCheckboxRenderer extends MessageLayoutRendererBase {
 
     input.setSubmittedValue("true".equals(newValue) ? "true" : "false");
 
-    RenderUtils.decodeClientBehaviors(facesContext, input);
+    decodeClientBehaviors(facesContext, input);
   }
 
   @Override
@@ -120,7 +118,6 @@ public class SelectBooleanCheckboxRenderer extends MessageLayoutRendererBase {
     writer.writeAttribute(HtmlAttributes.REQUIRED, select.isRequired());
     HtmlRendererUtils.renderFocus(clientId, select.isFocus(), ComponentUtils.isError(select), facesContext, writer);
     writer.writeAttribute(HtmlAttributes.TABINDEX, select.getTabIndex());
-    writer.writeCommandMapAttribute(JsonUtils.encode(RenderUtils.getBehaviorCommands(facesContext, select)));
     writer.endElement(HtmlElements.INPUT);
 
     writer.startElement(HtmlElements.I);
@@ -139,8 +136,12 @@ public class SelectBooleanCheckboxRenderer extends MessageLayoutRendererBase {
   @Override
   protected void encodeEndField(final FacesContext facesContext, final UIComponent component) throws IOException {
     final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    final AbstractUISelectBoolean select = (AbstractUISelectBoolean) component;
+
     writer.endElement(HtmlElements.LABEL);
     writer.endElement(HtmlElements.DIV);
+
+    encodeBehavior(writer, facesContext, select);
   }
 
   protected CssItem[] getOuterCssItems(final FacesContext facesContext, final AbstractUISelectBoolean select) {
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectManyCheckboxRenderer.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectManyCheckboxRenderer.java
index 0fd47dc..ec960f3 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectManyCheckboxRenderer.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectManyCheckboxRenderer.java
@@ -24,8 +24,6 @@ import org.apache.myfaces.tobago.internal.component.AbstractUISelectManyCheckbox
 import org.apache.myfaces.tobago.internal.component.AbstractUISelectReference;
 import org.apache.myfaces.tobago.internal.util.ArrayUtils;
 import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
-import org.apache.myfaces.tobago.internal.util.JsonUtils;
-import org.apache.myfaces.tobago.internal.util.RenderUtils;
 import org.apache.myfaces.tobago.internal.util.SelectItemUtils;
 import org.apache.myfaces.tobago.internal.util.StringUtils;
 import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
@@ -115,9 +113,10 @@ public class SelectManyCheckboxRenderer extends SelectManyRendererBase {
           first = false;
         }
         writer.writeAttribute(HtmlAttributes.TABINDEX, select.getTabIndex());
-        writer.writeCommandMapAttribute(JsonUtils.encode(RenderUtils.getBehaviorCommands(facesContext, select)));
         writer.endElement(HtmlElements.INPUT);
 
+        encodeBehavior(writer, facesContext, select);
+
         writer.startElement(HtmlElements.I);
         writer.writeClassAttribute(TobagoClass.INPUT_PSEUDO);
         writer.endElement(HtmlElements.I);
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectManyListboxRenderer.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectManyListboxRenderer.java
index 78abbd5..70f4e89 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectManyListboxRenderer.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectManyListboxRenderer.java
@@ -22,8 +22,6 @@ package org.apache.myfaces.tobago.internal.renderkit.renderer;
 import org.apache.myfaces.tobago.context.Markup;
 import org.apache.myfaces.tobago.internal.component.AbstractUISelectManyListbox;
 import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
-import org.apache.myfaces.tobago.internal.util.JsonUtils;
-import org.apache.myfaces.tobago.internal.util.RenderUtils;
 import org.apache.myfaces.tobago.internal.util.SelectItemUtils;
 import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
 import org.apache.myfaces.tobago.renderkit.css.TobagoClass;
@@ -80,7 +78,6 @@ public class SelectManyListboxRenderer extends SelectManyRendererBase {
     writer.writeAttribute(HtmlAttributes.MULTIPLE, true);
     writer.writeAttribute(HtmlAttributes.SIZE, size);
     writer.writeAttribute(HtmlAttributes.TITLE, title, true);
-    writer.writeCommandMapAttribute(JsonUtils.encode(RenderUtils.getBehaviorCommands(facesContext, select)));
     final Object[] values = select.getSelectedValues();
     final String[] submittedValues = getSubmittedValues(select);
 
@@ -91,7 +88,11 @@ public class SelectManyListboxRenderer extends SelectManyRendererBase {
   @Override
   public void encodeEndField(final FacesContext facesContext, final UIComponent component) throws IOException {
     final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    final AbstractUISelectManyListbox select = (AbstractUISelectManyListbox) component;
+
     writer.endElement(HtmlElements.SELECT);
+
+    encodeBehavior(writer, facesContext, select);
   }
 
   @Override
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectManyRendererBase.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectManyRendererBase.java
index 7da4c41..6286208 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectManyRendererBase.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectManyRendererBase.java
@@ -21,7 +21,6 @@ package org.apache.myfaces.tobago.internal.renderkit.renderer;
 
 import org.apache.myfaces.tobago.internal.component.AbstractUISelectManyBase;
 import org.apache.myfaces.tobago.internal.util.ArrayUtils;
-import org.apache.myfaces.tobago.internal.util.RenderUtils;
 import org.apache.myfaces.tobago.util.ComponentUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -86,7 +85,7 @@ public abstract class SelectManyRendererBase extends MessageLayoutRendererBase {
     }
     select.setSubmittedValue(newValues);
 
-    RenderUtils.decodeClientBehaviors(facesContext, select);
+    decodeClientBehaviors(facesContext, select);
   }
 
   public String[] getSubmittedValues(final UIInput input) {
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectManyShuttleRenderer.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectManyShuttleRenderer.java
index 786ea1e..563a070 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectManyShuttleRenderer.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectManyShuttleRenderer.java
@@ -22,8 +22,6 @@ package org.apache.myfaces.tobago.internal.renderkit.renderer;
 import org.apache.myfaces.tobago.context.Markup;
 import org.apache.myfaces.tobago.internal.component.AbstractUISelectManyShuttle;
 import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
-import org.apache.myfaces.tobago.internal.util.JsonUtils;
-import org.apache.myfaces.tobago.internal.util.RenderUtils;
 import org.apache.myfaces.tobago.internal.util.SelectItemUtils;
 import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
 import org.apache.myfaces.tobago.renderkit.css.Icons;
@@ -142,7 +140,6 @@ public class SelectManyShuttleRenderer extends SelectManyRendererBase {
     writer.writeNameAttribute(clientId);
     writer.writeAttribute(HtmlAttributes.MULTIPLE, true);
     writer.writeAttribute(HtmlAttributes.REQUIRED, select.isRequired());
-    writer.writeCommandMapAttribute(JsonUtils.encode(RenderUtils.getBehaviorCommands(facesContext, select)));
     HtmlRendererUtils.renderSelectItems(select, TobagoClass.SELECT_MANY_SHUTTLE__OPTION, items, values, submittedValues,
         writer, facesContext);
     writer.endElement(HtmlElements.SELECT);
@@ -151,7 +148,10 @@ public class SelectManyShuttleRenderer extends SelectManyRendererBase {
   @Override
   public void encodeEndField(final FacesContext facesContext, final UIComponent component) throws IOException {
     final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    final AbstractUISelectManyShuttle select = (AbstractUISelectManyShuttle) component;
     writer.endElement(HtmlElements.DIV);
+
+    encodeBehavior(writer, facesContext, select);
   }
 
   private void createButton(
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectOneChoiceRenderer.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectOneChoiceRenderer.java
index 1589fc6..779a4a5 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectOneChoiceRenderer.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectOneChoiceRenderer.java
@@ -22,8 +22,6 @@ package org.apache.myfaces.tobago.internal.renderkit.renderer;
 import org.apache.myfaces.tobago.context.Markup;
 import org.apache.myfaces.tobago.internal.component.AbstractUISelectOneChoice;
 import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
-import org.apache.myfaces.tobago.internal.util.JsonUtils;
-import org.apache.myfaces.tobago.internal.util.RenderUtils;
 import org.apache.myfaces.tobago.internal.util.SelectItemUtils;
 import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
 import org.apache.myfaces.tobago.renderkit.css.CssItem;
@@ -73,7 +71,6 @@ public class SelectOneChoiceRenderer extends SelectOneRendererBase {
     if (title != null) {
       writer.writeAttribute(HtmlAttributes.TITLE, title, true);
     }
-    writer.writeCommandMapAttribute(JsonUtils.encode(RenderUtils.getBehaviorCommands(facesContext, select)));
     HtmlRendererUtils.renderFocus(clientId, select.isFocus(), ComponentUtils.isError(select), facesContext, writer);
 
     HtmlRendererUtils.renderSelectItems(select, TobagoClass.SELECT_ONE_CHOICE__OPTION, items, select.getValue(),
@@ -83,7 +80,11 @@ public class SelectOneChoiceRenderer extends SelectOneRendererBase {
   @Override
   protected void encodeEndField(final FacesContext facesContext, final UIComponent component) throws IOException {
     final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    final AbstractUISelectOneChoice select = (AbstractUISelectOneChoice) component;
+
     writer.endElement(HtmlElements.SELECT);
+
+    encodeBehavior(writer, facesContext, select);
   }
 
   @Override
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectOneListboxRenderer.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectOneListboxRenderer.java
index bf4fd08..0773f02 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectOneListboxRenderer.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectOneListboxRenderer.java
@@ -22,8 +22,6 @@ package org.apache.myfaces.tobago.internal.renderkit.renderer;
 import org.apache.myfaces.tobago.context.Markup;
 import org.apache.myfaces.tobago.internal.component.AbstractUISelectOneListbox;
 import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
-import org.apache.myfaces.tobago.internal.util.JsonUtils;
-import org.apache.myfaces.tobago.internal.util.RenderUtils;
 import org.apache.myfaces.tobago.internal.util.SelectItemUtils;
 import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
 import org.apache.myfaces.tobago.renderkit.css.TobagoClass;
@@ -79,7 +77,6 @@ public class SelectOneListboxRenderer extends SelectOneRendererBase {
     final String title = HtmlRendererUtils.getTitleFromTipAndMessages(facesContext, select);
     writer.writeAttribute(HtmlAttributes.TITLE, title, true);
     writer.writeAttribute(HtmlAttributes.SIZE, size);
-    writer.writeCommandMapAttribute(JsonUtils.encode(RenderUtils.getBehaviorCommands(facesContext, select)));
     HtmlRendererUtils.renderSelectItems(select, TobagoClass.SELECT_ONE_LISTBOX__OPTION, items, select.getValue(),
         (String) select.getSubmittedValue(), writer, facesContext);
   }
@@ -87,7 +84,11 @@ public class SelectOneListboxRenderer extends SelectOneRendererBase {
   @Override
   protected void encodeEndField(final FacesContext facesContext, final UIComponent component) throws IOException {
     final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    final AbstractUISelectOneListbox select = (AbstractUISelectOneListbox) component;
+
     writer.endElement(HtmlElements.SELECT);
+
+    encodeBehavior(writer, facesContext, select);
   }
 
   @Override
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectOneRadioRenderer.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectOneRadioRenderer.java
index 330f417..9439269 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectOneRadioRenderer.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectOneRadioRenderer.java
@@ -24,9 +24,7 @@ import org.apache.myfaces.tobago.internal.component.AbstractUISelectOneRadio;
 import org.apache.myfaces.tobago.internal.component.AbstractUISelectReference;
 import org.apache.myfaces.tobago.internal.util.ArrayUtils;
 import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
-import org.apache.myfaces.tobago.internal.util.JsonUtils;
 import org.apache.myfaces.tobago.internal.util.ObjectUtils;
-import org.apache.myfaces.tobago.internal.util.RenderUtils;
 import org.apache.myfaces.tobago.internal.util.SelectItemUtils;
 import org.apache.myfaces.tobago.internal.util.StringUtils;
 import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
@@ -117,7 +115,6 @@ public class SelectOneRadioRenderer extends SelectOneRendererBase {
           first = false;
         }
         writer.writeAttribute(HtmlAttributes.TABINDEX, select.getTabIndex());
-        writer.writeCommandMapAttribute(JsonUtils.encode(RenderUtils.getBehaviorCommands(facesContext, select)));
         writer.endElement(HtmlElements.INPUT);
 
         writer.startElement(HtmlElements.I);
@@ -159,7 +156,11 @@ public class SelectOneRadioRenderer extends SelectOneRendererBase {
   @Override
   protected void encodeEndField(final FacesContext facesContext, final UIComponent component) throws IOException {
     final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    final AbstractUISelectOneRadio select = (AbstractUISelectOneRadio) component;
+
     writer.endElement(HtmlElements.DIV);
+
+    encodeBehavior(writer, facesContext, select);
   }
 
   protected boolean renderOuterItem() {
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectOneRendererBase.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectOneRendererBase.java
index f0ef180..a77b1ee 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectOneRendererBase.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectOneRendererBase.java
@@ -20,7 +20,6 @@
 package org.apache.myfaces.tobago.internal.renderkit.renderer;
 
 import org.apache.myfaces.tobago.internal.component.AbstractUISelectOneBase;
-import org.apache.myfaces.tobago.internal.util.RenderUtils;
 import org.apache.myfaces.tobago.util.ComponentUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -49,6 +48,6 @@ public abstract class SelectOneRendererBase extends MessageLayoutRendererBase {
     }
     select.setSubmittedValue(newValue);
 
-    RenderUtils.decodeClientBehaviors(facesContext, select);
+    decodeClientBehaviors(facesContext, select);
   }
 }
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SheetRenderer.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SheetRenderer.java
index 2f973cd..af165c7 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SheetRenderer.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SheetRenderer.java
@@ -56,7 +56,6 @@ import org.apache.myfaces.tobago.model.TreePath;
 import org.apache.myfaces.tobago.renderkit.RendererBase;
 import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
 import org.apache.myfaces.tobago.renderkit.css.CssItem;
-import org.apache.myfaces.tobago.renderkit.css.CustomClass;
 import org.apache.myfaces.tobago.renderkit.css.Icons;
 import org.apache.myfaces.tobago.renderkit.css.TobagoClass;
 import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
@@ -274,9 +273,6 @@ public class SheetRenderer extends RendererBase {
     if (reload != null && reload.isRendered()) {
       writer.writeAttribute(DataAttributes.RELOAD, reload.getFrequency());
     }
-// todo    writer.writeCommandMapAttribute(JsonUtils.encode(RenderUtils.getBehaviorCommands(facesContext, sheet)));
-    final CommandMap commands = RenderUtils.getBehaviorCommands(facesContext, sheet);
-    writer.writeAttribute(DataAttributes.BEHAVIOR_COMMANDS, JsonUtils.encode(commands), false);
     writer.writeAttribute(DataAttributes.SELECTION_MODE, sheet.getSelectable().name(), false);
     writer.writeAttribute(DataAttributes.FIRST, Integer.toString(sheet.getFirst()), false);
 
@@ -284,6 +280,8 @@ public class SheetRenderer extends RendererBase {
     if (!autoLayout) {
       writer.writeAttribute(DataAttributes.LAYOUT, JsonUtils.encode(sheet.getColumnLayout(), "columns"), true);
     }
+
+    encodeBehavior(writer, facesContext, sheet);
   }
 
   @Override
@@ -656,28 +654,26 @@ public class SheetRenderer extends RendererBase {
         writer.writeAttribute(DataAttributes.TREE_PARENT, parentId, false);
       }
 
-      // the row client id depends from the existence of an UIRow component! TBD: is this good?
-      String rowClientId = sheet.getRowClientId();
-      CustomClass rowClass = null;
+      AbstractUIRow row = null;
       for (final UIColumn column : columns) {
         if (column.isRendered()) {
           if (column instanceof AbstractUIRow) {
-            final AbstractUIRow row = (AbstractUIRow) column;
-            writer.writeCommandMapAttribute(JsonUtils.encode(RenderUtils.getBehaviorCommands(facesContext, row)));
-            rowClientId = row.getClientId(facesContext);
-            rowClass = row.getCustomClass();
+            row = (AbstractUIRow) column;
             // todo: Markup.CLICKABLE ???
           }
         }
       }
-      writer.writeIdAttribute(rowClientId);
+      // the row client id depends from the existence of an UIRow component! TBD: is this good?
+      writer.writeIdAttribute(row != null ? row.getClientId(facesContext): sheet.getRowClientId());
       writer.writeClassAttribute(
           TobagoClass.SHEET__ROW,
           TobagoClass.SHEET__ROW.createMarkup(rowMarkup),
           selected ? BootstrapClass.TABLE_INFO : null,
-          rowClass,
+          row != null ? row.getCustomClass() : null,
           sheet.isRowVisible() ? null : BootstrapClass.D_NONE);
 
+      encodeBehavior(writer, facesContext, row);
+
       for (final AbstractUIColumnBase column : columns) {
         if (column.isRendered()) {
           if (column instanceof AbstractUIColumn || column instanceof AbstractUIColumnSelector
@@ -906,6 +902,7 @@ public class SheetRenderer extends RendererBase {
             Markup markup = Markup.NULL;
             String tip = ComponentUtils.getStringAttribute(column, Attributes.tip);
             // sorter icons should only displayed when there is only 1 column and not input
+            CommandMap behaviorCommands = null;
             if (cell.getColumnSpan() == 1 && cellComponent instanceof AbstractUIOut) {
               final boolean sortable = ComponentUtils.getBooleanAttribute(column, Attributes.sortable);
               if (sortable) {
@@ -922,8 +919,7 @@ public class SheetRenderer extends RendererBase {
                   ComponentUtils.setFacet(column, Facets.sorter, sortCommand);
                 }
                 writer.writeIdAttribute(sortCommand.getClientId(facesContext));
-                writer.writeCommandMapAttribute(
-                    JsonUtils.encode(RenderUtils.getBehaviorCommands(facesContext, sortCommand)));
+                behaviorCommands = getBehaviorCommands(facesContext, sortCommand);
                 ComponentUtils.removeFacet(column, Facets.sorter);
                 if (tip == null) {
                   tip = "";
@@ -944,9 +940,7 @@ public class SheetRenderer extends RendererBase {
                     sortTitle = ResourceUtils.getString(facesContext, "sheet.descending");
                     markup = markup.add(Markup.DESCENDING);
                   }
-                  if (sortTitle != null) {
-                    tip += " - " + sortTitle;
-                  }
+                  tip += " - " + sortTitle;
                 }
               }
             }
@@ -954,6 +948,8 @@ public class SheetRenderer extends RendererBase {
             writer.writeClassAttribute(TobagoClass.SHEET__HEADER, TobagoClass.SHEET__HEADER.createMarkup(markup));
             writer.writeAttribute(HtmlAttributes.TITLE, tip, true);
 
+            encodeBehavior(writer, behaviorCommands);
+
             if (column instanceof AbstractUIColumnSelector && selectable.isMulti()) {
               writer.startElement(HtmlElements.INPUT);
               writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.CHECKBOX);
@@ -1083,9 +1079,6 @@ public class SheetRenderer extends RendererBase {
     writer.writeClassAttribute(BootstrapClass.PAGE_LINK);
     writer.writeIdAttribute(command.getClientId(facesContext));
     writer.writeAttribute(HtmlAttributes.TITLE, tip, true);
-    if (!disabled) {
-      writer.writeCommandMapAttribute(JsonUtils.encode(RenderUtils.getBehaviorCommands(facesContext, command)));
-    }
     writer.writeAttribute(HtmlAttributes.DISABLED, disabled);
     if (icon != null) {
       writer.startElement(HtmlElements.I);
@@ -1094,6 +1087,9 @@ public class SheetRenderer extends RendererBase {
     } else {
       writer.writeText(String.valueOf(target));
     }
+    if (!disabled) {
+      encodeBehavior(writer, facesContext, command);
+    }
     data.getFacets().remove(facet);
     writer.endElement(HtmlElements.BUTTON);
     writer.endElement(HtmlElements.LI);
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/StarsRenderer.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/StarsRenderer.java
index 700a46b..7c127de 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/StarsRenderer.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/StarsRenderer.java
@@ -21,8 +21,6 @@ package org.apache.myfaces.tobago.internal.renderkit.renderer;
 
 import org.apache.myfaces.tobago.internal.component.AbstractUIStars;
 import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
-import org.apache.myfaces.tobago.internal.util.JsonUtils;
-import org.apache.myfaces.tobago.internal.util.RenderUtils;
 import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
 import org.apache.myfaces.tobago.renderkit.css.TobagoClass;
 import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
@@ -87,7 +85,6 @@ public class StarsRenderer extends MessageLayoutRendererBase {
     writer.writeAttribute(HtmlAttributes.MIN, required ? 1 : 0);
     writer.writeAttribute(HtmlAttributes.MAX, max);
     writer.writeAttribute(HtmlAttributes.VALUE, sliderValue, true);
-    writer.writeCommandMapAttribute(JsonUtils.encode(RenderUtils.getBehaviorCommands(facesContext, stars)));
     if (placeholder != null) {
       writer.writeAttribute(HtmlAttributes.PLACEHOLDER, placeholder.toString(), true);
     }
@@ -99,6 +96,8 @@ public class StarsRenderer extends MessageLayoutRendererBase {
     writer.writeAttribute(HtmlAttributes.TITLE, title, true);
     writer.endElement(HtmlElements.INPUT);
 
+    encodeBehavior(writer, facesContext, stars);
+
     writer.startElement(HtmlElements.DIV);
     writer.writeClassAttribute(TobagoClass.STARS__FOCUS_BOX);
     writer.endElement(HtmlElements.DIV);
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TabGroupRenderer.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TabGroupRenderer.java
index a37dfc3..407631d 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TabGroupRenderer.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TabGroupRenderer.java
@@ -31,11 +31,8 @@ import org.apache.myfaces.tobago.internal.component.AbstractUIEvent;
 import org.apache.myfaces.tobago.internal.component.AbstractUIPanelBase;
 import org.apache.myfaces.tobago.internal.component.AbstractUITab;
 import org.apache.myfaces.tobago.internal.component.AbstractUITabGroup;
-import org.apache.myfaces.tobago.internal.renderkit.CommandMap;
 import org.apache.myfaces.tobago.internal.util.AccessKeyLogger;
 import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
-import org.apache.myfaces.tobago.internal.util.JsonUtils;
-import org.apache.myfaces.tobago.internal.util.RenderUtils;
 import org.apache.myfaces.tobago.model.SwitchType;
 import org.apache.myfaces.tobago.renderkit.LabelWithAccessKey;
 import org.apache.myfaces.tobago.renderkit.RendererBase;
@@ -141,9 +138,7 @@ public class TabGroupRenderer extends RendererBase implements ComponentSystemEve
   public void encodeEnd(final FacesContext facesContext, final UIComponent uiComponent) throws IOException {
 
     final AbstractUITabGroup tabGroup = (AbstractUITabGroup) uiComponent;
-
     final int selectedIndex = ensureRenderedSelectedIndex(facesContext, tabGroup);
-
     final String clientId = tabGroup.getClientId(facesContext);
     final String hiddenId = clientId + TabGroupRenderer.INDEX_POSTFIX;
     final SwitchType switchType = tabGroup.getSwitchType();
@@ -160,6 +155,8 @@ public class TabGroupRenderer extends RendererBase implements ComponentSystemEve
     HtmlRendererUtils.writeDataAttributes(facesContext, writer, tabGroup);
     writer.writeAttribute(CustomAttributes.SWITCH_TYPE, switchType.name(), false);
 
+    encodeBehavior(writer, facesContext, tabGroup);
+
     writer.startElement(HtmlElements.INPUT);
     writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.HIDDEN);
     writer.writeAttribute(HtmlAttributes.VALUE, selectedIndex);
@@ -227,7 +224,6 @@ public class TabGroupRenderer extends RendererBase implements ComponentSystemEve
         BootstrapClass.NAV_TABS,
         BootstrapClass.CARD_HEADER_TABS);
     writer.writeAttribute(HtmlAttributes.ROLE, HtmlRoleValues.TABLIST.toString(), false);
-    final CommandMap tabGroupMap = RenderUtils.getBehaviorCommands(facesContext, tabGroup);
 
     int index = 0;
     for (final UIComponent child : tabGroup.getChildren()) {
@@ -279,20 +275,16 @@ public class TabGroupRenderer extends RendererBase implements ComponentSystemEve
                 DataAttributes.TARGET, '#' + getTabPanelId(facesContext, tab).replaceAll(":", "\\\\:"), false);
           }
 
-          if (!disabled) {
-            final CommandMap map = RenderUtils.getBehaviorCommands(facesContext, tab);
-            CommandMap.merge(map, tabGroupMap);
-            if (false) { // TBD
-              writer.writeAttribute(DataAttributes.COMMANDS, JsonUtils.encode(map), false);
-            }
-          }
-
           if (!disabled && label.getAccessKey() != null) {
             writer.writeAttribute(HtmlAttributes.ACCESSKEY, Character.toString(label.getAccessKey()), false);
             AccessKeyLogger.addAccessKey(facesContext, label.getAccessKey(), tabId);
           }
           writer.writeAttribute(HtmlAttributes.ROLE, HtmlRoleValues.TAB.toString(), false);
 
+          if (!disabled) {
+            encodeBehavior(writer, facesContext, tab);
+          }
+
           boolean labelEmpty = true;
           final String image = tab.getImage();
           // tab.getImage() resolves to empty string if el-expression resolves to null
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TextareaRenderer.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TextareaRenderer.java
index d420837..360b7f2 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TextareaRenderer.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TextareaRenderer.java
@@ -24,7 +24,6 @@ import org.apache.myfaces.tobago.context.Markup;
 import org.apache.myfaces.tobago.internal.component.AbstractUITextarea;
 import org.apache.myfaces.tobago.internal.util.AccessKeyLogger;
 import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
-import org.apache.myfaces.tobago.internal.util.JsonUtils;
 import org.apache.myfaces.tobago.internal.util.RenderUtils;
 import org.apache.myfaces.tobago.internal.util.StringUtils;
 import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
@@ -136,8 +135,6 @@ public class TextareaRenderer extends MessageLayoutRendererBase {
       writer.writeAttribute(HtmlAttributes.PATTERN, pattern, true);
     }
 
-    writer.writeCommandMapAttribute(JsonUtils.encode(RenderUtils.getBehaviorCommands(facesContext, input)));
-
     HtmlRendererUtils.renderFocus(clientId, input.isFocus(), ComponentUtils.isError(input), facesContext, writer);
 
     final String placeholder = input.getPlaceholder();
@@ -163,6 +160,7 @@ public class TextareaRenderer extends MessageLayoutRendererBase {
     }
 
     writer.endElement(HtmlElements.TEXTAREA);
+    encodeBehavior(writer, facesContext, input);
   }
 
   @Override
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TreeSelectRenderer.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TreeSelectRenderer.java
index 1c442cc..54b7dfd 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TreeSelectRenderer.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TreeSelectRenderer.java
@@ -25,8 +25,6 @@ import org.apache.myfaces.tobago.internal.component.AbstractUITreeListbox;
 import org.apache.myfaces.tobago.internal.component.AbstractUITreeNodeBase;
 import org.apache.myfaces.tobago.internal.component.AbstractUITreeSelect;
 import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
-import org.apache.myfaces.tobago.internal.util.JsonUtils;
-import org.apache.myfaces.tobago.internal.util.RenderUtils;
 import org.apache.myfaces.tobago.internal.util.StringUtils;
 import org.apache.myfaces.tobago.model.Selectable;
 import org.apache.myfaces.tobago.renderkit.RendererBase;
@@ -132,9 +130,9 @@ public class TreeSelectRenderer extends RendererBase {
       writer.writeIdAttribute(id);
       writer.writeAttribute(HtmlAttributes.CHECKED, checked);
 
-      writer.writeCommandMapAttribute(JsonUtils.encode(RenderUtils.getBehaviorCommands(facesContext, treeSelect)));
-
       writer.endElement(HtmlElements.INPUT);
+
+      encodeBehavior(writer, facesContext, treeSelect);
     }
 
     // label
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/RenderUtils.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/RenderUtils.java
index 95d0df2..56feb91 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/RenderUtils.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/RenderUtils.java
@@ -293,6 +293,10 @@ public final class RenderUtils {
     return url;
   }
 
+  /**
+   * @deprecated since 5.0.0
+   */
+  @Deprecated
   public static CommandMap getBehaviorCommands(final FacesContext facesContext,
       final ClientBehaviorHolder clientBehaviorHolder) {
     CommandMap commandMap = null;
@@ -333,6 +337,10 @@ public final class RenderUtils {
     return commandMap;
   }
 
+  /**
+   * @deprecated since 5.0.0
+   */
+  @Deprecated
   private static ClientBehaviorContext getClientBehaviorContext(final FacesContext facesContext,
       final ClientBehaviorHolder clientBehaviorHolder, final String eventName) {
     UIComponent component = (UIComponent) clientBehaviorHolder;
@@ -348,6 +356,10 @@ public final class RenderUtils {
         .findFirst().orElse(null);
   }
 
+  /**
+   * @deprecated since 5.0.0
+   */
+  @Deprecated
   private static CommandMap getCommandMap(final FacesContext facesContext,
       final ClientBehaviorContext clientBehaviorContext, final ClientBehavior clientBehavior) {
     if (clientBehavior instanceof ClientBehaviorBase) {
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/RendererBase.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/RendererBase.java
index 08ea7e4..4e7568b 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/RendererBase.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/RendererBase.java
@@ -19,23 +19,47 @@
 
 package org.apache.myfaces.tobago.renderkit;
 
+import org.apache.myfaces.tobago.component.ClientBehaviors;
+import org.apache.myfaces.tobago.internal.behavior.EventBehavior;
+import org.apache.myfaces.tobago.internal.component.AbstractUICommand;
+import org.apache.myfaces.tobago.internal.component.AbstractUIEvent;
 import org.apache.myfaces.tobago.internal.component.AbstractUIReload;
+import org.apache.myfaces.tobago.internal.renderkit.Collapse;
+import org.apache.myfaces.tobago.internal.renderkit.Command;
+import org.apache.myfaces.tobago.internal.renderkit.CommandMap;
+import org.apache.myfaces.tobago.internal.util.RenderUtils;
 import org.apache.myfaces.tobago.internal.webapp.TobagoResponseWriterWrapper;
+import org.apache.myfaces.tobago.renderkit.html.CustomAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
 import org.apache.myfaces.tobago.util.ComponentUtils;
 import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import javax.faces.component.EditableValueHolder;
 import javax.faces.component.UIComponent;
 import javax.faces.component.ValueHolder;
+import javax.faces.component.behavior.AjaxBehavior;
+import javax.faces.component.behavior.ClientBehavior;
+import javax.faces.component.behavior.ClientBehaviorBase;
+import javax.faces.component.behavior.ClientBehaviorContext;
+import javax.faces.component.behavior.ClientBehaviorHolder;
 import javax.faces.context.FacesContext;
 import javax.faces.context.ResponseWriter;
 import javax.faces.convert.Converter;
 import javax.faces.convert.ConverterException;
+import javax.faces.render.ClientBehaviorRenderer;
 import javax.faces.render.Renderer;
 import java.io.IOException;
+import java.lang.invoke.MethodHandles;
+import java.util.List;
+import java.util.Map;
 
 public class RendererBase extends Renderer {
 
+  private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
   protected String getCurrentValue(final FacesContext facesContext, final UIComponent component) {
 
     if (component instanceof ValueHolder) {
@@ -92,4 +116,155 @@ public class RendererBase extends Renderer {
     final TobagoResponseWriter writer = getResponseWriter(facesContext);
     writer.write("{\"reload\":{\"frequency\":" + reload.getFrequency() + "}}");
   }
+
+  /**
+   * Renders the tobago-behavior tag.
+   *
+   * @since 5.0
+   */
+  protected void encodeBehavior(
+      final TobagoResponseWriter writer, final FacesContext facesContext, final ClientBehaviorHolder holder)
+      throws IOException {
+    if (holder != null) {
+      final CommandMap behaviorCommands = getBehaviorCommands(facesContext, holder);
+      encodeBehavior(writer, behaviorCommands);
+    }
+  }
+
+  /**
+   * Renders the tobago-behavior tag.
+   *
+   * @since 5.0
+   */
+  protected void encodeBehavior(
+      final TobagoResponseWriter writer, final CommandMap behaviorCommands)
+      throws IOException {
+    if (behaviorCommands != null) {
+      final Command click = behaviorCommands.getClick();
+      if (click != null) {
+        encodeBehavior(writer, ClientBehaviors.click, click);
+      }
+      final Map<ClientBehaviors, Command> other = behaviorCommands.getOther();
+      if (other != null) {
+        for (Map.Entry<ClientBehaviors, Command> entry : other.entrySet()) {
+          encodeBehavior(writer, entry.getKey(), entry.getValue());
+        }
+      }
+    }
+  }
+
+  private void encodeBehavior(
+      final TobagoResponseWriter writer, final ClientBehaviors behaviors, final Command command)
+      throws IOException {
+    writer.startElement(HtmlElements.TOBAGO_BEHAVIOR);
+    writer.writeAttribute(CustomAttributes.EVENT, behaviors.name(), false);
+    writer.writeAttribute(HtmlAttributes.ACTION, command.getAction(), false); // tbd: rename to actionId?
+    writer.writeAttribute(CustomAttributes.EXECUTE, command.getExecute(), false);
+    writer.writeAttribute(CustomAttributes.RENDER, command.getRender(), false);
+    writer.writeAttribute(CustomAttributes.OMIT, command.getOmit());
+    writer.writeAttribute(CustomAttributes.CONFIRMATION, command.getConfirmation(), true);
+    writer.writeAttribute(CustomAttributes.DECOUPLED, command.getTransition() != null ? command.getTransition() : false);
+    final Collapse collapse = command.getCollapse();
+    if (collapse != null) {
+      writer.writeAttribute(CustomAttributes.COLLAPSE_ACTION, collapse.getAction().name(), false);
+      writer.writeAttribute(CustomAttributes.COLLAPSE_TARGET, collapse.getFor(), false);
+    }
+    writer.writeAttribute(CustomAttributes.DELAY, command.getDelay());
+    writer.writeAttribute(CustomAttributes.FOCUS_ID, command.getFocus(), false);
+    writer.writeAttribute(HtmlAttributes.TARGET, command.getTarget(), true);
+
+    // todo: all the other attributes
+    writer.endElement(HtmlElements.TOBAGO_BEHAVIOR);
+  }
+
+  protected CommandMap getBehaviorCommands(final FacesContext facesContext,
+                                               final ClientBehaviorHolder clientBehaviorHolder) {
+    CommandMap commandMap = null;
+
+    for (final Map.Entry<String, List<ClientBehavior>> entry : clientBehaviorHolder.getClientBehaviors().entrySet()) {
+      final String eventName = entry.getKey();
+      final ClientBehaviorContext clientBehaviorContext
+          = getClientBehaviorContext(facesContext, clientBehaviorHolder, eventName);
+
+      for (final ClientBehavior clientBehavior : entry.getValue()) {
+        if (clientBehavior instanceof EventBehavior) {
+          final EventBehavior eventBehavior = (EventBehavior) clientBehavior;
+          final AbstractUIEvent abstractUIEvent
+              = RenderUtils.getAbstractUIEvent((UIComponent) clientBehaviorHolder, eventBehavior);
+
+          if (abstractUIEvent != null && abstractUIEvent.isRendered() && !abstractUIEvent.isDisabled()) {
+            for (List<ClientBehavior> children : abstractUIEvent.getClientBehaviors().values()) {
+              for (ClientBehavior child : children) {
+                final CommandMap childMap = getCommandMap(facesContext, clientBehaviorContext, child);
+                commandMap = CommandMap.merge(commandMap, childMap);
+              }
+            }
+          }
+        }
+
+        final CommandMap map = getCommandMap(facesContext, clientBehaviorContext, clientBehavior);
+        commandMap = CommandMap.merge(commandMap, map);
+      }
+    }
+
+    // if there is no explicit behavior (with f:ajax or tc:event), use the command properties as default.
+    if ((commandMap == null || commandMap.isEmpty()) && clientBehaviorHolder instanceof AbstractUICommand) {
+      if (commandMap == null) {
+        commandMap = new CommandMap();
+      }
+      commandMap.addCommand(ClientBehaviors.click, new Command(facesContext, (AbstractUICommand) clientBehaviorHolder));
+    }
+
+    return commandMap;
+  }
+
+  private static ClientBehaviorContext getClientBehaviorContext(final FacesContext facesContext,
+                                                                final ClientBehaviorHolder clientBehaviorHolder, final String eventName) {
+    UIComponent component = (UIComponent) clientBehaviorHolder;
+    return ClientBehaviorContext.createClientBehaviorContext(facesContext, component, eventName,
+        component.getClientId(facesContext), null);
+  }
+
+  private static CommandMap getCommandMap(final FacesContext facesContext,
+                                          final ClientBehaviorContext clientBehaviorContext, final ClientBehavior clientBehavior) {
+    if (clientBehavior instanceof ClientBehaviorBase) {
+      String type = ((ClientBehaviorBase) clientBehavior).getRendererType();
+
+      // this is to use a different renderer for Tobago components and other components.
+      if (type.equals(AjaxBehavior.BEHAVIOR_ID)) {
+        type = "org.apache.myfaces.tobago.behavior.Ajax";
+      }
+      final ClientBehaviorRenderer renderer = facesContext.getRenderKit().getClientBehaviorRenderer(type);
+      final String dummy = renderer.getScript(clientBehaviorContext, clientBehavior);
+      if (dummy != null) {
+        return CommandMap.restoreCommandMap(facesContext);
+      }
+    } else {
+      LOG.warn("Ignoring: '{}'", clientBehavior);
+    }
+    return null;
+  }
+
+  protected void decodeClientBehaviors(final FacesContext facesContext, final UIComponent component) {
+    if (component instanceof ClientBehaviorHolder) {
+      final ClientBehaviorHolder clientBehaviorHolder = (ClientBehaviorHolder) component;
+      final Map<String, List<ClientBehavior>> clientBehaviors = clientBehaviorHolder.getClientBehaviors();
+      if (clientBehaviors != null && !clientBehaviors.isEmpty()) {
+        final Map<String, String> paramMap = facesContext.getExternalContext().getRequestParameterMap();
+        final String behaviorEventName = paramMap.get("javax.faces.behavior.event");
+        if (behaviorEventName != null) {
+          final List<ClientBehavior> clientBehaviorList = clientBehaviors.get(behaviorEventName);
+          if (clientBehaviorList != null && !clientBehaviorList.isEmpty()) {
+            final String clientId = paramMap.get("javax.faces.source");
+            if (component.getClientId(facesContext).equals(clientId)) {
+              for (final ClientBehavior clientBehavior : clientBehaviorList) {
+                clientBehavior.decode(facesContext, component);
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+
 }
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/CustomAttributes.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/CustomAttributes.java
index 2e49e66..af6aade 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/CustomAttributes.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/CustomAttributes.java
@@ -21,8 +21,17 @@ package org.apache.myfaces.tobago.renderkit.html;
 
 public enum CustomAttributes implements MarkupLanguageAttributes {
 
+  COLLAPSE_ACTION("collapse-action"),
+  COLLAPSE_TARGET("collapse-target"),
+  CONFIRMATION("confirmation"),
   DATA("data"),
   DELAY("delay"),
+  EVENT("event"),
+  /**
+   * &lt;f:ajax&gt; attribute
+   */
+  EXECUTE("execute"),
+  FOCUS_ID("focus-id"),
   /**
    * The index of the tab inside the tab group.
    */
@@ -30,15 +39,20 @@ public enum CustomAttributes implements MarkupLanguageAttributes {
   LOCAL_MENU("local-menu"),
   MAX_ITEMS("max-items"),
   MIN_CHARS("min-chars"),
+  OMIT("omit"),
   ORIENTATION("orientation"),
   /**
+   * &lt;f:ajax&gt; attribute
+   */
+  RENDER("render"),
+  /**
    * The mode of the tab switch: client, reloadTab, reloadPage.
    */
   SWITCH_TYPE("switch-type"),
   TOTAL_COUNT("total-count"),
+  DECOUPLED("decoupled"),
   UPDATE("update");
 
-
   private final String value;
 
   CustomAttributes(final String value) {
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/DataAttributes.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/DataAttributes.java
index 175737f..bb8cdb6 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/DataAttributes.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/DataAttributes.java
@@ -44,17 +44,6 @@ public enum DataAttributes implements MarkupLanguageAttributes {
    */
   COLUMN_INDEX("data-tobago-column-index"),
 
-  /**
-   * Custom command attribute. Is used to mark different client side JavaScript buttons.
-   * Should only contain the command name as a keyword, for security reasons.
-   */
-  COMMAND("data-tobago-command"),
-
-  /**
-   * The list of commands attached to an element.
-   */
-  COMMANDS("data-tobago-commands"),
-
   CONTENT("data-content"),
 
   /**
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/HtmlElements.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/HtmlElements.java
index fd2dc46..5394f3c 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/HtmlElements.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/HtmlElements.java
@@ -133,6 +133,7 @@ public enum HtmlElements {
   VIDEO("video"),
   WBR("wbr", Qualifier.VOID),
 
+  TOBAGO_BEHAVIOR("tobago-behavior"),
   TOBAGO_FILE("tobago-file"),
   TOBAGO_IN("tobago-in"),
   TOBAGO_PANEL("tobago-panel"),
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/webapp/TobagoResponseWriter.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/webapp/TobagoResponseWriter.java
index c00b4a4..9e9bfe5 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/webapp/TobagoResponseWriter.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/webapp/TobagoResponseWriter.java
@@ -19,11 +19,11 @@
 
 package org.apache.myfaces.tobago.webapp;
 
+import org.apache.myfaces.tobago.internal.util.Deprecation;
 import org.apache.myfaces.tobago.renderkit.css.CssItem;
 import org.apache.myfaces.tobago.renderkit.css.FontAwesomeIconEncoder;
 import org.apache.myfaces.tobago.renderkit.css.IconEncoder;
 import org.apache.myfaces.tobago.renderkit.css.Icons;
-import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
 import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
 import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
 import org.apache.myfaces.tobago.renderkit.html.HtmlTypes;
@@ -147,12 +147,13 @@ public abstract class TobagoResponseWriter extends ResponseWriter {
 
   /**
    * Write the command map data attribute.
+   *
+   * @deprecated since 5.0, use {@link
+   * org.apache.myfaces.tobago.renderkit.RendererBase#encodeBehavior} instead.
    */
-  public void writeCommandMapAttribute(final String map) throws IOException { // XXX use CommandMap instead of String
-    if (map != null) {
-      // XXX
-      writeAttribute(DataAttributes.COMMANDS, map, true);
-    }
+  @Deprecated
+  public void writeCommandMapAttribute(final String map) throws IOException {
+    Deprecation.LOG.error("No longer supported. Data: {}", map);
   }
 
   /**
diff --git a/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/TextareaController.java b/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/TextareaController.java
index 1a26d6e..3df98c7 100644
--- a/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/TextareaController.java
+++ b/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/TextareaController.java
@@ -19,15 +19,22 @@
 
 package org.apache.myfaces.tobago.example.demo;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import javax.enterprise.context.RequestScoped;
 import javax.inject.Named;
 import java.io.Serializable;
+import java.lang.invoke.MethodHandles;
 
 @RequestScoped
 @Named
 public class TextareaController implements Serializable {
 
+  private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
   private String longText;
+  private String ajaxValue;
 
   public TextareaController() {
     longText = "The goal of Apache Tobagoâ„¢ is to provide the community with a well designed set of user interface "
@@ -47,6 +54,11 @@ public class TextareaController implements Serializable {
         + "The development of Tobago started in 2002.";
   }
 
+  public String submit() {
+    LOG.info("Submit Textarea");
+    return null;
+  }
+
   public String getLongText() {
     return longText;
   }
@@ -54,4 +66,12 @@ public class TextareaController implements Serializable {
   public void setLongText(final String longText) {
     this.longText = longText;
   }
+
+  public String getAjaxValue() {
+    return ajaxValue;
+  }
+
+  public void setAjaxValue(String ajaxValue) {
+    this.ajaxValue = ajaxValue;
+  }
 }
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/10-in/In.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/10-in/In.test.js
index 0d4568b..16a31ad 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/10-in/In.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/10-in/In.test.js
@@ -47,7 +47,7 @@ QUnit.test("ajax change event", function (assert) {
   });
   TTT.action(function () {
     inputFieldFn().value = "qwe";
-    inputFieldFn().dispatchEvent(new Event('change'));
+    inputFieldFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/10-in/In.xhtml b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/10-in/In.xhtml
index d9f32b1..3640356 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/10-in/In.xhtml
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/10-in/In.xhtml
@@ -81,6 +81,8 @@
       Additional, the <code>listener</code> attribute is set. The given method is called after the inputfield
       loose focus.</p>
     <tc:in id="inputAjax" label="On Change" value="#{inController.changeValue}">
+      <f:facet name="before">AJAX</f:facet>
+      <f:facet name="after">on change</f:facet>
       <f:ajax render="outputAjax" listener="#{inController.update}"/>
     </tc:in>
     <tc:out id="outputAjax" label="On Server" value="#{inController.changeValue}"/>
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/20-suggest/Suggest.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/20-suggest/Suggest.test.js
index 5054d6a..f22cab7 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/20-suggest/Suggest.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/20-suggest/Suggest.test.js
@@ -53,7 +53,7 @@ function testMarsBasics(assert, inputString, expectedLength) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     inFn().value = inputString;
-    inFn().dispatchEvent(new Event('input'));
+    inFn().dispatchEvent(new Event("input", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(expectedLength + 1, function () {
@@ -72,7 +72,7 @@ QUnit.test("Basics: Add 'eus' and click first entry.", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     inFn().value = "eus";
-    inFn().dispatchEvent(new Event('input'));
+    inFn().dispatchEvent(new Event("input", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(5, function () {
@@ -83,7 +83,7 @@ QUnit.test("Basics: Add 'eus' and click first entry.", function (assert) {
     assert.equal(suggestionsFn().item(2).querySelector("strong").textContent, "eus");
   });
   TTT.action(function () {
-    suggestionsFn().item(0).click();
+    suggestionsFn().item(0).dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.asserts(1, function () {
     assert.equal(inFn().value, "Prometheus");
@@ -100,7 +100,7 @@ QUnit.test("Advanced: 'C'", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     inFn().value = "C";
-    inFn().dispatchEvent(new Event('input'));
+    inFn().dispatchEvent(new Event("input", {bubbles: true}));
   });
   TTT.waitMs(suggestionDelay);
   TTT.asserts(1, function () {
@@ -118,7 +118,7 @@ QUnit.test("Advanced: 'Ca'", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     inFn().value = "Ca";
-    inFn().dispatchEvent(new Event('input'));
+    inFn().dispatchEvent(new Event("input", {bubbles: true}));
   });
   TTT.waitMs(200); // default suggestion delay
   TTT.asserts(1, function () {
@@ -143,7 +143,7 @@ QUnit.test("Client side: 'Ju'", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     inFn().value = "Ju";
-    inFn().dispatchEvent(new Event('input'));
+    inFn().dispatchEvent(new Event("input", {bubbles: true}));
   });
   TTT.asserts(3, function () {
     assert.equal(suggestionsFn().length, 2);
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/30-textarea/Textarea.xhtml b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/30-textarea/Textarea.xhtml
index 1d36d52..2e5b249 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/30-textarea/Textarea.xhtml
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/30-textarea/Textarea.xhtml
@@ -20,7 +20,8 @@
 <ui:composition template="/main.xhtml"
                 xmlns="http://www.w3.org/1999/xhtml"
                 xmlns:tc="http://myfaces.apache.org/tobago/component"
-                xmlns:ui="http://java.sun.com/jsf/facelets">
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
 
   <p>The <code class="language-markup">&lt;tc:textarea/&gt;</code> tag, creates a textfield with one or more rows.
     The textarea becomes scrollable if the containing text could not displayed in the current size.</p>
@@ -50,7 +51,15 @@
       Leave the field blank and press 'submit' to see the errormessage.</p>
     <pre><code class="language-markup">&lt;tc:textarea id="treq" label="Text Area" required="true"/></code></pre>
     <tc:textarea id="treq" label="Text Area" required="true"/>
-    <tc:button label="Submit"/>
+    <tc:button label="Submit" action="#{textareaController.submit}"/>
+  </tc:section>
+
+  <tc:section label="Ajax">
+    <p>Ajax update by the change event:</p>
+    <tc:textarea id="tajax" label="Text Area" value="#{textareaController.ajaxValue}">
+      <f:ajax render="outputAjax" />
+    </tc:textarea>
+    <tc:out id="outputAjax" label="On Server" value="#{textareaController.ajaxValue}"/>
   </tc:section>
 
   <tc:section label="Rows">
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/40-date/Date.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/40-date/Date.test.js
index a0eae35..d2afd34 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/40-date/Date.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/40-date/Date.test.js
@@ -37,7 +37,7 @@ QUnit.test("date with label", function (assert) {
   assert.equal(dateFieldFn().value, today);
 
   dateFieldFn().value = "32.05.2016";
-  dateButtonFn().click();
+  dateButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
 
   assert.equal(dateFieldFn().value, today);
   assert.notOk(dayTodayFn().classList.contains("past"));
@@ -47,7 +47,7 @@ QUnit.test("date with label", function (assert) {
     assert.notOk(dayTodayFn().nextElementSibling.classList.contains("past"));
   }
 
-  dateButtonFn().click(); // IE11: close datetimepicker for next test
+  dateButtonFn().dispatchEvent(new Event("click", {bubbles: true})); // IE11: close datetimepicker for next test
 });
 
 QUnit.test("date+time pattern", function (assert) {
@@ -59,7 +59,7 @@ QUnit.test("date+time pattern", function (assert) {
 
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
-    dateButtonFn().click();
+    dateButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.asserts(3, function () {
     assert.ok(datepickerFn() !== null);
@@ -67,7 +67,7 @@ QUnit.test("date+time pattern", function (assert) {
     assert.equal(getComputedStyle(lastLiFn()).display, "none");
   });
   TTT.action(function () {
-    togglePickerButtonFn().click();
+    togglePickerButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitMs(1000); // wait for animation
   TTT.asserts(2, function () {
@@ -75,7 +75,7 @@ QUnit.test("date+time pattern", function (assert) {
     assert.notEqual(getComputedStyle(lastLiFn()).display, "none"); //block
   });
   TTT.action(function () {
-    dateButtonFn().click(); // IE11: close datetimepicker for next test
+    dateButtonFn().dispatchEvent(new Event("click", {bubbles: true})); // IE11: close datetimepicker for next test
   });
   TTT.startTest();
 });
@@ -95,7 +95,7 @@ QUnit.test("submit", function (assert) {
     assert.equal(outFieldFn().textContent, "22.05.2016");
   });
   TTT.action(function () {
-    dateButtonFn().click();
+    dateButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.asserts(2, function () {
     assert.ok(widgetFn().item(0), ".bootstrap-datetimepicker-widget should be available");
@@ -109,13 +109,13 @@ QUnit.test("submit", function (assert) {
     assert.ok(daysFn().item(day22 + 10));
   });
   TTT.action(function () {
-    daysFn().item(day22 + 10).click(); // Choose '01.06.2016'.
+    daysFn().item(day22 + 10).dispatchEvent(new Event("click", {bubbles: true})); // Choose '01.06.2016'.
   });
   TTT.asserts(1, function () {
     assert.equal(dateFieldFn().value, "01.06.2016");
   });
   TTT.action(function () {
-    submitButtonFn().click();
+    submitButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -137,7 +137,7 @@ QUnit.test("ajax", function (assert) {
     assert.equal(outFieldFn().textContent, "");
   });
   TTT.action(function () {
-    dateButtonFn().click();
+    dateButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/50-input-group/Group.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/50-input-group/Group.test.js
index be24022..dc68d8c 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/50-input-group/Group.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/50-input-group/Group.test.js
@@ -26,7 +26,7 @@ QUnit.test("ajax: chat send button", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     inputFn().value = "delete chat";
-    sendButtonFn().click();
+    sendButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -34,7 +34,7 @@ QUnit.test("ajax: chat send button", function (assert) {
   });
   TTT.action(function () {
     inputFn().value = "Hi Peter, how are you?";
-    sendButtonFn().click();
+    sendButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -52,24 +52,24 @@ QUnit.test("ajax: dropdown button", function (assert) {
 
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
-    buttonFn().click();
-    sendToPeterFn().click();
+    buttonFn().dispatchEvent(new Event("click", {bubbles: true}));
+    sendToPeterFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
     assert.equal(buttonLabelFn().textContent, "SendTo: Peter");
   });
   TTT.action(function () {
-    buttonFn().click();
-    sendToBobFn().click();
+    buttonFn().dispatchEvent(new Event("click", {bubbles: true}));
+    sendToBobFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
     assert.equal(buttonLabelFn().textContent, "SendTo: Bob");
   });
   TTT.action(function () {
-    buttonFn().click();
-    sendToAllFn().click();
+    buttonFn().dispatchEvent(new Event("click", {bubbles: true}));
+    sendToAllFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -91,7 +91,7 @@ QUnit.test("ajax: currency change event", function (assert) {
     currencyOptionFn().item(2).selected = false;
     currencyOptionFn().item(3).selected = false;
     currencyOptionFn().item(0).selected = true; // Yen
-    currencyFn().dispatchEvent(new Event('change'));
+    currencyFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -103,7 +103,7 @@ QUnit.test("ajax: currency change event", function (assert) {
     currencyOptionFn().item(2).selected = false;
     currencyOptionFn().item(3).selected = false;
     currencyOptionFn().item(1).selected = true; // Trinidad-Tobago Dollar
-    currencyFn().dispatchEvent(new Event('change'));
+    currencyFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -115,7 +115,7 @@ QUnit.test("ajax: currency change event", function (assert) {
     currencyOptionFn().item(1).selected = false;
     currencyOptionFn().item(3).selected = false;
     currencyOptionFn().item(2).selected = true; // US Dollar
-    currencyFn().dispatchEvent(new Event('change'));
+    currencyFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/10-selectBooleanCheckbox/Checkbox.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/10-selectBooleanCheckbox/Checkbox.test.js
index 94f1905..994ce61 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/10-selectBooleanCheckbox/Checkbox.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/10-selectBooleanCheckbox/Checkbox.test.js
@@ -67,7 +67,7 @@ QUnit.test("ajax: select D", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     selectDFn().checked = true;
-    selectDFn().dispatchEvent(new Event('change'));
+    selectDFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -83,7 +83,7 @@ QUnit.test("ajax: deselect D", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     selectDFn().checked = false;
-    selectDFn().dispatchEvent(new Event('change'));
+    selectDFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -99,7 +99,7 @@ QUnit.test("ajax: select E", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     selectEFn().checked = true;
-    selectEFn().dispatchEvent(new Event('change'));
+    selectEFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -115,7 +115,7 @@ QUnit.test("ajax: deselect E", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     selectEFn().checked = false;
-    selectEFn().dispatchEvent(new Event('change'));
+    selectEFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -131,7 +131,7 @@ QUnit.test("ajax: select F", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     selectFFn().checked = true;
-    selectFFn().dispatchEvent(new Event('change'));
+    selectFFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -147,7 +147,7 @@ QUnit.test("ajax: deselect F", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     selectFFn().checked = false;
-    selectFFn().dispatchEvent(new Event('change'));
+    selectFFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/15-selectBooleanToggle/Toggle.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/15-selectBooleanToggle/Toggle.test.js
index 94f1905..994ce61 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/15-selectBooleanToggle/Toggle.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/15-selectBooleanToggle/Toggle.test.js
@@ -67,7 +67,7 @@ QUnit.test("ajax: select D", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     selectDFn().checked = true;
-    selectDFn().dispatchEvent(new Event('change'));
+    selectDFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -83,7 +83,7 @@ QUnit.test("ajax: deselect D", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     selectDFn().checked = false;
-    selectDFn().dispatchEvent(new Event('change'));
+    selectDFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -99,7 +99,7 @@ QUnit.test("ajax: select E", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     selectEFn().checked = true;
-    selectEFn().dispatchEvent(new Event('change'));
+    selectEFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -115,7 +115,7 @@ QUnit.test("ajax: deselect E", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     selectEFn().checked = false;
-    selectEFn().dispatchEvent(new Event('change'));
+    selectEFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -131,7 +131,7 @@ QUnit.test("ajax: select F", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     selectFFn().checked = true;
-    selectFFn().dispatchEvent(new Event('change'));
+    selectFFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -147,7 +147,7 @@ QUnit.test("ajax: deselect F", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     selectFFn().checked = false;
-    selectFFn().dispatchEvent(new Event('change'));
+    selectFFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/20-selectOneChoice/Dropdown.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/20-selectOneChoice/Dropdown.test.js
index f0e335b..9297334 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/20-selectOneChoice/Dropdown.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/20-selectOneChoice/Dropdown.test.js
@@ -28,7 +28,7 @@ QUnit.test("submit: Alice", function (assert) {
   TTT.action(function () {
     aliceFn().selected = true;
     bobFn().selected = false;
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -47,7 +47,7 @@ QUnit.test("submit: Bob", function (assert) {
   TTT.action(function () {
     aliceFn().selected = false;
     bobFn().selected = true;
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -66,7 +66,7 @@ QUnit.test("ajax: select Mars", function (assert) {
   TTT.action(function () {
     jupiterOptionFn().selected = false;
     marsOptionFn().selected = true;
-    planetFn().dispatchEvent(new Event('change'));
+    planetFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(2, function () {
@@ -86,7 +86,7 @@ QUnit.test("ajax: select Jupiter", function (assert) {
   TTT.action(function () {
     marsOptionFn().selected = false;
     jupiterOptionFn().selected = true;
-    planetFn().dispatchEvent(new Event('change'));
+    planetFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(4, function () {
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/30-selectOneRadio/Radio.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/30-selectOneRadio/Radio.test.js
index b88361e..00e7a39 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/30-selectOneRadio/Radio.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/30-selectOneRadio/Radio.test.js
@@ -32,7 +32,7 @@ QUnit.test("submit: Addition (2 + 4)", function (assert) {
     number2Fn().item(0).checked = false;
     number2Fn().item(1).checked = false;
     number2Fn().item(2).checked = true; // Select 4
-    submitAddFn().click();
+    submitAddFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -55,7 +55,7 @@ QUnit.test("submit: Subtraction (4 - 1)", function (assert) {
     number2Fn().item(0).checked = true; // Select 1
     number2Fn().item(1).checked = false;
     number2Fn().item(2).checked = false;
-    submitSubFn().click();
+    submitSubFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -73,7 +73,7 @@ QUnit.test("ajax: select Mars", function (assert) {
     planetFn().item(0).checked = false;
     planetFn().item(2).checked = false;
     planetFn().item(1).checked = true; // Mars.
-    planetFn().item(1).dispatchEvent(new Event('change'));
+    planetFn().item(1).dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(2, function () {
@@ -92,7 +92,7 @@ QUnit.test("ajax: select Jupiter", function (assert) {
     planetFn().item(0).checked = false;
     planetFn().item(1).checked = false;
     planetFn().item(2).checked = true; // Jupiter.
-    planetFn().item(2).dispatchEvent(new Event('change'));
+    planetFn().item(2).dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(4, function () {
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/40-selectOneListbox/Listbox.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/40-selectOneListbox/Listbox.test.js
index 1dd4d64..6e72010 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/40-selectOneListbox/Listbox.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/40-selectOneListbox/Listbox.test.js
@@ -30,7 +30,7 @@ QUnit.test("submit: select 'Nile'", function (assert) {
     riversFn().item(2).selected = false; // Yangtze
     riversFn().item(3).selected = false; // Yellow River
     riversFn().item(4).selected = false; // Paraná River
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -51,7 +51,7 @@ QUnit.test("submit: select 'Yangtze'", function (assert) {
     riversFn().item(2).selected = true; // Yangtze
     riversFn().item(3).selected = false; // Yellow River
     riversFn().item(4).selected = false; // Paraná River
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -73,7 +73,7 @@ QUnit.test("ajax: select Everest", function (assert) {
     mountainsFn().item(3).selected = false;
     mountainsFn().item(4).selected = false;
     mountainsFn().item(0).selected = true; // Everest
-    mountainListFn().dispatchEvent(new Event('change')); // Everest
+    mountainListFn().dispatchEvent(new Event("change", {bubbles: true})); // Everest
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -94,7 +94,7 @@ QUnit.test("ajax: select Makalu", function (assert) {
     mountainsFn().item(2).selected = false;
     mountainsFn().item(3).selected = false;
     mountainsFn().item(4).selected = true; // Everest
-    mountainListFn().dispatchEvent(new Event('change')); // Everest
+    mountainListFn().dispatchEvent(new Event("change", {bubbles: true})); // Everest
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/50-selectManyCheckbox/Multi_Checkbox.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/50-selectManyCheckbox/Multi_Checkbox.test.js
index e41bc5f..19a864f 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/50-selectManyCheckbox/Multi_Checkbox.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/50-selectManyCheckbox/Multi_Checkbox.test.js
@@ -29,7 +29,7 @@ QUnit.test("submit: select cat", function (assert) {
     animalsFn().item(1).checked = false;
     animalsFn().item(2).checked = false;
     animalsFn().item(3).checked = false;
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -49,7 +49,7 @@ QUnit.test("submit: select fox and rabbit", function (assert) {
     animalsFn().item(1).checked = false;
     animalsFn().item(2).checked = true;
     animalsFn().item(3).checked = true;
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -68,11 +68,11 @@ QUnit.test("ajax: click 'Two'", function (assert) {
     if (number2Fn().checked) {
       newOutputValue = parseInt(outputFn().textContent) - 2;
       number2Fn().checked = false;
-      number2Fn().dispatchEvent(new Event('change'));
+      number2Fn().dispatchEvent(new Event("change", {bubbles: true}));
     } else {
       newOutputValue = parseInt(outputFn().textContent) + 2;
       number2Fn().checked = true;
-      number2Fn().dispatchEvent(new Event('change'));
+      number2Fn().dispatchEvent(new Event("change", {bubbles: true}));
     }
   });
   TTT.waitForResponse();
@@ -92,11 +92,11 @@ QUnit.test("ajax: click 'Three'", function (assert) {
     if (number3Fn().checked) {
       newOutputValue = parseInt(outputFn().textContent) - 3;
       number3Fn().checked = false;
-      number3Fn().dispatchEvent(new Event('change'));
+      number3Fn().dispatchEvent(new Event("change", {bubbles: true}));
     } else {
       newOutputValue = parseInt(outputFn().textContent) + 3;
       number3Fn().checked = true;
-      number3Fn().dispatchEvent(new Event('change'));
+      number3Fn().dispatchEvent(new Event("change", {bubbles: true}));
     }
   });
   TTT.waitForResponse();
@@ -116,11 +116,11 @@ QUnit.test("ajax: click 'Two'", function (assert) {
     if (number2Fn().checked) {
       newOutputValue = parseInt(outputFn().textContent) - 2;
       number2Fn().checked = false;
-      number2Fn().dispatchEvent(new Event('change'));
+      number2Fn().dispatchEvent(new Event("change", {bubbles: true}));
     } else {
       newOutputValue = parseInt(outputFn().textContent) + 2;
       number2Fn().checked = true;
-      number2Fn().dispatchEvent(new Event('change'));
+      number2Fn().dispatchEvent(new Event("change", {bubbles: true}));
     }
   });
   TTT.waitForResponse();
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/060-popup/Popup.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/060-popup/Popup.test.js
index 1659bd0..fbbea0e 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/060-popup/Popup.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/060-popup/Popup.test.js
@@ -26,9 +26,9 @@ QUnit.test("Open 'Client Popup' and press 'Cancel'.", function (assert) {
   let cancelButtonFn = testFrameQuerySelectorFn("#page\\:mainForm\\:form2\\:clientPopup\\:cancel2");
 
   assert.equal(popupFn().getAttribute("value"), "true");
-  openButtonFn().click();
+  openButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
   assert.equal(popupFn().getAttribute("value"), "false");
-  cancelButtonFn().click();
+  cancelButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
   assert.equal(popupFn().getAttribute("value"), "true");
 });
 
@@ -47,21 +47,21 @@ QUnit.test("Open 'Client Popup', press 'Submit' while field is empty. Press 'Can
     assert.equal(popupFn().getAttribute("value"), "true");
   });
   TTT.action(function () {
-    openButtonFn().click();
+    openButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.asserts(1, function () {
     assert.equal(popupFn().getAttribute("value"), "false");
   });
   TTT.action(function () {
     inputFieldFn().value = "";
-    submitButtonFn().click();
+    submitButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
     assert.equal(messagesFn().length, 1);
   });
   TTT.action(function () {
-    cancelButtonFn().click();
+    cancelButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.asserts(2, function () {
     assert.equal(popupFn().getAttribute("value"), "true");
@@ -84,21 +84,21 @@ QUnit.test("Open 'Client Popup', press 'Submit' while field has content. Press '
     assert.equal(popupFn().getAttribute("value"), "true");
   });
   TTT.action(function () {
-    openButtonFn().click();
+    openButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.asserts(1, function () {
     assert.equal(popupFn().getAttribute("value"), "false");
   });
   TTT.action(function () {
     inputFieldFn().value = "test client popup - submit button";
-    submitButtonFn().click();
+    submitButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
     assert.equal(messagesFn().length, 0);
   });
   TTT.action(function () {
-    cancelButtonFn().click();
+    cancelButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.asserts(2, function () {
     assert.equal(popupFn().getAttribute("value"), "true");
@@ -120,14 +120,14 @@ QUnit.test("Open 'Client Popup', press 'Submit & Close' while field is empty.",
     assert.equal(popupFn().getAttribute("value"), "true");
   });
   TTT.action(function () {
-    openButtonFn().click();
+    openButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.asserts(1, function () {
     assert.equal(popupFn().getAttribute("value"), "false");
   });
   TTT.action(function () {
     inputFieldFn().value = "";
-    submitCloseButtonFn().click();
+    submitCloseButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(2, function () {
@@ -149,14 +149,14 @@ QUnit.test("Open 'Client Popup', press 'Submit & Close' while field has content.
     assert.equal(popupFn().getAttribute("value"), "true");
   });
   TTT.action(function () {
-    openButtonFn().click();
+    openButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.asserts(1, function () {
     assert.equal(popupFn().getAttribute("value"), "false");
   });
   TTT.action(function () {
     inputFieldFn().value = "test client popup - submit and close button";
-    submitCloseButtonFn().click();
+    submitCloseButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(2, function () {
@@ -176,10 +176,10 @@ QUnit.test("Open 'Large Popup'.", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     if (popupFn().classList.contains("show")) {
-      closeButtonFn().click();
+      closeButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
     }
     if (dropdownContainerFn().classList.contains("show")) {
-      dropdownButtonFn().click();
+      dropdownButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
     }
   });
   TTT.asserts(2, function () {
@@ -187,14 +187,14 @@ QUnit.test("Open 'Large Popup'.", function (assert) {
     assert.equal(popupFn().classList.contains("show"), false);
   });
   TTT.action(function () {
-    dropdownButtonFn().click();
+    dropdownButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.asserts(2, function () {
     assert.equal(dropdownContainerFn().classList.contains("show"), true);
     assert.equal(popupFn().classList.contains("show"), false);
   });
   TTT.action(function () {
-    openButtonFn().click();
+    openButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitMs(1000); // wait for animation
   TTT.asserts(2, function () {
@@ -202,7 +202,7 @@ QUnit.test("Open 'Large Popup'.", function (assert) {
     assert.equal(popupFn().classList.contains("show"), true);
   });
   TTT.action(function () {
-    closeButtonFn().click();
+    closeButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitMs(1000); // wait for animation
   TTT.asserts(2, function () {
@@ -222,7 +222,7 @@ QUnit.test("Open 'Small Popup'.", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     if (popupFn().classList.contains("show")) {
-      closeButtonFn().click();
+      closeButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
     }
     if (dropdownContainerFn().classList.contains("show")) {
       dropdownButtonFn().click();
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/070-tab/Tab_Group.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/070-tab/Tab_Group.test.js
index 97d9081..d9bf8af 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/070-tab/Tab_Group.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/070-tab/Tab_Group.test.js
@@ -32,7 +32,7 @@ QUnit.test("Client: Select Tab 3", function (assert) {
     assert.ok(tab3Fn().classList.contains("tobago-tab-markup-three"));
   });
   TTT.action(function () {
-    tab3Fn().querySelector(".nav-link").click();
+    tab3Fn().querySelector(".nav-link").dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.asserts(5, function () {
     assert.equal(tabGroupFn().hiddenInput.value, 3);
@@ -58,7 +58,7 @@ QUnit.test("Ajax: Select Tab 3", function (assert) {
     assert.ok(tab3Fn().classList.contains("tobago-tab-markup-three"));
   });
   TTT.action(function () {
-    tab3Fn().querySelector(".nav-link").click();
+    tab3Fn().querySelector(".nav-link").dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(5, function () {
@@ -85,7 +85,7 @@ QUnit.test("FullReload: Select Tab 3", function (assert) {
     assert.ok(tab3Fn().classList.contains("tobago-tab-markup-three"));
   });
   TTT.action(function () {
-    tab3Fn().querySelector(".nav-link").click();
+    tab3Fn().querySelector(".nav-link").dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(5, function () {
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/10-sort/Sheet_Sorting.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/10-sort/Sheet_Sorting.test.js
index f8d99d2..e4eeba2 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/10-sort/Sheet_Sorting.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/10-sort/Sheet_Sorting.test.js
@@ -26,7 +26,7 @@ QUnit.test("Basics: Name", function (assert) {
   let TTT = new TobagoTestTool(assert);
   if (!colNameFn().classList.contains("tobago-sheet-header-markup-ascending")) {
     TTT.action(function () {
-      colNameFn().click();
+      colNameFn().dispatchEvent(new Event("click", {bubbles: true}));
     });
     TTT.waitForResponse();
   }
@@ -37,7 +37,7 @@ QUnit.test("Basics: Name", function (assert) {
   });
   TTT.action(function () {
     leftPagingFn().value = "22";
-    leftPagingFn().dispatchEvent(new Event('blur'));
+    leftPagingFn().dispatchEvent(new Event("blur", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(12, function () {
@@ -48,7 +48,7 @@ QUnit.test("Basics: Name", function (assert) {
         "Epimetheus", "0.69", "1980");
   });
   TTT.action(function () {
-    colNameFn().click();
+    colNameFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(12, function () {
@@ -59,7 +59,7 @@ QUnit.test("Basics: Name", function (assert) {
         "Praxidike", "625.3", "2000");
   });
   TTT.action(function () {
-    colNameFn().click();
+    colNameFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(12, function () {
@@ -80,7 +80,7 @@ QUnit.test("Basics: Period", function (assert) {
   let TTT = new TobagoTestTool(assert);
   if (!colPeriodFn().classList.contains("tobago-sheet-header-markup-ascending")) {
     TTT.action(function () {
-      colPeriodFn().click();
+      colPeriodFn().dispatchEvent(new Event("click", {bubbles: true}));
     });
     TTT.waitForResponse();
   }
@@ -91,7 +91,7 @@ QUnit.test("Basics: Period", function (assert) {
   });
   TTT.action(function () {
     leftPagingFn().value = "29";
-    leftPagingFn().dispatchEvent(new Event('blur'));
+    leftPagingFn().dispatchEvent(new Event("blur", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(12, function () {
@@ -102,7 +102,7 @@ QUnit.test("Basics: Period", function (assert) {
         "Prometheus", "0.61", "1980");
   });
   TTT.action(function () {
-    colPeriodFn().click();
+    colPeriodFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(12, function () {
@@ -113,7 +113,7 @@ QUnit.test("Basics: Period", function (assert) {
         "Titania", "8.71", "1787");
   });
   TTT.action(function () {
-    colPeriodFn().click();
+    colPeriodFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(12, function () {
@@ -134,7 +134,7 @@ QUnit.test("Basics: Year", function (assert) {
   let TTT = new TobagoTestTool(assert);
   if (!colYearFn().classList.contains("tobago-sheet-header-markup-ascending")) {
     TTT.action(function () {
-      colYearFn().click();
+      colYearFn().dispatchEvent(new Event("click", {bubbles: true}));
     });
     TTT.waitForResponse();
   }
@@ -145,7 +145,7 @@ QUnit.test("Basics: Year", function (assert) {
   });
   TTT.action(function () {
     leftPagingFn().value = "22";
-    leftPagingFn().dispatchEvent(new Event('blur'));
+    leftPagingFn().dispatchEvent(new Event("blur", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(4, function () {
@@ -155,7 +155,7 @@ QUnit.test("Basics: Year", function (assert) {
     assert.equal(rowsFn().item(3).querySelectorAll(".tobago-sheet-cell").item(2).textContent.trim(), "1905", "row3col2");
   });
   TTT.action(function () {
-    colYearFn().click();
+    colYearFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(4, function () {
@@ -165,7 +165,7 @@ QUnit.test("Basics: Year", function (assert) {
     assert.equal(rowsFn().item(3).querySelectorAll(".tobago-sheet-cell").item(2).textContent.trim(), "1997", "row3col2");
   });
   TTT.action(function () {
-    colYearFn().click();
+    colYearFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(4, function () {
@@ -189,7 +189,7 @@ QUnit.test("Basics: left paging", function (assert) {
   let TTT = new TobagoTestTool(assert);
   if (!colNameFn().classList.contains("tobago-sheet-header-markup-ascending")) {
     TTT.action(function () {
-      colNameFn().click();
+      colNameFn().dispatchEvent(new Event("click", {bubbles: true}));
     });
     TTT.waitForResponse();
   }
@@ -200,7 +200,7 @@ QUnit.test("Basics: left paging", function (assert) {
   });
   TTT.action(function () {
     leftPagingFn().value = "8";
-    leftPagingFn().dispatchEvent(new Event('blur'));
+    leftPagingFn().dispatchEvent(new Event("blur", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(12, function () {
@@ -212,7 +212,7 @@ QUnit.test("Basics: left paging", function (assert) {
   });
   TTT.action(function () {
     leftPagingFn().value = "9";
-    leftPagingFn().dispatchEvent(new Event('blur'));
+    leftPagingFn().dispatchEvent(new Event("blur", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(12, function () {
@@ -239,7 +239,7 @@ QUnit.test("Basics: center paging", function (assert) {
   let TTT = new TobagoTestTool(assert);
   if (!colNameFn().classList.contains("tobago-sheet-header-markup-ascending")) {
     TTT.action(function () {
-      colNameFn().click();
+      colNameFn().dispatchEvent(new Event("click", {bubbles: true}));
     });
     TTT.waitForResponse();
   }
@@ -250,7 +250,7 @@ QUnit.test("Basics: center paging", function (assert) {
   });
   TTT.action(function () {
     leftPagingFn().value = "1";
-    leftPagingFn().dispatchEvent(new Event('blur'));
+    leftPagingFn().dispatchEvent(new Event("blur", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(12, function () {
@@ -261,7 +261,7 @@ QUnit.test("Basics: center paging", function (assert) {
         "Ananke", "-629.77", "1951");
   });
   TTT.action(function () {
-    centerPagingFn().item(6).click();
+    centerPagingFn().item(6).dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(12, function () {
@@ -272,7 +272,7 @@ QUnit.test("Basics: center paging", function (assert) {
         "Galatea", "0.43", "1989");
   });
   TTT.action(function () {
-    centerPagingFn().item(10).click();
+    centerPagingFn().item(10).dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(12, function () {
@@ -283,7 +283,7 @@ QUnit.test("Basics: center paging", function (assert) {
         "Praxidike", "625.3", "2000");
   });
   TTT.action(function () {
-    centerPagingFn().item(3).click();
+    centerPagingFn().item(3).dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(12, function () {
@@ -313,7 +313,7 @@ QUnit.test("Basics: right paging", function (assert) {
   let TTT = new TobagoTestTool(assert);
   if (!colNameFn().classList.contains("tobago-sheet-header-markup-ascending")) {
     TTT.action(function () {
-      colNameFn().click();
+      colNameFn().dispatchEvent(new Event("click", {bubbles: true}));
     });
     TTT.waitForResponse();
   }
@@ -324,7 +324,7 @@ QUnit.test("Basics: right paging", function (assert) {
   });
   TTT.action(function () {
     leftPagingFn().value = "22";
-    leftPagingFn().dispatchEvent(new Event('blur'));
+    leftPagingFn().dispatchEvent(new Event("blur", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(12, function () {
@@ -335,7 +335,7 @@ QUnit.test("Basics: right paging", function (assert) {
         "Epimetheus", "0.69", "1980");
   });
   TTT.action(function () {
-    rightPagingFn().item(0).click();
+    rightPagingFn().item(0).dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(12, function () {
@@ -346,7 +346,7 @@ QUnit.test("Basics: right paging", function (assert) {
         "Ananke", "-629.77", "1951");
   });
   TTT.action(function () {
-    rightPagingFn().item(3).click();
+    rightPagingFn().item(3).dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(12, function () {
@@ -357,7 +357,7 @@ QUnit.test("Basics: right paging", function (assert) {
         "Bianca", "0.43", "1986");
   });
   TTT.action(function () {
-    rightPagingFn().item(4).click();
+    rightPagingFn().item(4).dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(12, function () {
@@ -368,7 +368,7 @@ QUnit.test("Basics: right paging", function (assert) {
         "Venus", "224.7", "");
   });
   TTT.action(function () {
-    rightPagingFn().item(1).click();
+    rightPagingFn().item(1).dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(12, function () {
@@ -380,7 +380,7 @@ QUnit.test("Basics: right paging", function (assert) {
   });
   TTT.action(function () {
     jumpToPageFn().value = "14";
-    jumpToPageFn().dispatchEvent(new Event('blur'));
+    jumpToPageFn().dispatchEvent(new Event("blur", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(12, function () {
@@ -401,7 +401,7 @@ QUnit.test("Custom Sorting: Name", function (assert) {
   let TTT = new TobagoTestTool(assert);
   if (!colNameFn().classList.contains("tobago-sheet-header-markup-ascending")) {
     TTT.action(function () {
-      colNameFn().click();
+      colNameFn().dispatchEvent(new Event("click", {bubbles: true}));
     });
     TTT.waitForResponse();
   }
@@ -412,7 +412,7 @@ QUnit.test("Custom Sorting: Name", function (assert) {
   });
   TTT.action(function () {
     leftPagingFn().value = "22";
-    leftPagingFn().dispatchEvent(new Event('blur'));
+    leftPagingFn().dispatchEvent(new Event("blur", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(12, function () {
@@ -423,7 +423,7 @@ QUnit.test("Custom Sorting: Name", function (assert) {
         "Epimetheus", "0.69", "1980");
   });
   TTT.action(function () {
-    colNameFn().click();
+    colNameFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(12, function () {
@@ -434,7 +434,7 @@ QUnit.test("Custom Sorting: Name", function (assert) {
         "Praxidike", "625.3", "2000");
   });
   TTT.action(function () {
-    colNameFn().click();
+    colNameFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(12, function () {
@@ -455,7 +455,7 @@ QUnit.test("Custom Sorting: Period", function (assert) {
   let TTT = new TobagoTestTool(assert);
   if (!colPeriodFn().classList.contains("tobago-sheet-header-markup-ascending")) {
     TTT.action(function () {
-      colPeriodFn().click();
+      colPeriodFn().dispatchEvent(new Event("click", {bubbles: true}));
     });
     TTT.waitForResponse();
   }
@@ -466,7 +466,7 @@ QUnit.test("Custom Sorting: Period", function (assert) {
   });
   TTT.action(function () {
     leftPagingFn().value = "29";
-    leftPagingFn().dispatchEvent(new Event('blur'));
+    leftPagingFn().dispatchEvent(new Event("blur", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(12, function () {
@@ -477,7 +477,7 @@ QUnit.test("Custom Sorting: Period", function (assert) {
         "Enceladus", "1.37", "1789");
   });
   TTT.action(function () {
-    colPeriodFn().click();
+    colPeriodFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(12, function () {
@@ -488,7 +488,7 @@ QUnit.test("Custom Sorting: Period", function (assert) {
         "Leda", "238.72", "1974");
   });
   TTT.action(function () {
-    colPeriodFn().click();
+    colPeriodFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(12, function () {
@@ -509,7 +509,7 @@ QUnit.test("Custom Sorting: Year", function (assert) {
   let TTT = new TobagoTestTool(assert);
   if (!colYearFn().classList.contains("tobago-sheet-header-markup-ascending")) {
     TTT.action(function () {
-      colYearFn().click();
+      colYearFn().dispatchEvent(new Event("click", {bubbles: true}));
     });
     TTT.waitForResponse();
   }
@@ -520,7 +520,7 @@ QUnit.test("Custom Sorting: Year", function (assert) {
   });
   TTT.action(function () {
     leftPagingFn().value = "22";
-    leftPagingFn().dispatchEvent(new Event('blur'));
+    leftPagingFn().dispatchEvent(new Event("blur", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(4, function () {
@@ -530,7 +530,7 @@ QUnit.test("Custom Sorting: Year", function (assert) {
     assert.equal(rowsFn().item(3).querySelectorAll(".tobago-sheet-cell").item(2).textContent.trim(), "1848", "row3col2");
   });
   TTT.action(function () {
-    colYearFn().click();
+    colYearFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(4, function () {
@@ -540,7 +540,7 @@ QUnit.test("Custom Sorting: Year", function (assert) {
     assert.equal(rowsFn().item(3).querySelectorAll(".tobago-sheet-cell").item(2).textContent.trim(), "1986", "row3col2");
   });
   TTT.action(function () {
-    colYearFn().click();
+    colYearFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(4, function () {
@@ -564,7 +564,7 @@ QUnit.test("Custom Sorting: left paging", function (assert) {
   let TTT = new TobagoTestTool(assert);
   if (!colNameFn().classList.contains("tobago-sheet-header-markup-ascending")) {
     TTT.action(function () {
-      colNameFn().click();
+      colNameFn().dispatchEvent(new Event("click", {bubbles: true}));
     });
     TTT.waitForResponse();
   }
@@ -575,7 +575,7 @@ QUnit.test("Custom Sorting: left paging", function (assert) {
   });
   TTT.action(function () {
     leftPagingFn().value = "8";
-    leftPagingFn().dispatchEvent(new Event('blur'));
+    leftPagingFn().dispatchEvent(new Event("blur", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(12, function () {
@@ -587,7 +587,7 @@ QUnit.test("Custom Sorting: left paging", function (assert) {
   });
   TTT.action(function () {
     leftPagingFn().value = "9";
-    leftPagingFn().dispatchEvent(new Event('blur'));
+    leftPagingFn().dispatchEvent(new Event("blur", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(12, function () {
@@ -614,7 +614,7 @@ QUnit.test("Custom Sorting: center paging", function (assert) {
   let TTT = new TobagoTestTool(assert);
   if (!colNameFn().classList.contains("tobago-sheet-header-markup-ascending")) {
     TTT.action(function () {
-      colNameFn().click();
+      colNameFn().dispatchEvent(new Event("click", {bubbles: true}));
     });
     TTT.waitForResponse();
   }
@@ -625,7 +625,7 @@ QUnit.test("Custom Sorting: center paging", function (assert) {
   });
   TTT.action(function () {
     leftPagingFn().value = "1";
-    leftPagingFn().dispatchEvent(new Event('blur'));
+    leftPagingFn().dispatchEvent(new Event("blur", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(12, function () {
@@ -636,7 +636,7 @@ QUnit.test("Custom Sorting: center paging", function (assert) {
         "Ananke", "-629.77", "1951");
   });
   TTT.action(function () {
-    centerPagingFn().item(6).click();
+    centerPagingFn().item(6).dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(12, function () {
@@ -647,7 +647,7 @@ QUnit.test("Custom Sorting: center paging", function (assert) {
         "Galatea", "0.43", "1989");
   });
   TTT.action(function () {
-    centerPagingFn().item(10).click();
+    centerPagingFn().item(10).dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(12, function () {
@@ -658,7 +658,7 @@ QUnit.test("Custom Sorting: center paging", function (assert) {
         "Praxidike", "625.3", "2000");
   });
   TTT.action(function () {
-    centerPagingFn().item(3).click();
+    centerPagingFn().item(3).dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(12, function () {
@@ -688,7 +688,7 @@ QUnit.test("Custom Sorting: right paging", function (assert) {
   let TTT = new TobagoTestTool(assert);
   if (!colNameFn().classList.contains("tobago-sheet-header-markup-ascending")) {
     TTT.action(function () {
-      colNameFn().click();
+      colNameFn().dispatchEvent(new Event("click", {bubbles: true}));
     });
     TTT.waitForResponse();
   }
@@ -699,7 +699,7 @@ QUnit.test("Custom Sorting: right paging", function (assert) {
   });
   TTT.action(function () {
     leftPagingFn().value = "22";
-    leftPagingFn().dispatchEvent(new Event('blur'));
+    leftPagingFn().dispatchEvent(new Event("blur", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(12, function () {
@@ -710,7 +710,7 @@ QUnit.test("Custom Sorting: right paging", function (assert) {
         "Epimetheus", "0.69", "1980");
   });
   TTT.action(function () {
-    rightPagingFn().item(0).click();
+    rightPagingFn().item(0).dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(12, function () {
@@ -721,7 +721,7 @@ QUnit.test("Custom Sorting: right paging", function (assert) {
         "Ananke", "-629.77", "1951");
   });
   TTT.action(function () {
-    rightPagingFn().item(3).click();
+    rightPagingFn().item(3).dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(12, function () {
@@ -732,7 +732,7 @@ QUnit.test("Custom Sorting: right paging", function (assert) {
         "Bianca", "0.43", "1986");
   });
   TTT.action(function () {
-    rightPagingFn().item(4).click();
+    rightPagingFn().item(4).dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(12, function () {
@@ -743,7 +743,7 @@ QUnit.test("Custom Sorting: right paging", function (assert) {
         "Venus", "224.7", "");
   });
   TTT.action(function () {
-    rightPagingFn().item(1).click();
+    rightPagingFn().item(1).dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(12, function () {
@@ -755,7 +755,7 @@ QUnit.test("Custom Sorting: right paging", function (assert) {
   });
   TTT.action(function () {
     rightPagingInputFn().value = "14";
-    rightPagingInputFn().dispatchEvent(new Event('blur'));
+    rightPagingInputFn().dispatchEvent(new Event("blur", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(12, function () {
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/30-event/Sheet_Event.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/30-event/Sheet_Event.test.js
index cef2c6c..1f28ea9 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/30-event/Sheet_Event.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/30-event/Sheet_Event.test.js
@@ -28,7 +28,7 @@ QUnit.test("On click with ajax", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     oneClickAjaxFn().checked = true;
-    oneClickAjaxFn().dispatchEvent(new Event('change'));
+    oneClickAjaxFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
@@ -37,21 +37,21 @@ QUnit.test("On click with ajax", function (assert) {
     assert.ok(saturnFn());
   });
   TTT.action(function () {
-    venusFn().click();
+    venusFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
     assert.equal(namefieldFn().value, "Venus");
   });
   TTT.action(function () {
-    jupiterFn().click();
+    jupiterFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
     assert.equal(namefieldFn().value, "Jupiter");
   });
   TTT.action(function () {
-    saturnFn().click();
+    saturnFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -70,7 +70,7 @@ QUnit.test("On click with full request", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     oneClickFullRequestFn().checked = true;
-    oneClickFullRequestFn().dispatchEvent(new Event('change'));
+    oneClickFullRequestFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
@@ -79,21 +79,21 @@ QUnit.test("On click with full request", function (assert) {
     assert.ok(saturnFn());
   });
   TTT.action(function () {
-    venusFn().click();
+    venusFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
     assert.equal(namefieldFn().value, "Venus");
   });
   TTT.action(function () {
-    jupiterFn().click();
+    jupiterFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
     assert.equal(namefieldFn().value, "Jupiter");
   });
   TTT.action(function () {
-    saturnFn().click();
+    saturnFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -112,7 +112,7 @@ QUnit.test("On double click with full request", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     doubleClickFullRequestFn().checked = true;
-    doubleClickFullRequestFn().dispatchEvent(new Event('change'));
+    doubleClickFullRequestFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
@@ -121,21 +121,21 @@ QUnit.test("On double click with full request", function (assert) {
     assert.ok(saturnFn());
   });
   TTT.action(function () {
-    venusFn().dispatchEvent(new Event('dblclick'));
+    venusFn().dispatchEvent(new Event("dblclick", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
     assert.equal(namefieldFn().value, "Venus");
   });
   TTT.action(function () {
-    jupiterFn().dispatchEvent(new Event('dblclick'));
+    jupiterFn().dispatchEvent(new Event("dblclick", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
     assert.equal(namefieldFn().value, "Jupiter");
   });
   TTT.action(function () {
-    saturnFn().dispatchEvent(new Event('dblclick'));
+    saturnFn().dispatchEvent(new Event("dblclick", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -156,7 +156,7 @@ QUnit.test("Open popup on click with ajax", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     radioButtonFn().checked = true;
-    radioButtonFn().dispatchEvent(new Event('change'));
+    radioButtonFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
@@ -165,7 +165,7 @@ QUnit.test("Open popup on click with ajax", function (assert) {
     assert.ok(saturnFn());
   });
   TTT.action(function () {
-    venusFn().click();
+    venusFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.waitMs(1000); // wait for animation
@@ -174,14 +174,14 @@ QUnit.test("Open popup on click with ajax", function (assert) {
     assert.equal(nameFn().value, "Venus");
   });
   TTT.action(function () {
-    cancelFn().click();
+    cancelFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitMs(1000); // wait for animation
   TTT.asserts(1, function () {
     assert.notOk(popupFn().classList.contains("show"));
   });
   TTT.action(function () {
-    jupiterFn().click();
+    jupiterFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.waitMs(1000); // wait for animation
@@ -190,14 +190,14 @@ QUnit.test("Open popup on click with ajax", function (assert) {
     assert.equal(nameFn().value, "Jupiter");
   });
   TTT.action(function () {
-    cancelFn().click();
+    cancelFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitMs(1000); // wait for animation
   TTT.asserts(1, function () {
     assert.notOk(popupFn().classList.contains("show"));
   });
   TTT.action(function () {
-    saturnFn().click();
+    saturnFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.waitMs(1000); // wait for animation
@@ -206,7 +206,7 @@ QUnit.test("Open popup on click with ajax", function (assert) {
     assert.equal(nameFn().value, "Saturn");
   });
   TTT.action(function () {
-    cancelFn().click();
+    cancelFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitMs(1000); // wait for animation
   TTT.asserts(1, function () {
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/70-tree/Sheet_Tree.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/70-tree/Sheet_Tree.test.js
index 52d5e9a..6161cb5 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/70-tree/Sheet_Tree.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/70-tree/Sheet_Tree.test.js
@@ -53,7 +53,7 @@ QUnit.test("Collapse tree", function (assert) {
     assert.notEqual(getComputedStyle(sheetRow).display, "none");
   });
   TTT.action(function () {
-    rootTreeButtonFn().click();
+    rootTreeButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitMs(1000);
   TTT.asserts(8, function () {
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/090-tree/01-select/Tree_Select.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/090-tree/01-select/Tree_Select.test.js
index 6ae2232..7b638ed 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/090-tree/01-select/Tree_Select.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/090-tree/01-select/Tree_Select.test.js
@@ -29,7 +29,7 @@ QUnit.test("single: select Music, select Mathematics", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     selectableNoneFn().checked = true;
-    selectableNoneFn().dispatchEvent(new Event('change'));
+    selectableNoneFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -37,7 +37,7 @@ QUnit.test("single: select Music, select Mathematics", function (assert) {
   });
   TTT.action(function () {
     selectableSingleFn().checked = true;
-    selectableSingleFn().dispatchEvent(new Event('change'));
+    selectableSingleFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -45,7 +45,7 @@ QUnit.test("single: select Music, select Mathematics", function (assert) {
   });
   TTT.action(function () {
     musicFn().checked = true;
-    musicFn().dispatchEvent(new Event('change'));
+    musicFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -53,7 +53,7 @@ QUnit.test("single: select Music, select Mathematics", function (assert) {
   });
   TTT.action(function () {
     mathematicsFn().checked = true;
-    mathematicsFn().dispatchEvent(new Event('change'));
+    mathematicsFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -73,7 +73,7 @@ QUnit.test("singleLeafOnly: select Classic, select Mathematics", function (asser
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     selectableNoneFn().checked = true;
-    selectableNoneFn().dispatchEvent(new Event('change'));
+    selectableNoneFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -81,7 +81,7 @@ QUnit.test("singleLeafOnly: select Classic, select Mathematics", function (asser
   });
   TTT.action(function () {
     selectableSingleLeafOnlyFn().checked = true;
-    selectableSingleLeafOnlyFn().dispatchEvent(new Event('change'));
+    selectableSingleLeafOnlyFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -89,7 +89,7 @@ QUnit.test("singleLeafOnly: select Classic, select Mathematics", function (asser
   });
   TTT.action(function () {
     classicFn().checked = true;
-    classicFn().dispatchEvent(new Event('change'));
+    classicFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -97,7 +97,7 @@ QUnit.test("singleLeafOnly: select Classic, select Mathematics", function (asser
   });
   TTT.action(function () {
     mathematicsFn().checked = true;
-    mathematicsFn().dispatchEvent(new Event('change'));
+    mathematicsFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -117,7 +117,7 @@ QUnit.test("multi: select Music, select Mathematics, deselect Music", function (
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     selectableNoneFn().checked = true;
-    selectableNoneFn().dispatchEvent(new Event('change'));
+    selectableNoneFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -125,7 +125,7 @@ QUnit.test("multi: select Music, select Mathematics, deselect Music", function (
   });
   TTT.action(function () {
     selectableMultiFn().checked = true;
-    selectableMultiFn().dispatchEvent(new Event('change'));
+    selectableMultiFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -133,7 +133,7 @@ QUnit.test("multi: select Music, select Mathematics, deselect Music", function (
   });
   TTT.action(function () {
     musicFn().checked = true;
-    musicFn().dispatchEvent(new Event('change'));
+    musicFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -141,7 +141,7 @@ QUnit.test("multi: select Music, select Mathematics, deselect Music", function (
   });
   TTT.action(function () {
     mathematicsFn().checked = true;
-    mathematicsFn().dispatchEvent(new Event('change'));
+    mathematicsFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -149,7 +149,7 @@ QUnit.test("multi: select Music, select Mathematics, deselect Music", function (
   });
   TTT.action(function () {
     musicFn().checked = false;
-    musicFn().dispatchEvent(new Event('change'));
+    musicFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -169,7 +169,7 @@ QUnit.test("multiLeafOnly: select Classic, select Mathematics, deselect Classic"
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     selectableNoneFn().checked = true;
-    selectableNoneFn().dispatchEvent(new Event('change'));
+    selectableNoneFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -177,7 +177,7 @@ QUnit.test("multiLeafOnly: select Classic, select Mathematics, deselect Classic"
   });
   TTT.action(function () {
     selectableMultiLeafOnlyFn().checked = true;
-    selectableMultiLeafOnlyFn().dispatchEvent(new Event('change'));
+    selectableMultiLeafOnlyFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -185,7 +185,7 @@ QUnit.test("multiLeafOnly: select Classic, select Mathematics, deselect Classic"
   });
   TTT.action(function () {
     classicFn().checked = true;
-    classicFn().dispatchEvent(new Event('change'));
+    classicFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -193,7 +193,7 @@ QUnit.test("multiLeafOnly: select Classic, select Mathematics, deselect Classic"
   });
   TTT.action(function () {
     mathematicsFn().checked = true;
-    mathematicsFn().dispatchEvent(new Event('change'));
+    mathematicsFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -201,7 +201,7 @@ QUnit.test("multiLeafOnly: select Classic, select Mathematics, deselect Classic"
   });
   TTT.action(function () {
     classicFn().checked = false;
-    classicFn().dispatchEvent(new Event('change'));
+    classicFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -222,7 +222,7 @@ QUnit.test("multiCascade: select Music, select Mathematics, deselect Classic", f
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     selectableNoneFn().checked = true;
-    selectableNoneFn().dispatchEvent(new Event('change'));
+    selectableNoneFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -230,7 +230,7 @@ QUnit.test("multiCascade: select Music, select Mathematics, deselect Classic", f
   });
   TTT.action(function () {
     selectableMultiCascadeFn().checked = true;
-    selectableMultiCascadeFn().dispatchEvent(new Event('change'));
+    selectableMultiCascadeFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -238,7 +238,7 @@ QUnit.test("multiCascade: select Music, select Mathematics, deselect Classic", f
   });
   TTT.action(function () {
     musicFn().checked = true;
-    musicFn().dispatchEvent(new Event('change'));
+    musicFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse(); // an ajax request is send for every leaf (Music, Classic, Pop, World)
   TTT.waitMs(2000); // wait for the last ajax
@@ -247,7 +247,7 @@ QUnit.test("multiCascade: select Music, select Mathematics, deselect Classic", f
   });
   TTT.action(function () {
     mathematicsFn().checked = true;
-    mathematicsFn().dispatchEvent(new Event('change'));
+    mathematicsFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -255,7 +255,7 @@ QUnit.test("multiCascade: select Music, select Mathematics, deselect Classic", f
   });
   TTT.action(function () {
     classicFn().checked = false;
-    classicFn().dispatchEvent(new Event('change'));
+    classicFn().dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/06-validation/00/Content_Validation.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/06-validation/00/Content_Validation.test.js
index f3fd1ad..fe976fb 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/06-validation/00/Content_Validation.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/06-validation/00/Content_Validation.test.js
@@ -27,7 +27,7 @@ QUnit.test("Required: Submit without content.", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     textareaFn().value = "";
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(2, function () {
@@ -45,7 +45,7 @@ QUnit.test("Required: Submit with content.", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     textareaFn().value = "some content";
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(2, function () {
@@ -63,7 +63,7 @@ QUnit.test("Validate Length: Submit single character.", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     inFn().value = "a";
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -80,7 +80,7 @@ QUnit.test("Validate Length: Submit two character.", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     inFn().value = "ab";
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -97,7 +97,7 @@ QUnit.test("Validate Range: Submit no number.", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     inFn().value = "no number";
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -114,7 +114,7 @@ QUnit.test("Validate Range: Submit number '2' which is out of range.", function
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     inFn().value = "2";
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -131,7 +131,7 @@ QUnit.test("Validate Range: Submit number '78' which is out of range.", function
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     inFn().value = "78";
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -148,7 +148,7 @@ QUnit.test("Validate Range: Submit number '64' which is within the range.", func
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     inFn().value = "64";
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -165,7 +165,7 @@ QUnit.test("Regex Validation: Submit 'T' which violates the pattern.", function
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     inFn().value = "T";
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -182,7 +182,7 @@ QUnit.test("Regex Validation: Submit '3' which violates the pattern.", function
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     inFn().value = "3";
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -199,7 +199,7 @@ QUnit.test("Regex Validation: Submit 'T3' which is accepted.", function (assert)
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     inFn().value = "T3";
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -216,7 +216,7 @@ QUnit.test("Custom Validator: Submit rejected string.", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     inFn().value = "java";
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -233,7 +233,7 @@ QUnit.test("Custom Validator: Submit accepted string.", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     inFn().value = "tobago";
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/06-validation/01/JSR_303.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/06-validation/01/JSR_303.test.js
index 9e01a0e..029b4f2 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/06-validation/01/JSR_303.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/06-validation/01/JSR_303.test.js
@@ -26,7 +26,7 @@ QUnit.test("Required: Submit without content.", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     inFn().value = "";
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -43,7 +43,7 @@ QUnit.test("Required: Submit with content.", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     inFn().value = "some content";
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -60,7 +60,7 @@ QUnit.test("Length: Submit single character.", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     inFn().value = "a";
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -77,7 +77,7 @@ QUnit.test("Length: Submit three characters.", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     inFn().value = "abc";
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -94,7 +94,7 @@ QUnit.test("Length: Submit five characters.", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     inFn().value = "abcde";
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/08-form/10-required/Required.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/08-form/10-required/Required.test.js
index c884783..0221f0b 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/08-form/10-required/Required.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/08-form/10-required/Required.test.js
@@ -27,7 +27,7 @@ QUnit.test("submit inner form 1 without violations", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     form1InputFieldFn().value = "Alice";
-    form1SubmitButtonFn().click();
+    form1SubmitButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
@@ -53,7 +53,7 @@ QUnit.test("submit inner form 2, violate required field", function (assert) {
     assert.equal(form2InputFieldFn().value, "");
   });
   TTT.action(function () {
-    form2SubmitButtonFn().click();
+    form2SubmitButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
@@ -78,7 +78,7 @@ QUnit.test("submit inner form 2 without violations", function (assert) {
     assert.equal(form2InputFieldFn().value, "Bob");
   });
   TTT.action(function () {
-    form2SubmitButtonFn().click();
+    form2SubmitButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
@@ -104,7 +104,7 @@ QUnit.test("submit outer form, violate both required fields", function (assert)
   TTT.action(function () {
     form2InputFieldFn().value = "";
     outerFormInputFieldFn().value = "";
-    outerFormSubmitButtonFn().click();
+    outerFormSubmitButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(5, function () {
@@ -132,7 +132,7 @@ QUnit.test("submit outer form, violate required field in form 2", function (asse
   TTT.action(function () {
     form2InputFieldFn().value = "";
     outerFormInputFieldFn().value = "Charlie";
-    outerFormSubmitButtonFn().click();
+    outerFormSubmitButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(5, function () {
@@ -160,7 +160,7 @@ QUnit.test("submit outer form, violate required field in outer form", function (
   TTT.action(function () {
     form2InputFieldFn().value = "Dave";
     outerFormInputFieldFn().value = "";
-    outerFormSubmitButtonFn().click();
+    outerFormSubmitButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(5, function () {
@@ -188,7 +188,7 @@ QUnit.test("submit outer form without violations", function (assert) {
     form1InputFieldFn().value = "Eve";
     form2InputFieldFn().value = "Frank";
     outerFormInputFieldFn().value = "Grace";
-    outerFormSubmitButtonFn().click();
+    outerFormSubmitButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(7, function () {
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/08-form/20-ajax/Ajax.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/08-form/20-ajax/Ajax.test.js
index 308043a..cae9837 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/08-form/20-ajax/Ajax.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/08-form/20-ajax/Ajax.test.js
@@ -27,7 +27,7 @@ QUnit.test("submit inner form 1 without violations", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     form1InputFieldFn().value = "Alice";
-    buttonFn().click();
+    buttonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
@@ -49,7 +49,7 @@ QUnit.test("submit inner form 2, violate required field", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     form2InputFieldFn().value = "";
-    buttonFn().click();
+    buttonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
@@ -69,7 +69,7 @@ QUnit.test("submit inner form 2 without violations", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     form2InputFieldFn().value = "Bob";
-    buttonFn().click();
+    buttonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
@@ -99,7 +99,7 @@ QUnit.test("submit outer form, violate both required fields", function (assert)
     form1InputFieldFn().value = "Charlie";
     form2InputFieldFn().value = "";
     outerFormInputFieldFn().value = "";
-    buttonFn().click();
+    buttonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(7, function () {
@@ -133,7 +133,7 @@ QUnit.test("submit outer form, violate required field in form 2", function (asse
     form1InputFieldFn().value = "Dave";
     form2InputFieldFn().value = "";
     outerFormInputFieldFn().value = "Eve";
-    buttonFn().click();
+    buttonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(7, function () {
@@ -167,7 +167,7 @@ QUnit.test("submit outer form, violate required field in outer form", function (
     form1InputFieldFn().value = "Frank";
     form2InputFieldFn().value = "Grace";
     outerFormInputFieldFn().value = "";
-    buttonFn().click();
+    buttonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(7, function () {
@@ -197,7 +197,7 @@ QUnit.test("submit outer form without violations", function (assert) {
     form1InputFieldFn().value = "Hank";
     form2InputFieldFn().value = "Irene";
     outerFormInputFieldFn().value = "John";
-    buttonFn().click();
+    buttonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(7, function () {
@@ -231,7 +231,7 @@ QUnit.test("submit inner forms, violate required field in form 2", function (ass
     form1InputFieldFn().value = "Kate";
     form2InputFieldFn().value = "";
     outerFormInputFieldFn().value = "Leonard";
-    buttonFn().click();
+    buttonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(7, function () {
@@ -263,7 +263,7 @@ QUnit.test("submit inner forms without violations", function (assert) {
     form1InputFieldFn().value = "Mike";
     form2InputFieldFn().value = "Neil";
     outerFormInputFieldFn().value = "";
-    buttonFn().click();
+    buttonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(7, function () {
@@ -297,7 +297,7 @@ QUnit.test("submit outer value, violate required field", function (assert) {
     form1InputFieldFn().value = "Oscar";
     form2InputFieldFn().value = "Penny";
     outerFormInputFieldFn().value = "";
-    buttonFn().click();
+    buttonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(7, function () {
@@ -330,7 +330,7 @@ QUnit.test("submit outer value without violations", function (assert) {
     form1InputFieldFn().value = "Quin";
     form2InputFieldFn().value = "Sue";
     outerFormInputFieldFn().value = "Ted";
-    buttonFn().click();
+    buttonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(7, function () {
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/08-form/Form.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/08-form/Form.test.js
index 139c006..70af523 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/08-form/Form.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/08-form/Form.test.js
@@ -30,7 +30,7 @@ QUnit.test("submit form 1", function (assert) {
   TTT.action(function () {
     form1InputFieldFn().value = "Oliver";
     form2InputFieldFn().value = "Peter";
-    form1SubmitButtonFn().click();
+    form1SubmitButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(4, function () {
@@ -54,7 +54,7 @@ QUnit.test("submit form 2", function (assert) {
   TTT.action(function () {
     form1InputFieldFn().value = "Oliver";
     form2InputFieldFn().value = "Peter";
-    form2SubmitButtonFn().click();
+    form2SubmitButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(4, function () {
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/51-for-each/For_Each.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/51-for-each/For_Each.test.js
index 1e2ead6..fc6e743 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/51-for-each/For_Each.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/51-for-each/For_Each.test.js
@@ -29,7 +29,7 @@ QUnit.test("Add a river and reset.", function (assert) {
 
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
-    resetFn().click();
+    resetFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(2, function () {
@@ -40,7 +40,7 @@ QUnit.test("Add a river and reset.", function (assert) {
     nameFn().value = "Mississippi";
     lengthFn().value = "6275";
     dischargeFn().value = "16200";
-    addFn().click();
+    addFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(2, function () {
@@ -48,7 +48,7 @@ QUnit.test("Add a river and reset.", function (assert) {
     assert.equal(uiRepeatSectionsFn().length, 4);
   });
   TTT.action(function () {
-    resetFn().click();
+    resetFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(2, function () {
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/00-collapsible-box/Collapsible_Box.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/00-collapsible-box/Collapsible_Box.test.js
index 3fa4388..f6c59fb 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/00-collapsible-box/Collapsible_Box.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/00-collapsible-box/Collapsible_Box.test.js
@@ -25,14 +25,14 @@ QUnit.test("Simple Collapsible Box: show -> hide transition", function (assert)
 
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
-    showFn().click();
+    showFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
     assert.ok(contentFn() !== null);
   });
   TTT.action(function () {
-    hideFn().click();
+    hideFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -48,14 +48,14 @@ QUnit.test("Simple Collapsible Box: hide -> show transition", function (assert)
 
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
-    hideFn().click();
+    hideFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
     assert.equal(contentFn(), null);
   });
   TTT.action(function () {
-    showFn().click();
+    showFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -73,7 +73,7 @@ QUnit.test("Full Server Request: open both boxes", function (assert) {
 
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
-    show1Fn().click();
+    show1Fn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(2, function () {
@@ -81,7 +81,7 @@ QUnit.test("Full Server Request: open both boxes", function (assert) {
     assert.equal(content2Fn().length, content2Length);
   });
   TTT.action(function () {
-    show2Fn().click();
+    show2Fn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(2, function () {
@@ -100,7 +100,7 @@ QUnit.test("Full Server Request: open box 1, close box 2", function (assert) {
 
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
-    show1Fn().click();
+    show1Fn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(2, function () {
@@ -108,7 +108,7 @@ QUnit.test("Full Server Request: open box 1, close box 2", function (assert) {
     assert.equal(content2Fn().length, content2Length);
   });
   TTT.action(function () {
-    hide2Fn().click();
+    hide2Fn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(2, function () {
@@ -127,7 +127,7 @@ QUnit.test("Full Server Request: close box 1, open box 2", function (assert) {
 
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
-    hide1Fn().click();
+    hide1Fn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(2, function () {
@@ -135,7 +135,7 @@ QUnit.test("Full Server Request: close box 1, open box 2", function (assert) {
     assert.equal(content2Fn() !== null, existContent2);
   });
   TTT.action(function () {
-    show2Fn().click();
+    show2Fn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(2, function () {
@@ -154,7 +154,7 @@ QUnit.test("Full Server Request: close both boxes", function (assert) {
 
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
-    hide1Fn().click();
+    hide1Fn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(2, function () {
@@ -162,7 +162,7 @@ QUnit.test("Full Server Request: close both boxes", function (assert) {
     assert.equal(content2Fn() !== null, existContent2);
   });
   TTT.action(function () {
-    hide2Fn().click();
+    hide2Fn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(2, function () {
@@ -179,13 +179,13 @@ QUnit.test("Client Side: show -> hide transition", function (assert) {
 
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
-    showFn().click();
+    showFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.asserts(1, function () {
     assert.equal(boxFn().classList.contains("tobago-collapsed"), false);
   });
   TTT.action(function () {
-    hideFn().click();
+    hideFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.asserts(1, function () {
     assert.equal(boxFn().classList.contains("tobago-collapsed"), true);
@@ -200,13 +200,13 @@ QUnit.test("Client Side: hide -> show transition", function (assert) {
 
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
-    hideFn().click();
+    hideFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.asserts(1, function () {
     assert.equal(boxFn().classList.contains("tobago-collapsed"), true);
   });
   TTT.action(function () {
-    showFn().click();
+    showFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.asserts(1, function () {
     assert.equal(boxFn().classList.contains("tobago-collapsed"), false);
@@ -224,14 +224,14 @@ QUnit.test("Client Side: hide content and submit empty string", function (assert
 
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
-    hideFn().click();
+    hideFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.asserts(1, function () {
     assert.equal(boxFn().classList.contains("tobago-collapsed"), true);
   });
   TTT.action(function () {
     inFn().value = "";
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -247,14 +247,14 @@ QUnit.test("Ajax: show -> hide transition", function (assert) {
 
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
-    showFn().click();
+    showFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
     assert.ok(inFn() !== null);
   });
   TTT.action(function () {
-    hideFn().click();
+    hideFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -270,14 +270,14 @@ QUnit.test("Ajax: hide -> show transition", function (assert) {
 
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
-    hideFn().click();
+    hideFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
     assert.equal(inFn(), null);
   });
   TTT.action(function () {
-    showFn().click();
+    showFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -295,7 +295,7 @@ QUnit.test("Ajax: hide content and submit empty string", function (assert) {
 
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
-    showFn().click();
+    showFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -303,14 +303,14 @@ QUnit.test("Ajax: hide content and submit empty string", function (assert) {
   });
   TTT.action(function () {
     inFn().value = "";
-    hideFn().click();
+    hideFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
     assert.equal(inFn(), null);
   });
   TTT.action(function () {
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/10-collapsible-popup/Collapsible_Popup.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/10-collapsible-popup/Collapsible_Popup.test.js
index e5b3d3c..bf85409 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/10-collapsible-popup/Collapsible_Popup.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/10-collapsible-popup/Collapsible_Popup.test.js
@@ -28,7 +28,7 @@ QUnit.test("Simple Popup", function (assert) {
 
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
-    openFn().click();
+    openFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -36,7 +36,7 @@ QUnit.test("Simple Popup", function (assert) {
   });
   TTT.action(function () {
     inFn().value = "some text";
-    submitOnPopupFn().click();
+    submitOnPopupFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
@@ -46,7 +46,7 @@ QUnit.test("Simple Popup", function (assert) {
   });
   TTT.action(function () {
     inFn().value = "";
-    submitOnPopupFn().click();
+    submitOnPopupFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
@@ -55,14 +55,14 @@ QUnit.test("Simple Popup", function (assert) {
     assert.equal(inFn().value, "");
   });
   TTT.action(function () {
-    closeFn().click();
+    closeFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
     assert.equal(inFn(), null);
   });
   TTT.action(function () {
-    submitOnPageFn().click();
+    submitOnPageFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -81,7 +81,7 @@ QUnit.test("Full Server Request", function (assert) {
 
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
-    openFn().click();
+    openFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -89,7 +89,7 @@ QUnit.test("Full Server Request", function (assert) {
   });
   TTT.action(function () {
     inFn().value = "some text";
-    submitOnPopupFn().click();
+    submitOnPopupFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
@@ -99,7 +99,7 @@ QUnit.test("Full Server Request", function (assert) {
   });
   TTT.action(function () {
     inFn().value = "";
-    submitOnPopupFn().click();
+    submitOnPopupFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
@@ -108,14 +108,14 @@ QUnit.test("Full Server Request", function (assert) {
     assert.equal(inFn().value, "");
   });
   TTT.action(function () {
-    closeFn().click();
+    closeFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
     assert.equal(inFn(), null);
   });
   TTT.action(function () {
-    submitOnPageFn().click();
+    submitOnPageFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -135,26 +135,26 @@ QUnit.test("Client Side", function (assert) {
 
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
-    openFn().click();
+    openFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.asserts(1, function () {
     assert.equal(popupCollapsedFn().value, "false");
   });
   TTT.action(function () {
-    closeFn().click();
+    closeFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.asserts(1, function () {
     assert.equal(popupCollapsedFn().value, "true");
   });
   TTT.action(function () {
-    openFn().click();
+    openFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.asserts(1, function () {
     assert.equal(popupCollapsedFn().value, "false");
   });
   TTT.action(function () {
     inFn().value = "some text";
-    submitOnPopupFn().click();
+    submitOnPopupFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(2, function () {
@@ -162,14 +162,14 @@ QUnit.test("Client Side", function (assert) {
     assert.equal(popupCollapsedFn().value, "true");
   });
   TTT.action(function () {
-    openFn().click();
+    openFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.asserts(1, function () {
     assert.equal(popupCollapsedFn().value, "false");
   });
   TTT.action(function () {
     inFn().value = "";
-    submitOnPopupFn().click();
+    submitOnPopupFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(2, function () {
@@ -177,7 +177,7 @@ QUnit.test("Client Side", function (assert) {
     assert.equal(popupCollapsedFn().value, "true");
   });
   TTT.action(function () {
-    submitOnPageFn().click();
+    submitOnPageFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/20-collapsible-panel/Collapsible_Panel.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/20-collapsible-panel/Collapsible_Panel.test.js
index cdd3275..b5d2d57 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/20-collapsible-panel/Collapsible_Panel.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/20-collapsible-panel/Collapsible_Panel.test.js
@@ -28,7 +28,7 @@ QUnit.test("Simple Panel", function (assert) {
 
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
-    showFn().click();
+    showFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(2, function () {
@@ -37,7 +37,7 @@ QUnit.test("Simple Panel", function (assert) {
   });
   TTT.action(function () {
     inFn().value = "some text";
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
@@ -47,7 +47,7 @@ QUnit.test("Simple Panel", function (assert) {
   });
   TTT.action(function () {
     inFn().value = "";
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
@@ -56,7 +56,7 @@ QUnit.test("Simple Panel", function (assert) {
     assert.ok(inFn() !== null);
   });
   TTT.action(function () {
-    hideFn().click();
+    hideFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
@@ -65,7 +65,7 @@ QUnit.test("Simple Panel", function (assert) {
     assert.equal(inFn(), null);
   });
   TTT.action(function () {
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
@@ -86,7 +86,7 @@ QUnit.test("Full Server Request", function (assert) {
 
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
-    showFn().click();
+    showFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(2, function () {
@@ -95,7 +95,7 @@ QUnit.test("Full Server Request", function (assert) {
   });
   TTT.action(function () {
     inFn().value = "some text";
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
@@ -105,7 +105,7 @@ QUnit.test("Full Server Request", function (assert) {
   });
   TTT.action(function () {
     inFn().value = "";
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
@@ -114,7 +114,7 @@ QUnit.test("Full Server Request", function (assert) {
     assert.ok(inFn() !== null);
   });
   TTT.action(function () {
-    hideFn().click();
+    hideFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
@@ -123,7 +123,7 @@ QUnit.test("Full Server Request", function (assert) {
     assert.equal(inFn(), null);
   });
   TTT.action(function () {
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
@@ -144,7 +144,7 @@ QUnit.test("Client Side", function (assert) {
 
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
-    showFn().click();
+    showFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.asserts(2, function () {
     assert.equal(panelCollapsedFn().value, "false");
@@ -152,7 +152,7 @@ QUnit.test("Client Side", function (assert) {
   });
   TTT.action(function () {
     inFn().value = "some text";
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
@@ -162,7 +162,7 @@ QUnit.test("Client Side", function (assert) {
   });
   TTT.action(function () {
     inFn().value = "";
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
@@ -171,7 +171,7 @@ QUnit.test("Client Side", function (assert) {
     assert.ok(inFn() !== null);
   });
   TTT.action(function () {
-    hideFn().click();
+    hideFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.asserts(3, function () {
     assert.equal(messagesFn().length, 1);
@@ -179,7 +179,7 @@ QUnit.test("Client Side", function (assert) {
     assert.ok(inFn() !== null);
   });
   TTT.action(function () {
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
@@ -200,7 +200,7 @@ QUnit.test("Ajax", function (assert) {
 
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
-    showFn().click();
+    showFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(2, function () {
@@ -209,7 +209,7 @@ QUnit.test("Ajax", function (assert) {
   });
   TTT.action(function () {
     inFn().value = "some text";
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
@@ -219,7 +219,7 @@ QUnit.test("Ajax", function (assert) {
   });
   TTT.action(function () {
     inFn().value = "";
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
@@ -228,7 +228,7 @@ QUnit.test("Ajax", function (assert) {
     assert.ok(inFn() !== null);
   });
   TTT.action(function () {
-    hideFn().click();
+    hideFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(2, function () {
@@ -236,7 +236,7 @@ QUnit.test("Ajax", function (assert) {
     assert.equal(inFn(), null);
   });
   TTT.action(function () {
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/30-collapsible-section/Collapsible_Section.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/30-collapsible-section/Collapsible_Section.test.js
index 629f67f..8682f1f 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/30-collapsible-section/Collapsible_Section.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/30-collapsible-section/Collapsible_Section.test.js
@@ -28,7 +28,7 @@ QUnit.test("Simple Panel", function (assert) {
 
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
-    showFn().click();
+    showFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(2, function () {
@@ -37,7 +37,7 @@ QUnit.test("Simple Panel", function (assert) {
   });
   TTT.action(function () {
     inFn().value = "some text";
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
@@ -47,7 +47,7 @@ QUnit.test("Simple Panel", function (assert) {
   });
   TTT.action(function () {
     inFn().value = "";
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
@@ -56,7 +56,7 @@ QUnit.test("Simple Panel", function (assert) {
     assert.ok(inFn() !== null);
   });
   TTT.action(function () {
-    hideFn().click();
+    hideFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
@@ -65,7 +65,7 @@ QUnit.test("Simple Panel", function (assert) {
     assert.equal(inFn(), null);
   });
   TTT.action(function () {
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
@@ -86,7 +86,7 @@ QUnit.test("Full Server Request", function (assert) {
 
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
-    showFn().click();
+    showFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(2, function () {
@@ -95,7 +95,7 @@ QUnit.test("Full Server Request", function (assert) {
   });
   TTT.action(function () {
     inFn().value = "some text";
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
@@ -105,7 +105,7 @@ QUnit.test("Full Server Request", function (assert) {
   });
   TTT.action(function () {
     inFn().value = "";
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
@@ -114,7 +114,7 @@ QUnit.test("Full Server Request", function (assert) {
     assert.ok(inFn() !== null);
   });
   TTT.action(function () {
-    hideFn().click();
+    hideFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
@@ -123,7 +123,7 @@ QUnit.test("Full Server Request", function (assert) {
     assert.equal(inFn(), null);
   });
   TTT.action(function () {
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
@@ -144,7 +144,7 @@ QUnit.test("Client Side", function (assert) {
 
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
-    showFn().click();
+    showFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.asserts(2, function () {
     assert.equal(sectionCollapsedFn().value, "false");
@@ -152,7 +152,7 @@ QUnit.test("Client Side", function (assert) {
   });
   TTT.action(function () {
     inFn().value = "some text";
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
@@ -162,7 +162,7 @@ QUnit.test("Client Side", function (assert) {
   });
   TTT.action(function () {
     inFn().value = "";
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
@@ -171,7 +171,7 @@ QUnit.test("Client Side", function (assert) {
     assert.ok(inFn() !== null);
   });
   TTT.action(function () {
-    hideFn().click();
+    hideFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.asserts(3, function () {
     assert.equal(messagesFn().length, 1);
@@ -179,7 +179,7 @@ QUnit.test("Client Side", function (assert) {
     assert.ok(inFn() !== null);
   });
   TTT.action(function () {
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
@@ -200,7 +200,7 @@ QUnit.test("Ajax", function (assert) {
 
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
-    showFn().click();
+    showFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(2, function () {
@@ -209,7 +209,7 @@ QUnit.test("Ajax", function (assert) {
   });
   TTT.action(function () {
     inFn().value = "some text";
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
@@ -219,7 +219,7 @@ QUnit.test("Ajax", function (assert) {
   });
   TTT.action(function () {
     inFn().value = "";
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
@@ -228,7 +228,7 @@ QUnit.test("Ajax", function (assert) {
     assert.ok(inFn() !== null);
   });
   TTT.action(function () {
-    hideFn().click();
+    hideFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(2, function () {
@@ -236,7 +236,7 @@ QUnit.test("Ajax", function (assert) {
     assert.equal(inFn(), null);
   });
   TTT.action(function () {
-    submitFn().click();
+    submitFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/75-resize/Resize.xhtml b/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/75-resize/Resize.xhtml
index d8471f8..b4d9b4c 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/75-resize/Resize.xhtml
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/75-resize/Resize.xhtml
@@ -27,10 +27,19 @@
     <tc:link id="resize" action="#{resizeController.resize}"/>
   </f:facet>
 
-  <!--todo-->
-  Todo: make nicer example
-  <br/>
+  <tc:panel>
+    <tc:event event="click" action="#{resizeController.resize}">
+      <f:ajax/>
+    </tc:event>
 
-  Resizing demo. Resizing the window will call a command (from the resize facet).
+    Please to a resize of the browser window and look in the server logs to check the resize actions...
+    <br/>
+
+    <!--todo-->
+    Todo: make nicer example
+    <br/>
+
+    Resizing demo. Resizing the window will call a command (from the resize facet).
+  </tc:panel>
 
 </ui:composition>
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/35-deprecated/15-suggest-method/Suggest_Method.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/35-deprecated/15-suggest-method/Suggest_Method.test.js
index 69baf98..c3d87da 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/35-deprecated/15-suggest-method/Suggest_Method.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/35-deprecated/15-suggest-method/Suggest_Method.test.js
@@ -28,7 +28,7 @@ QUnit.test("Deprecated: 'Ma'", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     inFn().value = inputString;
-    inFn().dispatchEvent(new Event('input'));
+    inFn().dispatchEvent(new Event("input", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(expectedLength + 1, function () {
@@ -50,7 +50,7 @@ QUnit.test("Replacement: 'Ma'", function (assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     inFn().value = inputString;
-    inFn().dispatchEvent(new Event('input'));
+    inFn().dispatchEvent(new Event("input", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(expectedLength + 1, function () {
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/1020-suggest-quotMark/Suggest_QuotMark.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/1020-suggest-quotMark/Suggest_QuotMark.test.js
index eab97ce..2cfeae4 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/1020-suggest-quotMark/Suggest_QuotMark.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/1020-suggest-quotMark/Suggest_QuotMark.test.js
@@ -53,7 +53,7 @@ function testMarsBasics(assert, inputString, expectedLength) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
     inFn().value = inputString;
-    inFn().dispatchEvent(new Event('input'));
+    inFn().dispatchEvent(new Event("input", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(expectedLength + 1, function () {
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/1040-date/Date.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/1040-date/Date.test.js
index 209081a..dd0f42a 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/1040-date/Date.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/1040-date/Date.test.js
@@ -26,7 +26,7 @@ QUnit.test("inputfield with label", function (assert) {
   let datepickerFn = testFrameQuerySelectorAllFn(".bootstrap-datetimepicker-widget");
   assert.notOk(datepickerFn().item(0));
 
-  dateButtonFn().click();
+  dateButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
 
   datepickerFn = testFrameQuerySelectorAllFn(".bootstrap-datetimepicker-widget");
   assert.ok(datepickerFn().item(0));
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/1041-date-tobagoConverter/Date_TobagoConverter.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/1041-date-tobagoConverter/Date_TobagoConverter.test.js
index 856aac8..d3907d8 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/1041-date-tobagoConverter/Date_TobagoConverter.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/1041-date-tobagoConverter/Date_TobagoConverter.test.js
@@ -220,7 +220,7 @@ function testConvertDateTime(assert, inputFn, datepickerButtonFn, outputFn,
   });
   TTT.action(function () {
         inputFn().value = inputValue;
-        submitButtonFn().click();
+        submitButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
       }
   );
   TTT.waitForResponse();
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/4000-button-link/4050-ajax-dropdown/Ajax_Dropdown.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/4000-button-link/4050-ajax-dropdown/Ajax_Dropdown.test.js
index fa01e57..bf4502f 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/4000-button-link/4050-ajax-dropdown/Ajax_Dropdown.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/4000-button-link/4050-ajax-dropdown/Ajax_Dropdown.test.js
@@ -31,7 +31,7 @@ QUnit.test("Execute 'AJAX' entry in dropdown menu", function (assert) {
     assert.ok(tobagoPageMenuStoreFn().querySelector(ajaxEntryId) === null, "Dropdown menu should be closed.");
   });
   TTT.action(function () {
-    dropdownMenuButtonFn().click();
+    dropdownMenuButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.asserts(1, function () {
     assert.ok(tobagoPageMenuStoreFn().querySelector(ajaxEntryId) !== null, "Dropdown menu should be opened.");
@@ -43,7 +43,7 @@ QUnit.test("Execute 'AJAX' entry in dropdown menu", function (assert) {
     assert.equal(outputFn().textContent, "", "Output should be empty.");
   });
   TTT.action(function () {
-    ajaxEntryFn().click();
+    ajaxEntryFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(2, function () {
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/4000-button-link/Button_Link.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/4000-button-link/Button_Link.test.js
index 3dedd25..356946d 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/4000-button-link/Button_Link.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/4000-button-link/Button_Link.test.js
@@ -47,14 +47,14 @@ function testStandardCommands(commandFn, destinationSectionFn, assert) {
 
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
-    commandFn().click();
+    commandFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
     assert.ok(destinationSectionFn() !== null);
   });
   TTT.action(function () {
-    backFn().click();
+    backFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -98,7 +98,7 @@ QUnit.test("Style must not be a dropdown item", function (assert) {
 function testTargetCommands(commandFn, expectedText, assert) {
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
-    commandFn().click();
+    commandFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitMs(2000); //TobagoTestTools.waitForResponse() didn't recognize responses on a target frame, so we just wait
   TTT.asserts(1, function () {
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/40000-style/100-headings/Headings.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/40000-style/100-headings/Headings.test.js
index 3fd6803..b572d5a 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/40000-style/100-headings/Headings.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/40000-style/100-headings/Headings.test.js
@@ -83,7 +83,7 @@ QUnit.test("Ajax reload for section 2", function (assert) {
     assert.ok(section2HeaderFn() !== null);
   });
   TTT.action(function () {
-    reloadButtonFn().click();
+    reloadButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(2, function () {
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/4600-gridLayout/90-style-tag/Style_Tag.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/4600-gridLayout/90-style-tag/Style_Tag.test.js
index 361a35a..1dbdd57 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/4600-gridLayout/90-style-tag/Style_Tag.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/4600-gridLayout/90-style-tag/Style_Tag.test.js
@@ -27,7 +27,7 @@ QUnit.test("Style tag inside grid layout", function (assert) {
     assert.ok(outputFn().classList.contains("text-warning"));
   });
   TTT.action(function () {
-    buttonFn().click();
+    buttonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/4950-severity/Severity.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/4950-severity/Severity.test.js
index 5e9409e..68443fa 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/4950-severity/Severity.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/4950-severity/Severity.test.js
@@ -31,7 +31,7 @@ QUnit.test("Check severity CSS classes", function (assert) {
 
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
-    submitButtonFn().click();
+    submitButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(8, function () {
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/50000-java/20-ajax-execute/Ajax_Execute.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/50000-java/20-ajax-execute/Ajax_Execute.test.js
index 9178dab..c3245fc 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/50000-java/20-ajax-execute/Ajax_Execute.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/50000-java/20-ajax-execute/Ajax_Execute.test.js
@@ -33,7 +33,7 @@ QUnit.test("ajax excecute", function (assert) {
     in2Fn().value = "b";
     in3Fn().value = "c";
     in4Fn().value = "d";
-    clearButtonFn().click();
+    clearButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(4, function () {
@@ -47,7 +47,7 @@ QUnit.test("ajax excecute", function (assert) {
     in2Fn().value = "b";
     in3Fn().value = "c";
     in4Fn().value = "d";
-    submitButtonFn().click();
+    submitButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(4, function () {
@@ -57,7 +57,7 @@ QUnit.test("ajax excecute", function (assert) {
     assert.equal(in4Fn().value, "");
   });
   TTT.action(function () {
-    reloadButtonFn().click();
+    reloadButtonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(4, function () {
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/50000-java/30-ajax-special-character/Ajax_Special_Character.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/50000-java/30-ajax-special-character/Ajax_Special_Character.test.js
index a02891d..227248c 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/50000-java/30-ajax-special-character/Ajax_Special_Character.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/50000-java/30-ajax-special-character/Ajax_Special_Character.test.js
@@ -30,7 +30,7 @@ QUnit.test("ajax excecute", function (assert) {
 
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
-    buttonFn().click();
+    buttonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(3, function () {
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/6000-event/Event.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/6000-event/Event.test.js
index afa7a5c..66c9eab 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/6000-event/Event.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/6000-event/Event.test.js
@@ -151,7 +151,7 @@ function activateComponent(componentName, eventName) {
       Array.prototype.forEach.call(buttons, function (element, i) {
         let id = element.getAttribute("id");
         if (id !== undefined && id.indexOf(eventName + "Behavior") >= 0) {
-          element.click();
+          element.dispatchEvent(new Event("click", {bubbles: true}));
         }
       });
     }
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/6500-behavior/Behavior.test.js b/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/6500-behavior/Behavior.test.js
index 56833c4..dfb4c79 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/6500-behavior/Behavior.test.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/6500-behavior/Behavior.test.js
@@ -24,7 +24,7 @@ QUnit.test("Simple Event", function (assert) {
 
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
-    buttonFn().click();
+    buttonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(11, function () {
@@ -39,7 +39,7 @@ QUnit.test("Simple Ajax", function (assert) {
 
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
-    buttonFn().click();
+    buttonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(11, function () {
@@ -54,7 +54,7 @@ QUnit.test("Simple EventAjax", function (assert) {
 
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
-    buttonFn().click();
+    buttonFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(11, function () {
@@ -116,7 +116,7 @@ function testEventOption(assert, optionId, componentFn, eventName,
 
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
-    hideFn().click();
+    hideFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -127,7 +127,7 @@ function testEventOption(assert, optionId, componentFn, eventName,
     optionsFn().item(1).checked = false;
     optionsFn().item(2).checked = false;
     optionsFn().item(optionId).checked = true;
-    optionsFn().item(optionId).dispatchEvent(new Event('change'));
+    optionsFn().item(optionId).dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.action(function () {
@@ -158,7 +158,7 @@ function testAjaxOption(assert, optionId, componentFn, eventName,
 
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
-    hideFn().click();
+    hideFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
@@ -169,7 +169,7 @@ function testAjaxOption(assert, optionId, componentFn, eventName,
     optionsFn().item(1).checked = false;
     optionsFn().item(2).checked = false;
     optionsFn().item(optionId).checked = true;
-    optionsFn().item(optionId).dispatchEvent(new Event('change'));
+    optionsFn().item(optionId).dispatchEvent(new Event("change", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.action(function () {
@@ -194,7 +194,7 @@ function testInputSection(assert, inputFn, eventName) {
 
   let TTT = new TobagoTestTool(assert);
   TTT.action(function () {
-    hideFn().click();
+    hideFn().dispatchEvent(new Event("click", {bubbles: true}));
   });
   TTT.waitForResponse();
   TTT.asserts(1, function () {
diff --git a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-calendar.ts b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-calendar.ts
index b5dfa36..a3d896a 100644
--- a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-calendar.ts
+++ b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-calendar.ts
@@ -17,7 +17,7 @@
 
 import {Listener, Phase} from "./tobago-listener";
 import {DomUtils} from "./tobago-utils";
-import {Command} from "./tobago-command";
+import {CommandHelper} from "./tobago-command";
 
 class DateTime {
 
@@ -169,7 +169,9 @@ class DateTime {
                   render: commands.change.render
                 });
           } else if (commands.change.action) {
-            Command.submitAction(this.firstElementChild, commands.change.action, commands.change);
+            CommandHelper.submitAction(
+                this.firstElementChild as HTMLElement,
+                commands.change.action, commands.change.transition, commands.change.target);
           }
         }
       });
diff --git a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-command.test.ts b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-command.test.ts
deleted file mode 100644
index 7de9ada..0000000
--- a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-command.test.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import {Command, CommandMap} from "./tobago-command";
-
-test('class Command: string', () => {
-  let command = new Command('{"omit":false,"execute":"execute-id"}');
-  expect(command.omit).toBe(false);
-  expect(command.stringify()).toBe('{"omit":false,"execute":"execute-id"}');
-});
-
-test('class Command: object', () => {
-  let command = new Command({"omit": false, "execute": "execute-id"});
-  expect(command.omit).toBe(false);
-  expect(command.stringify()).toBe('{"omit":false,"execute":"execute-id"}');
-});
-
-test('class CommandMap: click', () => {
-  let commands = new CommandMap('{"click":{"omit":false}}');
-  expect(commands.stringify()).toBe('{"commands":{"click":{"omit":false}}}');
-});
-
-test('class CommandMap: change', () => {
-  let commands = new CommandMap('{"change":{"action":"page:header:j_id_k"}}');
-  expect(commands.stringify()).toBe('{"commands":{"change":{"action":"page:header:j_id_k"}}}');
-});
diff --git a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-command.ts b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-command.ts
index 94dcca6..409b182 100644
--- a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-command.ts
+++ b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-command.ts
@@ -15,196 +15,232 @@
  * limitations under the License.
  */
 
-import {Listener, Order, Phase} from "./tobago-listener";
+import {Listener, Phase} from "./tobago-listener";
 import {Overlay} from "./tobago-overlay";
 import {DomUtils, Tobago4Utils} from "./tobago-utils";
-import {Collapse, Popup} from "./tobago-popup";
+import {Collapse} from "./tobago-popup";
 import {Setup} from "./tobago-core";
 
-export class CommandMap {
+class Behavior extends HTMLElement {
 
-  commands: Map<string, Command>;
+  constructor() {
+    super();
+  }
 
-  // XXX remove me later... may be, if using "Custom Elements"
-  /** @deprecated */
-  public static getData(element: HTMLElement, eventType: string): Command {
-    const commandMap: CommandMap = new CommandMap(element.dataset["tobagoCommands"]);
-    return commandMap.commands.get(eventType);
+  connectedCallback() {
+    switch (this.event) {
+      case "load": // this is a special case, because the "load" is too late now.
+        this.callback();
+        break;
+      case "resize":
+        document.body.addEventListener(this.event, this.callback.bind(this));
+        break;
+      default:
+        this.parentElement.addEventListener(this.event, this.callback.bind(this));
+    }
   }
 
-  static change(event: TextEvent) {
-    const element = event.currentTarget as HTMLElement;
-    const change = CommandMap.getData(element, "change");
+  callback(event?: Event) {
 
-    if (change.execute || change.render) {
+    if (this.collapseAction && this.collapseTarget) {
+      const target = this.getRootNode() as ShadowRoot | Document;
+      Collapse.execute(this.collapseAction, target.getElementById(this.collapseTarget));
+    }
+
+    if (this.execute || this.render) { // this means: AJAX case?
+      if (this.render) {
+        // prepare overlay for all by AJAX reloaded elements
+        let partialIds = this.render.split(" ");
+        for (let i = 0; i < partialIds.length; i++) {
+          new Overlay(document.getElementById(partialIds[i]), true);
+        }
+      }
       jsf.ajax.request(
-          element.getAttribute("name"),
-          event,
-          {
-            "javax.faces.behavior.event": "change",
-            execute: change.execute,
-            render: change.render
+          this.parentElement,
+          event, {
+            //"javax.faces.behavior.event": this.event,
+            execute: this.execute,
+            render: this.render
           });
     } else {
-      Command.submitAction(this, change.action, change);
+      if (!this.omit) {
+        setTimeout(this.submit.bind(this), this.delay);
+      }
     }
   }
 
-  static resize(event: Event) { // TBD MouseEvent?
-    const element = event.currentTarget as HTMLElement;
-    const resize = CommandMap.getData(element, "resize");
-    console.debug("window resize event: " + resize);
-    Command.submitAction(this, resize.action, resize);
+  submit() {
+    const actionId = this.action != null ? this.action : this.element.id;
+    CommandHelper.submitAction(this, actionId, !this.decoupled, this.target);
   }
 
-  static otherEvent(event: Event) {
-    const element = event.currentTarget as HTMLElement;
-    const command = CommandMap.getData(element, event.type);
+  get event(): string {
+    return this.getAttribute("event");
+  }
 
-    const confirmation = command.confirmation;
-    if (confirmation) {
-      if (!confirm(confirmation)) {
-        event.preventDefault();
-        return;
-      }
-    }
-    const collapse = command.collapse;
-    if (collapse) {
-      Collapse.execute(collapse);
-    }
+  set event(event: string) {
+    this.setAttribute("event", event);
+  }
 
-    if (!command.omit) {
-      const popup = command.popup;
-      if (popup && popup.command === "close" && popup.immediate) {
-        Popup.close(element);
-      } else {
-        const action = command.action ? command.action : element.id;
-        if (command.execute || command.render) {
-          Command.preparePartialOverlay(command);
-          jsf.ajax.request(
-              action,
-              event,
-              {
-                "javax.faces.behavior.event": event.type,
-                execute: command.execute,
-                render: command.render
-              });
-        } else {
-          Command.submitAction(this, action, command);
-        }
-        if (popup && popup.command === "close") {
-          Popup.close(element);
-        }
-      }
-    }
+  get action(): string {
+    return this.getAttribute("action");
+  }
+
+  set action(action: string) {
+    this.setAttribute("action", action);
+  }
+
+  get execute(): string {
+    return this.getAttribute("execute");
+  }
+
+  set execute(execute: string) {
+    this.setAttribute("execute", execute);
   }
 
-  constructor(data: string) {
-    this.commands = new Map<string, Command>();
-    const object = JSON.parse(data);
-    for (let key of Object.keys(object)) {
-      const command5 = new Command(object[key]);
-      this.commands.set(key, command5);
+  get render(): string {
+    return this.getAttribute("render");
+  }
+
+  set render(render: string) {
+    this.setAttribute("render", render);
+  }
+
+  get delay(): number {
+    return parseInt(this.getAttribute("delay")) || 0;
+  }
+
+  set delay(delay: number) {
+    this.setAttribute("delay", String(delay));
+  }
+
+  get omit(): boolean {
+    return this.hasAttribute("omit");
+  }
+
+  set omit(omit: boolean) {
+    if (omit) {
+      this.setAttribute("omit", "");
+    } else {
+      this.removeAttribute("omit");
     }
   }
 
-  get change() {
-    return this.commands.get("change");
+  get target(): string {
+    return this.getAttribute("target");
+  }
+
+  set target(target: string) {
+    this.setAttribute("target", target);
   }
 
-  get complete() {
-    return this.commands.get("complete");
+  get confirmation(): string {
+    return this.getAttribute("confirmation");
   }
 
-  get load() {
-    return this.commands.get("load");
+  set confirmation(confirmation: string) {
+    this.setAttribute("confirmation", confirmation);
   }
 
-  get resize() {
-    return this.commands.get("resize");
+  get collapseAction(): string {
+    return this.getAttribute("collapse-action");
   }
 
-  public stringify(): string {
-    let object = Object.create(null);
-    for (let [k, v] of this.commands) {
-      object[k] = v;
+  set collapseAction(collapseAction: string) {
+    this.setAttribute("collapse-action", collapseAction);
+  }
+
+  get collapseTarget(): string {
+    return this.getAttribute("collapse-target");
+  }
+
+  set collapseTarget(collapseTarget: string) {
+    this.setAttribute("collapse-target", collapseTarget);
+  }
+
+  get decoupled(): boolean {
+    return this.hasAttribute("decoupled");
+  }
+
+  set decoupled(decoupled: boolean) {
+    if (decoupled) {
+      this.setAttribute("decoupled", "");
+    } else {
+      this.removeAttribute("decoupled");
     }
-    const outer = JSON.stringify(this);
-    // remove {} and replace with object-JSON
-    return outer.substring(0, outer.length - 3) + JSON.stringify(object) + "}";
+  }
+
+  get focusId(): string {
+    return this.getAttribute("focus-id");
+  }
+
+  set focusId(focusId: string) {
+    this.setAttribute("focus-id", focusId);
+  }
+
+  get element(): HTMLElement {
+    return this.parentElement;
   }
 }
 
-export class Command {
+document.addEventListener("DOMContentLoaded", function (event) {
+  window.customElements.define('tobago-behavior', Behavior);
+});
 
-  // XXX this is a state of the page
+export class CommandHelper {
   static isSubmit: boolean = false;
 
-  confirmation: string;
-  collapse: boolean; // XXX is boolean okay??? Should this be not an element or a structure?
-  omit: boolean;
-  popup; // todo: type
-  action: string;
-  execute: string;
-  render: string;
-  transition: boolean;
-  delay: number;
-  target: string;
-
   /**
    * Submitting the page with specified actionId.
-   * options.transition
-   * options.target
+   * @param source
+   * @param actionId
+   * @param decoupled
+   * @param target
    */
-  public static submitAction = function (source: any, actionId: string, command: Command = new Command()) {
-
-    let transition = command.transition === undefined || command.transition;
+  public static submitAction = function (source: HTMLElement, actionId: string, decoupled: boolean = true, target?: string) {
 
     Transport.request(function () {
-      if (!Command.isSubmit) {
-        Command.isSubmit = true;
+      if (!CommandHelper.isSubmit) {
+        CommandHelper.isSubmit = true;
         const form = document.getElementsByTagName("form")[0] as HTMLFormElement;
-        var oldTarget = form.getAttribute("target");
+        const oldTarget = form.getAttribute("target");
         const sourceHidden = document.getElementById("javax.faces.source") as HTMLInputElement;
         sourceHidden.disabled = false;
         sourceHidden.value = actionId;
-        if (command.target) {
-          form.setAttribute("target", command.target);
+        if (target) {
+          form.setAttribute("target", target);
         }
-        this.oldTransition = this.transition;
-        this.transition = transition && !command.target;
-
         var listenerOptions = {
           source: source,
-          actionId: actionId,
-          options: command
+          actionId: actionId/*,
+          options: commandHelper*/
         };
-        var onSubmitResult = Command.onSubmit(listenerOptions);
+        var onSubmitResult = CommandHelper.onSubmit(listenerOptions);
         if (onSubmitResult) {
           try {
             form.submit();
-            // reset the source field after submit, to be prepared for possible next AJAX with transition=false
+            // reset the source field after submit, to be prepared for possible next AJAX with decoupled=true
             sourceHidden.disabled = true;
             sourceHidden.value = "";
           } catch (e) {
             Overlay.destroy(DomUtils.page().id);
-            Command.isSubmit = false;
+            CommandHelper.isSubmit = false;
             alert('Submit failed: ' + e); // XXX localization, better error handling
           }
         }
-        if (command.target) {
+        if (target) {
           if (oldTarget) {
             form.setAttribute("target", oldTarget);
           } else {
             form.removeAttribute("target");
           }
         }
-        if (command.target || !transition || !onSubmitResult) {
-          Command.isSubmit = false;
+        if (target || decoupled || !onSubmitResult) {
+          CommandHelper.isSubmit = false;
           Transport.pageSubmitted = false;
         }
       }
-      if (!Command.isSubmit) {
+      if (!CommandHelper.isSubmit) {
         Transport.requestComplete(); // remove this from queue
       }
     }, true);
@@ -243,52 +279,6 @@ export class Command {
     }
   }
 
-  static init = function (element: HTMLElement) {
-
-    for (const commandElement of DomUtils.selfOrQuerySelectorAll(element, "[data-tobago-commands]")) {
-
-      const commandMap = new CommandMap(commandElement.dataset["tobagoCommands"]);
-
-      for (const entry of commandMap.commands.entries()) {
-        const key: string = entry[0];
-        const value: Command = entry[1];
-
-        switch (key) {
-          case "change":
-            commandElement.addEventListener("change", CommandMap.change);
-            break;
-          case "complete":
-            if (parseFloat(commandElement.getAttribute("value")) >= parseFloat(commandElement.getAttribute("max"))) {
-              if (commandMap.complete.execute || commandMap.complete.render) {
-                jsf.ajax.request(
-                    this.id,
-                    null,
-                    {
-                      "javax.faces.behavior.event": "complete",
-                      execute: commandMap.complete.execute,
-                      render: commandMap.complete.render
-                    });
-              } else {
-                Command.submitAction(this, commandMap.complete.action, commandMap.complete);
-              }
-            }
-            break;
-          case "load":
-            setTimeout(function () {
-                  Command.submitAction(this, commandMap.load.action, commandMap.load);
-                },
-                commandMap.load.delay || 100);
-            break;
-          case "resize":
-            window.addEventListener("resize", CommandMap.resize);
-            break;
-          default:
-            commandElement.addEventListener(key, CommandMap.otherEvent);
-        }
-      }
-    }
-  };
-
   static onSubmit = function (listenerOptions) {
     Listener.executeBeforeSubmit();
     /*
@@ -311,48 +301,16 @@ export class Command {
           return false;
         }
     */
-    Command.isSubmit = true;
+    CommandHelper.isSubmit = true;
 
     Setup.onBeforeUnload();
 
     return true;
   };
 
-  static preparePartialOverlay = function (command: Command) {
-    if (command.transition === undefined || command.transition == null || command.transition) {
-      console.debug("[tobago-command] render: '" + command.render + "'");
-      if (command.render) {
-        let partialIds = command.render.split(" ");
-        for (let i = 0; i < partialIds.length; i++) {
-          new Overlay(document.getElementById(partialIds[i]), true);
-        }
-      }
-    }
-  };
-
-  constructor(data?: string | object) {
-    let object;
-    if (data) {
-      if (typeof data === "string") {
-        object = JSON.parse(data);
-      } else {
-        object = data;
-      }
-      for (let key of Object.keys(object)) {
-        this[key] = object[key];
-      }
-    }
-  }
-
-  public stringify(): string {
-    return JSON.stringify(this);
-  }
 }
 
-Listener.register(Command.initEnter, Phase.DOCUMENT_READY);
-
-Listener.register(Command.init, Phase.DOCUMENT_READY, Order.LATER);
-Listener.register(Command.init, Phase.AFTER_UPDATE, Order.LATER);
+Listener.register(CommandHelper.initEnter, Phase.DOCUMENT_READY);
 
 class Transport {
   static requests = [];
diff --git a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-core.ts b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-core.ts
index a81648d..bf5953c 100644
--- a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-core.ts
+++ b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-core.ts
@@ -18,7 +18,7 @@
 import {Listener} from "./tobago-listener";
 import {Overlay} from "./tobago-overlay";
 import {DomUtils} from "./tobago-utils";
-import {Command} from "./tobago-command";
+import {CommandHelper} from "./tobago-command";
 
 /**
  * @deprecated since 5.0.0
@@ -44,7 +44,7 @@ export class Setup {
 
   static init = function() {
     console.time("[tobago] init");
-    document.querySelector("form").addEventListener('submit', Command.onSubmit);
+    document.querySelector("form").addEventListener('submit', CommandHelper.onSubmit);
     window.addEventListener('unload', Setup.onUnload);
     Listener.executeDocumentReady(document.documentElement);
     console.timeEnd("[tobago] init");
@@ -62,7 +62,7 @@ export class Setup {
    */
   static onUnload = function () {
     console.info('on onload');
-    if (Command.isSubmit) {
+    if (CommandHelper.isSubmit) {
       if (Setup.transition) {
         new Overlay(DomUtils.page());
       }
diff --git a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-popup.ts b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-popup.ts
index be593f4..d72f611 100644
--- a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-popup.ts
+++ b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-popup.ts
@@ -53,13 +53,11 @@ export class Collapse {
     return document.getElementById(element.id + "::collapse") as HTMLInputElement;
   }
 
-  static execute = function (collapse) {
-    const transition = collapse.transition;
-    const forElement = document.getElementById(collapse.forId);
-    const hidden = Collapse.findHidden(forElement);
-    const isPopup = forElement.tagName === "TOBAGO-POPUP";
+  static execute = function (action: string, target: HTMLElement) {
+    const hidden = Collapse.findHidden(target);
+    const isPopup = target.tagName === "TOBAGO-POPUP";
     let newCollapsed;
-    switch (transition) {
+    switch (action) {
       case "hide":
         newCollapsed = true;
         break;
@@ -67,19 +65,19 @@ export class Collapse {
         newCollapsed = false;
         break;
       default:
-        console.error("unknown transition: '" + transition + "'");
+        console.error("unknown action: '" + action + "'");
     }
     if (newCollapsed) {
       if (isPopup) {
-        BootstrapUtils.modal(forElement, "hide");
+        BootstrapUtils.modal(target, "hide");
       } else {
-        forElement.classList.add("tobago-collapsed");
+        target.classList.add("tobago-collapsed");
       }
     } else {
       if (isPopup) {
-        BootstrapUtils.modal(forElement, "show");
+        BootstrapUtils.modal(target, "show");
       } else {
-        forElement.classList.remove("tobago-collapsed");
+        target.classList.remove("tobago-collapsed");
       }
     }
     hidden.value = newCollapsed;
diff --git a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-scroll.ts b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-scroll.ts
index 974f68e..9a440f0 100644
--- a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-scroll.ts
+++ b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-scroll.ts
@@ -15,10 +15,8 @@
  * limitations under the License.
  */
 
-import {Listener, Phase, Order} from "./tobago-listener";
-import {Overlay} from "./tobago-overlay";
-import {DomUtils, Tobago4Utils} from "./tobago-utils";
-import {Command} from "./tobago-command";
+import {Listener, Order, Phase} from "./tobago-listener";
+import {DomUtils} from "./tobago-utils";
 
 class Scroll {
 
diff --git a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-sheet.ts b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-sheet.ts
index 6a252b8..2ed1b61 100644
--- a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-sheet.ts
+++ b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-sheet.ts
@@ -17,7 +17,7 @@
 
 import {Listener, Phase} from "./tobago-listener";
 import {DomUtils} from "./tobago-utils";
-import {Command} from "./tobago-command";
+import {CommandHelper} from "./tobago-command";
 
 class Sheet {
 
@@ -436,7 +436,7 @@ class Sheet {
                 render: clickRenderIds
               });
         } else {
-          Command.submitAction(row, action);
+          CommandHelper.submitAction(row, action);
         }
       }
     }
@@ -536,7 +536,7 @@ class Sheet {
               render: this.dblClickReloadComponentId
             });
       } else {
-        Command.submitAction(row, action);
+        CommandHelper.submitAction(row, action);
       }
     }
   }
diff --git a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-tab.ts b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-tab.ts
index 47a1606..8a164b2 100644
--- a/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-tab.ts
+++ b/tobago-theme/tobago-theme-standard/src/main/npm/ts/tobago-tab.ts
@@ -15,8 +15,6 @@
  * limitations under the License.
  */
 
-import {Command} from "./tobago-command";
-
 class TabGroup extends HTMLElement {
 
   private hiddenInput: HTMLInputElement;
@@ -88,16 +86,10 @@ export class Tab extends HTMLElement {
         this.content.classList.add("active");
         break;
       case "reloadTab":
-        jsf.ajax.request(
-            this.navLink,
-            event, {
-              //"javax.faces.behavior.event": "click",
-              execute: tabGroup.id,
-              render: tabGroup.id
-            });
+        // will be done by <tobago-behavior>
         break;
       case "reloadPage":
-        Command.submitAction(this.navLink, this.id);
+        // will be done by <tobago-behavior>
         break;
       case "none": // todo
         console.error("Not implemented yet: %s", tabGroup.switchType);