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

lukaszlenart pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/struts.git

commit aee029a6c7b560bd04139bf46c010dcfe7e9ce33
Author: Emil Huseynov <[email protected]>
AuthorDate: Sun Nov 1 11:04:43 2026 +0400

    WW-5774 Address review: html5 fixture, RadioNodeList, guard the script
    
    - combobox.js: when form.elements[target] is a RadioNodeList (two controls
      share the name) resolve the first text input rather than assigning value
      to the list, which would not reach the field.
    - Add testHtml5ThemeRendersDataAttributes with a ComboBox-5 html5-theme
      fixture pinning data-struts-combobox-target / -header-key / -empty-option,
      which the xhtml->simple fixtures never exercised.
    - Move the combobox.js include inside the list?? guard, right before the
      select, so a listless combobox emits no stray script; fixtures 1-4 updated
      for the new position.
    - Rename testJsCallNamingUsesEscapedId(_clearTagStateSet) to
      testDataAttributeUsesEscapedId; the escaped id now lands in the
      data-struts-combobox attribute, not a JS call name.
---
 .../org/apache/struts2/static/combobox.js          | 12 ++++++++
 .../src/main/resources/template/html5/combobox.ftl |  2 +-
 .../main/resources/template/simple/combobox.ftl    |  2 +-
 .../apache/struts2/views/jsp/ui/ComboBoxTest.java  | 33 ++++++++++++++++++++--
 .../org/apache/struts2/views/jsp/ui/ComboBox-1.txt |  2 +-
 .../org/apache/struts2/views/jsp/ui/ComboBox-2.txt |  2 +-
 .../org/apache/struts2/views/jsp/ui/ComboBox-3.txt |  2 +-
 .../org/apache/struts2/views/jsp/ui/ComboBox-4.txt |  2 +-
 .../jsp/ui/{ComboBox-2.txt => ComboBox-5.txt}      | 13 ++-------
 9 files changed, 52 insertions(+), 18 deletions(-)

diff --git a/core/src/main/resources/org/apache/struts2/static/combobox.js 
b/core/src/main/resources/org/apache/struts2/static/combobox.js
index 94a570fda..e32a53797 100644
--- a/core/src/main/resources/org/apache/struts2/static/combobox.js
+++ b/core/src/main/resources/org/apache/struts2/static/combobox.js
@@ -49,6 +49,18 @@
             return;
         }
         var field = select.form.elements[target];
+        if (field && typeof field.length === 'number' && field.tagName === 
undefined) {
+            // Two controls in the form share the name, so elements[target] is 
a RadioNodeList rather than the
+            // text field; assigning value to it would not reach the input. 
Resolve the first text input in it.
+            var resolved = null;
+            for (var i = 0; i < field.length; i++) {
+                if (field[i].tagName === 'INPUT') {
+                    resolved = field[i];
+                    break;
+                }
+            }
+            field = resolved;
+        }
         if (field) {
             field.value = value;
         }
diff --git a/core/src/main/resources/template/html5/combobox.ftl 
b/core/src/main/resources/template/html5/combobox.ftl
index 9f5c1b617..8c3972142 100644
--- a/core/src/main/resources/template/html5/combobox.ftl
+++ b/core/src/main/resources/template/html5/combobox.ftl
@@ -18,11 +18,11 @@
  * under the License.
  */
 -->
-<@s.script src="${base}${attributes.staticContentPath}/combobox.js" />
 <#include "/${attributes.templateDir}/html5/text.ftl" /><#rt/>
 
 <#include 
"/${attributes.templateDir}/${attributes.expandTheme}/controlheader.ftl" />
 <#if attributes.list??>
+<@s.script src="${base}${attributes.staticContentPath}/combobox.js" />
 <select data-struts-combobox="${attributes.escapedId}" 
data-struts-combobox-target="${attributes.name}"<#rt/>
 <#if attributes.headerKey?? && attributes.headerValue??> 
data-struts-header-key="${attributes.headerKey}"</#if><#t/>
 <#if attributes.emptyOption!false> data-struts-empty-option="true"</#if><#t/>
diff --git a/core/src/main/resources/template/simple/combobox.ftl 
b/core/src/main/resources/template/simple/combobox.ftl
index 13dd95851..01a2fa6ae 100644
--- a/core/src/main/resources/template/simple/combobox.ftl
+++ b/core/src/main/resources/template/simple/combobox.ftl
@@ -18,10 +18,10 @@
  * under the License.
  */
 -->
-<@s.script src="${base}${attributes.staticContentPath}/combobox.js" />
 <#include "/${attributes.templateDir}/simple/text.ftl" />
 <br />
 <#if attributes.list??>
