Repository: primefaces/primefaces (java)

Issue:
DataScroller: facet loader is not rendered, because the rowCount is badly set
### Describe the bug

if datasource is LazyDataModel, then the rowCount must be updated after the encodeList is called, otherwise the loader is not encoded (rendered).

```
DataScrollerRenderer.java
protected void encodeMarkup(FacesContext context, DataScroller ds, int chunkSize) throws IOException {

           ...

141           if (ds.isStartAtBottom()) {
142               start = rowCount > chunkSize ? rowCount - chunkSize : 0;
143           }
144
145           encodeList(context, ds, start, chunkSize);
146
                  //rowCount = ds.getRowCount(); THIS IS MISSING

147           writer.startElement("div", null);
148           writer.writeAttribute("class", DataScroller.LOADER_CLASS, null);
149           if (rowCount > chunkSize && FacetUtils.shouldRenderFacet(loader)) {
150                loader.encodeAll(context);
                  }
```

### Reproducer

_No response_

### Expected behavior

_No response_

### PrimeFaces edition

Community

### PrimeFaces version

master

### Theme

_No response_

### JSF implementation

Mojarra

### JSF version

2.3.20

### Java version

11

### Browser(s)

_No response_

Pull request:
Fix #11589: DataScroller update lazy rowCount for facet
Fix #11589: DataScroller update lazy rowCount for facet

cc @vonnai 

