You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by hn...@apache.org on 2026/05/27 09:35:11 UTC

(myfaces-tobago) branch main updated (162398a846 -> 797e680718)

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

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


    from 162398a846 build(theme): rebuild
     new d895970487 build: skip linter and tests for "dev-ts"
     new 797e680718 fix(ajax queue): not connected to DOM

The 2 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:
 tobago-theme/package.json                          |   2 +-
 .../src/main/ts/tobago-ajax-queue-static.test.ts   | 106 +++++++++++++++++++++
 .../src/main/ts/tobago-ajax-queue-static.ts        |  12 ++-
 .../src/main/ts/tobago-ajax-queue.ts               |   1 +
 4 files changed, 117 insertions(+), 4 deletions(-)


(myfaces-tobago) 02/02: fix(ajax queue): not connected to DOM

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

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

commit 797e6807188ac6ca98039b16e1dbd2e154d02371
Author: Henning Noeth <hn...@apache.org>
AuthorDate: Wed May 27 10:11:40 2026 +0200

    fix(ajax queue): not connected to DOM
    
    Ignore queued elements which are not connected to the DOM.
    
    Fix test: begin every test with a clean <body> element.
    
    Issue: TOBAGO-2521
---
 .../src/main/ts/tobago-ajax-queue-static.test.ts   | 106 +++++++++++++++++++++
 .../src/main/ts/tobago-ajax-queue-static.ts        |  12 ++-
 .../src/main/ts/tobago-ajax-queue.ts               |   1 +
 3 files changed, 116 insertions(+), 3 deletions(-)