+<@s.script src="${base}${attributes.staticContentPath}/combobox.js" />
 <select data-struts-combobox="${attributes.escapedId}" 
data-struts-combobox-target="${attributes.name}"<#rt/>
 <#if attributes.headerKey?? && attributes.headerValue??> 
data-struts-header-key="${attributes.headerKey}"</#if><#t/>
 <#if attributes.emptyOption!false> data-struts-empty-option="true"</#if><#t/>
diff --git 
a/core/src/test/java/org/apache/struts2/views/jsp/ui/ComboBoxTest.java 
b/core/src/test/java/org/apache/struts2/views/jsp/ui/ComboBoxTest.java
index 03721c9d0..5562d9714 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/ui/ComboBoxTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/ComboBoxTest.java
@@ -278,7 +278,7 @@ public class ComboBoxTest extends AbstractUITagTest {
                 strutsBodyTagsAreReflectionEqual(tag, freshTag));
     }
 
-    public void testJsCallNamingUsesEscapedId() throws Exception {
+    public void testDataAttributeUsesEscapedId() throws Exception {
         TestAction testAction = (TestAction) action;
         testAction.setFoo("hello");
 
@@ -306,7 +306,7 @@ public class ComboBoxTest extends AbstractUITagTest {
                 strutsBodyTagsAreReflectionEqual(tag, freshTag));
     }
 
-    public void testJsCallNamingUsesEscapedId_clearTagStateSet() throws 
Exception {
+    public void testDataAttributeUsesEscapedId_clearTagStateSet() throws 
Exception {
         TestAction testAction = (TestAction) action;
         testAction.setFoo("hello");
 
@@ -337,4 +337,33 @@ public class ComboBoxTest extends AbstractUITagTest {
                 strutsBodyTagsAreReflectionEqual(tag, freshTag));
     }
 
+    public void testHtml5ThemeRendersDataAttributes() throws Exception {
+        // The ComboBox-1..4 fixtures all render the xhtml -> simple path, so 
a typo in the html5 template's
+        // data-struts-combobox-target / data-struts-header-key / 
data-struts-empty-option lines would go
+        // unnoticed. Render the html5 theme explicitly and pin all three 
attributes.
+        TestAction testAction = (TestAction) action;
+        testAction.setFoo("banana");
+
+        List l = new ArrayList();
+        l.add("apple");
+        l.add("banana");
+        testAction.setCollection(l);
+
+        ComboBoxTag tag = new ComboBoxTag();
+        tag.setPageContext(pageContext);
+        tag.setTheme("html5");
+        tag.setLabel("My Favourite Fruit");
+        tag.setName("myFavouriteFruit");
+        tag.setEmptyOption("true");
+        tag.setHeaderKey("-1");
+        tag.setHeaderValue("--- Please Select ---");
+        tag.setList("collection");
+        tag.setValue("%{foo}");
+
+        tag.doStartTag();
+        tag.doEndTag();
+
+        verify(ComboBoxTag.class.getResource("ComboBox-5.txt"));
+    }
+
 }
diff --git 
a/core/src/test/resources/org/apache/struts2/views/jsp/ui/ComboBox-1.txt 
b/core/src/test/resources/org/apache/struts2/views/jsp/ui/ComboBox-1.txt
index 8c91cbd7f..ecdc52238 100644
--- a/core/src/test/resources/org/apache/struts2/views/jsp/ui/ComboBox-1.txt
+++ b/core/src/test/resources/org/apache/struts2/views/jsp/ui/ComboBox-1.txt
@@ -1,8 +1,8 @@
 <tr>
     <td class="tdLabel"><label for="cb" class="label">mylabel:</label></td>
     <td class="tdInput">
-<script src="/static/combobox.js" nonce="r4nd0m"></script>
 <input type="text" name="foo" value="hello" id="cb"/><br/>
+<script src="/static/combobox.js" nonce="r4nd0m"></script>
 <select data-struts-combobox="cb" data-struts-combobox-target="foo">
     <option value="foo">foo</option>
     <option value="bar">bar</option>
diff --git 
a/core/src/test/resources/org/apache/struts2/views/jsp/ui/ComboBox-2.txt 
b/core/src/test/resources/org/apache/struts2/views/jsp/ui/ComboBox-2.txt
index 2f39ed24d..6f98ce713 100644
--- a/core/src/test/resources/org/apache/struts2/views/jsp/ui/ComboBox-2.txt
+++ b/core/src/test/resources/org/apache/struts2/views/jsp/ui/ComboBox-2.txt
@@ -1,8 +1,8 @@
 <tr>
     <td class="tdLabel"><label for="myFavouriteFruit" class="label">My 
Favourite Fruit:</label></td>
     <td class="tdInput">
-<script src="/static/combobox.js"></script>
 <input type="text" name="myFavouriteFruit" value="banana" 
id="myFavouriteFruit"/><br/>
+<script src="/static/combobox.js"></script>
 <select data-struts-combobox="myFavouriteFruit" 
data-struts-combobox-target="myFavouriteFruit" data-struts-header-key="-1" 
data-struts-empty-option="true">
        <option value="-1">--- Please Select ---</option>
        <option value=""></option>
diff --git 
a/core/src/test/resources/org/apache/struts2/views/jsp/ui/ComboBox-3.txt 
b/core/src/test/resources/org/apache/struts2/views/jsp/ui/ComboBox-3.txt
index 2f39ed24d..6f98ce713 100644
--- a/core/src/test/resources/org/apache/struts2/views/jsp/ui/ComboBox-3.txt
+++ b/core/src/test/resources/org/apache/struts2/views/jsp/ui/ComboBox-3.txt
@@ -1,8 +1,8 @@
 <tr>
     <td class="tdLabel"><label for="myFavouriteFruit" class="label">My 
Favourite Fruit:</label></td>
     <td class="tdInput">
-<script src="/static/combobox.js"></script>
 <input type="text" name="myFavouriteFruit" value="banana" 
id="myFavouriteFruit"/><br/>
+<script src="/static/combobox.js"></script>
 <select data-struts-combobox="myFavouriteFruit" 
data-struts-combobox-target="myFavouriteFruit" data-struts-header-key="-1" 
data-struts-empty-option="true">
        <option value="-1">--- Please Select ---</option>
        <option value=""></option>
diff --git 
a/core/src/test/resources/org/apache/struts2/views/jsp/ui/ComboBox-4.txt 
b/core/src/test/resources/org/apache/struts2/views/jsp/ui/ComboBox-4.txt
index 1e6830100..23f0e0caa 100644
--- a/core/src/test/resources/org/apache/struts2/views/jsp/ui/ComboBox-4.txt
+++ b/core/src/test/resources/org/apache/struts2/views/jsp/ui/ComboBox-4.txt
@@ -1,8 +1,8 @@
  <tr>
      <td class="tdLabel"><label for="cb[&#39;&quot;.&quot;&#39;]=bc(){};//" 
class="label">mylabel:</label></td>
      <td class="tdInput">
- <script src="/static/combobox.js"></script>
  <input type="text" name="foo" value="hello" 
id="cb[&#39;&quot;.&quot;&#39;]=bc(){};//"/><br/>
+ <script src="/static/combobox.js"></script>
  <select data-struts-combobox="cb__________bc_______" 
data-struts-combobox-target="foo">
      <option value="foo">foo</option>
  </select>
diff --git 
a/core/src/test/resources/org/apache/struts2/views/jsp/ui/ComboBox-2.txt 
b/core/src/test/resources/org/apache/struts2/views/jsp/ui/ComboBox-5.txt
similarity index 52%
copy from core/src/test/resources/org/apache/struts2/views/jsp/ui/ComboBox-2.txt
copy to core/src/test/resources/org/apache/struts2/views/jsp/ui/ComboBox-5.txt
index 2f39ed24d..ab9b56fba 100644
--- a/core/src/test/resources/org/apache/struts2/views/jsp/ui/ComboBox-2.txt
+++ b/core/src/test/resources/org/apache/struts2/views/jsp/ui/ComboBox-5.txt
@@ -1,15 +1,8 @@
-<tr>
-    <td class="tdLabel"><label for="myFavouriteFruit" class="label">My 
Favourite Fruit:</label></td>
-    <td class="tdInput">
+<input type="text" name="myFavouriteFruit" value="banana" 
id="myFavouriteFruit"/>
 <script src="/static/combobox.js"></script>
-<input type="text" name="myFavouriteFruit" value="banana" 
id="myFavouriteFruit"/><br/>
 <select data-struts-combobox="myFavouriteFruit" 
data-struts-combobox-target="myFavouriteFruit" data-struts-header-key="-1" 
data-struts-empty-option="true">
-       <option value="-1">--- Please Select ---</option>
-       <option value=""></option>
+    <option value="-1">--- Please Select ---</option>
+    <option value=""></option>
     <option value="apple">apple</option>
     <option value="banana" selected="selected">banana</option>
-    <option value="pineaple">pineaple</option>
-    <option value="grapes">grapes</option>
 </select>
-    </td>
-</tr>
\ No newline at end of file

Reply via email to