Patch:
diff --git a/primefaces/src/main/java/org/primefaces/component/datascroller/DataScrollerRenderer.java b/primefaces/src/main/java/org/primefaces/component/datascroller/DataScrollerRenderer.java
index 6a7abc3cc2..68bc0860ea 100644
--- a/primefaces/src/main/java/org/primefaces/component/datascroller/DataScrollerRenderer.java
+++ b/primefaces/src/main/java/org/primefaces/component/datascroller/DataScrollerRenderer.java
@@ -144,6 +144,10 @@ public class DataScrollerRenderer extends CoreRenderer {
 
             encodeList(context, ds, start, chunkSize);
 
+            if (ds.isLazy()) {
+                rowCount = ds.getRowCount();
+            }
+
             writer.startElement("div", null);
             writer.writeAttribute("class", DataScroller.LOADER_CLASS, null);
             if (rowCount > chunkSize && FacetUtils.shouldRenderFacet(loader)) {
diff --git a/primefaces/src/main/java/org/primefaces/component/inputmask/InputMaskRenderer.java b/primefaces/src/main/java/org/primefaces/component/inputmask/InputMaskRenderer.java
index 26197a485e..7cc926ba27 100644
--- a/primefaces/src/main/java/org/primefaces/component/inputmask/InputMaskRenderer.java
+++ b/primefaces/src/main/java/org/primefaces/component/inputmask/InputMaskRenderer.java
@@ -87,23 +87,31 @@ public class InputMaskRenderer extends InputRenderer {
 
     protected Pattern translateMaskIntoRegex(StringBuilder regex, String mask) {
         boolean optionalFound = false;
+        boolean escapeFound = false;
 
         for (char c : mask.toCharArray()) {
             if (c == '[' || c == ']') {
                 optionalFound = true;
             }
+            else if (c == '\\') {
+                escapeFound = true;
+            }
             else {
-                regex.append(translateMaskCharIntoRegex(c, optionalFound));
+                regex.append(translateMaskCharIntoRegex(c, optionalFound, escapeFound));
+                escapeFound = false;
             }
         }
         return Pattern.compile(regex.toString());
     }
 
-    protected String translateMaskCharIntoRegex(char c, boolean optional) {
+    protected String translateMaskCharIntoRegex(char c, boolean optional, boolean escapeFound) {
         String translated;
 
-        if (c == '[' || c == ']') {
-            return ""; //should be ignored
+        if (escapeFound) {
+            return String.valueOf(c);
+        }
+        else if (c == '[' || c == ']') {
+            return Constants.EMPTY_STRING; //should be ignored
         }
         else if (c == '9') {
             translated = "[0-9]";
diff --git a/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.resources.js b/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.resources.js
index 9f74802774..459b38ecfe 100644
--- a/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.resources.js
+++ b/primefaces/src/main/resources/META-INF/resources/primefaces/core/core.resources.js
@@ -112,16 +112,26 @@ if (!PrimeFaces.resources) {
            * @return {string} The first JavasScript resource URI.
            */
           getResourceScriptURI : function() {
-             if (!PrimeFaces.resources.SCRIPT_URI) {
-                PrimeFaces.resources.SCRIPT_URI =
-                   $('script[src*="/' + PrimeFaces.RESOURCE_IDENTIFIER + '/"]').first().attr('src');
-
-                // portlet
-                if (!PrimeFaces.resources.SCRIPT_URI) {
-                   PrimeFaces.resources.SCRIPT_URI = $('script[src*="' + PrimeFaces.RESOURCE_IDENTIFIER + '="]').first().attr('src');
-                }
-             }
-             return PrimeFaces.resources.SCRIPT_URI;
+              if (!PrimeFaces.resources.SCRIPT_URI) {
+                  function findScriptWithVersionParam(scripts) {
+                      scripts.each(function() {
+                          var src = $(this).attr('src');
+                          if (src && src.indexOf('v=') !== -1) {
+                              PrimeFaces.resources.SCRIPT_URI = src;
+                              return false; // Exit the loop early
+                          }
+                      });
+                  }
+
+                  // normal '/showcase/javax.faces.resource/jquery/jquery.js.xhtml?ln=primefaces&v=13.0.5'
+                  findScriptWithVersionParam($('script[src*="/' + PrimeFaces.RESOURCE_IDENTIFIER + '/"]'));
+
+                  // portlet 'javax.faces.resource=jquery/jquery.js.xhtml?ln=primefaces&v=13.0.5'
+                  if (!PrimeFaces.resources.SCRIPT_URI) {
+                      findScriptWithVersionParam($('script[src*="' + PrimeFaces.RESOURCE_IDENTIFIER + '="]'));
+                  }
+              }
+              return PrimeFaces.resources.SCRIPT_URI;
           }
     };
 
diff --git a/primefaces/src/main/resources/META-INF/resources/primefaces/forms/forms.selectoneradio.js b/primefaces/src/main/resources/META-INF/resources/primefaces/forms/forms.selectoneradio.js
index eb39587b8a..dcf39bc692 100644
--- a/primefaces/src/main/resources/META-INF/resources/primefaces/forms/forms.selectoneradio.js
+++ b/primefaces/src/main/resources/META-INF/resources/primefaces/forms/forms.selectoneradio.js
@@ -130,7 +130,8 @@ PrimeFaces.widget.SelectOneRadio = PrimeFaces.widget.BaseWidget.extend({
         var $this = this;
 
         if (!this.cfg.readonly) {
-            this.outputs.filter(':not(.ui-state-disabled)').on('mouseenter.selectOneRadio', function() {
+            this.outputs.filter(':not(.ui-state-disabled)').off('mouseenter.selectOneRadio mouseleave.selectOneRadio click.selectOneRadio')
+            .on('mouseenter.selectOneRadio', function() {
                 $(this).addClass('ui-state-hover');
             })
             .on('mouseleave.selectOneRadio', function() {
@@ -161,7 +162,8 @@ PrimeFaces.widget.SelectOneRadio = PrimeFaces.widget.BaseWidget.extend({
                 e.preventDefault();
             });
 
-            this.labels.filter(':not(.ui-state-disabled)').on('click.selectOneRadio', function(e) {
+            this.labels.filter(':not(.ui-state-disabled)').off('click.selectOneRadio')
+            .on('click.selectOneRadio', function(e) {
                 var target = $(PrimeFaces.escapeClientId($(this).attr('for'))),
                 radio = null;
 
@@ -177,7 +179,8 @@ PrimeFaces.widget.SelectOneRadio = PrimeFaces.widget.BaseWidget.extend({
             });
         }
 
-        this.enabledInputs.on('focus.selectOneRadio', function() {
+        this.enabledInputs.off('focus.selectOneRadio blur.selectOneRadio keydown.selectOneRadio')
+        .on('focus.selectOneRadio', function() {
             var input = $(this),
             radio = input.parent().next();
 


Test patch:
diff --git a/primefaces/src/test/java/org/primefaces/component/inputmask/InputMaskRendererTest.java b/primefaces/src/test/java/org/primefaces/component/inputmask/InputMaskRendererTest.java
index 35ea3bb74f..d838c3fb26 100644
--- a/primefaces/src/test/java/org/primefaces/component/inputmask/InputMaskRendererTest.java
+++ b/primefaces/src/test/java/org/primefaces/component/inputmask/InputMaskRendererTest.java
@@ -45,4 +45,18 @@ class InputMaskRendererTest {
         assertEquals("[0-9][0-9]?[0-9]?[0-9]?", result.pattern());
     }
 
+    @Test
+    void translateMaskIntoRegex_EscapeCharacter_GitHub11590() {
+        // Arrange
+        InputMaskRenderer comp = new InputMaskRenderer();
+        StringBuilder sb = new StringBuilder();
+        String mask = "\\G.9";
+
+        // Act
+        Pattern result = comp.translateMaskIntoRegex(sb, mask);
+
+        // Assert
+        assertEquals("G\\.[0-9]", result.pattern());
+    }
+
 }