diff --git a/tobago-theme/tobago-theme-standard/src/main/ts/tobago-ajax-queue-static.test.ts b/tobago-theme/tobago-theme-standard/src/main/ts/tobago-ajax-queue-static.test.ts
index 259803f217..8b43081456 100644
--- a/tobago-theme/tobago-theme-standard/src/main/ts/tobago-ajax-queue-static.test.ts
+++ b/tobago-theme/tobago-theme-standard/src/main/ts/tobago-ajax-queue-static.test.ts
@@ -21,6 +21,7 @@ import {QueueItem} from "./tobago-ajax-queue";
 test("Press button 1, 2, 3, 2, 1; than the queue is processed", () => {
   const queue: QueueItem[] = [];
 
+  document.querySelector("body").replaceChildren(); //fresh body
   document.querySelector("body").insertAdjacentHTML("afterbegin", `
 <BUTTON id="b1"/>
 <BUTTON id="b2"/>
@@ -152,6 +153,7 @@ test("Press button 1, 2, 3, 2, 1; than the queue is processed", () => {
 });
 
 test("getExecuteValues()", () => {
+  document.querySelector("body").replaceChildren(); //fresh body
   document.querySelector("body").insertAdjacentHTML("afterbegin", `
 <tobago-in id="page:mainForm:tcIn" class="tobago-auto-spacing">
   <input type="text" name="page:mainForm:tcIn" id="page:mainForm:tcIn::field" value="tc:in" class="form-control">
@@ -262,6 +264,7 @@ test("Input field: type 'h', 'i', delete 'i'", () => {
   let expectQueue: QueueItem[] = [];
   const dummyFunction = () => console.log("dummy function");
 
+  document.querySelector("body").replaceChildren(); //fresh body
   document.querySelector("body").insertAdjacentHTML("afterbegin", `
 <tobago-in id="page:mainForm:inputAjax" class="tobago-label-container tobago-auto-spacing">
   <label for="page:mainForm:inputAjax::field" class="col-form-label">Input</label>
@@ -327,6 +330,7 @@ test("Input field: type 'h', 'i', delete 'i'", () => {
 test("SelectManyList server side filtering; click, search for 'hea', click 'Rhea'", () => {
   const queue: QueueItem[] = [];
 
+  document.querySelector("body").replaceChildren(); //fresh body
   document.querySelector("body").insertAdjacentHTML("afterbegin", `
 <tobago-select-many-list id="page:mainForm:selectManyList" class="tobago-label-container tobago-auto-spacing tobago-focus">
   <label for="page:mainForm:selectManyList::field" class="col-form-label">selectManyList</label>
@@ -598,6 +602,7 @@ test("Dblclick on a button with f:ajax for click and dblclick", () => {
   const queue: QueueItem[] = [];
   let expectQueue: QueueItem[] = [];
 
+  document.querySelector("body").replaceChildren(); //fresh body
   document.querySelector("body").insertAdjacentHTML("afterbegin", `
 <BUTTON id="button">
   <tobago-behavior event="click" client-id="button" execute="button"></tobago-behavior>
@@ -631,3 +636,104 @@ test("Dblclick on a button with f:ajax for click and dblclick", () => {
   });
   expect(queue).toEqual(expectQueue);
 });
+
+test("Ignore and remove unconnected queue item", () => {
+  const queue: QueueItem[] = [];
+
+  document.querySelector("body").replaceChildren(); //fresh body
+  const domWrapperElement = `
+<tobago-panel id="wrapper">
+  <button type="button" id="button">
+    <tobago-behavior event="focus" client-id="button" execute="button" render="wrapper"></tobago-behavior>
+    <tobago-behavior event="click" client-id="button" execute="button" render="wrapper"></tobago-behavior>
+    <tobago-behavior event="dblclick" client-id="button" execute="button" render="wrapper"></tobago-behavior>
+    <span>multiple ajax</span>
+  </button>
+</tobago-panel>
+`;
+  document.querySelector("body").insertAdjacentHTML("afterbegin", domWrapperElement);
+
+  const button = document.getElementById("button");
+  const focusFunction = () => console.log("faces.ajax.request focus event");
+  const clickFunction = () => console.log("faces.ajax.request click event");
+  const dblclickFunction = () => console.log("faces.ajax.request dblclick event");
+
+  //click 4 times on the button (fast).
+  AjaxQueueStatic.request(queue, button, new Event("focus"), {render: "wrapper"}, focusFunction);
+  const renderIds = new Set<string>();
+  renderIds.add("wrapper");
+  let expectQueue: QueueItem[] = [];
+  expectQueue.push({
+    element: button,
+    event: new Event("focus"),
+    executeValues: [],
+    renderIds: renderIds,
+    func: focusFunction,
+    inProgress: true
+  });
+  expect(queue).toEqual(expectQueue);
+
+  AjaxQueueStatic.request(queue, button, new Event("click"), {render: "wrapper"}, clickFunction);
+  expectQueue.push({
+    element: button,
+    event: new Event("click"),
+    executeValues: [],
+    renderIds: renderIds,
+    func: clickFunction,
+    inProgress: false
+  });
+  expect(queue).toEqual(expectQueue);
+
+  AjaxQueueStatic.request(queue, button, new Event("dblclick"), {render: "wrapper"}, dblclickFunction);
+  expectQueue.push({
+    element: button,
+    event: new Event("dblclick"),
+    executeValues: [],
+    renderIds: renderIds,
+    func: dblclickFunction,
+    inProgress: false
+  });
+  expect(queue).toEqual(expectQueue);
+
+  AjaxQueueStatic.request(queue, button, new Event("click"), {render: "wrapper"}, clickFunction);
+  expectQueue = [];
+  expectQueue.push({
+    element: button,
+    event: new Event("focus"),
+    executeValues: [],
+    renderIds: renderIds,
+    func: focusFunction,
+    inProgress: true
+  });
+  expectQueue.push({
+    element: button,
+    event: new Event("dblclick"),
+    executeValues: [],
+    renderIds: renderIds,
+    func: dblclickFunction,
+    inProgress: false
+  });
+  expectQueue.push({
+    element: button,
+    event: new Event("click"),
+    executeValues: [],
+    renderIds: renderIds,
+    func: clickFunction,
+    inProgress: false
+  });
+  expect(queue).toEqual(expectQueue);
+
+  AjaxQueueStatic.ajaxEventListener(queue, button, "event", "begin");
+  expect(queue).toEqual(expectQueue);
+
+  AjaxQueueStatic.ajaxEventListener(queue, button, "event", "complete");
+  expect(queue).toEqual(expectQueue);
+
+  // After the focus Ajax request is done, the elements in the queue are no longer connected to the DOM.
+  document.querySelector("#wrapper").remove();
+  document.querySelector("body").insertAdjacentHTML("afterbegin", domWrapperElement);
+  AjaxQueueStatic.ajaxEventListener(queue, button, "event", "success");
+
+  expectQueue = [];
+  expect(queue).toEqual(expectQueue);
+});
diff --git a/tobago-theme/tobago-theme-standard/src/main/ts/tobago-ajax-queue-static.ts b/tobago-theme/tobago-theme-standard/src/main/ts/tobago-ajax-queue-static.ts
index e4cf3afa9c..65e3ecb043 100644
--- a/tobago-theme/tobago-theme-standard/src/main/ts/tobago-ajax-queue-static.ts
+++ b/tobago-theme/tobago-theme-standard/src/main/ts/tobago-ajax-queue-static.ts
@@ -124,9 +124,15 @@ export class AjaxQueueStatic {
   }
 
   static processQueue(queue: QueueItem[]): void {
-    if (queue.length > 0 && !queue[0].inProgress) {
-      queue[0].inProgress = true;
-      queue[0].func();
+    if (queue.length > 0) {
+      const item0 = queue[0];
+      if (!item0.element.isConnected) {
+        queue.shift();
+        this.processQueue(queue);
+      } else if (!item0.inProgress) {
+        queue[0].inProgress = true;
+        queue[0].func();
+      }
     }
   }
 
diff --git a/tobago-theme/tobago-theme-standard/src/main/ts/tobago-ajax-queue.ts b/tobago-theme/tobago-theme-standard/src/main/ts/tobago-ajax-queue.ts
index c464c9f05f..e5258fe0af 100644
--- a/tobago-theme/tobago-theme-standard/src/main/ts/tobago-ajax-queue.ts
+++ b/tobago-theme/tobago-theme-standard/src/main/ts/tobago-ajax-queue.ts
@@ -34,6 +34,7 @@ export interface QueueItem {
  * - A new request is ignored if the exact same request (based on element/event.type/executeValues/renderIds) is
  *   currently in progress.
  * - A new request replaces a queued request (based on element/event.type) and is moved to the end of the queue.
+ * - A queued request will be removed if the element is not connected to the DOM.
  */
 export class AjaxQueue {
   private queue: QueueItem[] = [];


(myfaces-tobago) 01/02: build: skip linter and tests for "dev-ts"

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

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

commit d895970487a048d7853a2e2f49804b2f5b44c7d2
Author: Henning Noeth <hn...@apache.org>
AuthorDate: Wed May 27 08:55:35 2026 +0200

    build: skip linter and tests for "dev-ts"
---
 tobago-theme/package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tobago-theme/package.json b/tobago-theme/package.json
index 44a0fc4e3b..1222ace70d 100644
--- a/tobago-theme/package.json
+++ b/tobago-theme/package.json
@@ -65,7 +65,7 @@
     "dev-css-cp": "npm-run-all --parallel dev-css-cp-*",
     "dev-css-cp-standard": "ncp tobago-theme-standard/src/main/css ../tobago-example/tobago-example-demo/target/tobago-theme-standard/META-INF/resources/tobago/standard/${npm_package_version}/css",
     "dev-css-cp-charlotteville": "ncp tobago-theme-charlotteville/src/main/css ../tobago-example/tobago-example-demo/target/tobago-theme-charlotteville/META-INF/resources/tobago/charlotteville/${npm_package_version}/css",
-    "dev-ts": "npm-run-all ts dev-ts-cp",
+    "dev-ts": "npm-run-all rollup dev-ts-cp",
     "dev-ts-cp": "ncp tobago-theme-standard/src/main/js ../tobago-example/tobago-example-demo/target/tobago-theme-standard/META-INF/resources/tobago/standard/${npm_package_version}/js"
   },
   "dependencies": {