1

The real question: I'm trying to understand the interaction between a javascript snippet I found and the Primefaces commandButton. The javascript snippet is assigned to the onkeypress attribute of the JSF h:form tag. I have this snippet working on some of my pages but not on others. When I tried to strip down the non-essentials to ask THAT question the javascript stopped working entirely.

There seems to be something I don't understand since this code doesn't work. Note the code does work if the user actually clicks the button. I want it to work when they press the Enter key. I have stripped away as much as I can and lobotomized style guidelines to make it shorter.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui">
    <h:head>
        <title>Tray Report</title>
        <h:outputStylesheet library="css" name="postalreports.css"  />
    </h:head>
    <h:body>
        <h:form id="thisform"  onkeypress="if (event.keyCode == 13) { document.getElementById('thisform:btn').click(); return false; }" > 
            <p:panel id="panel" header="Report For Days">  
                <p:messages id="messages" />  
                <p:inputText id ="days" value="#{trayBean.days}" >
                </p:inputText>
            </p:panel>
            <p:commandButton id="btn" value="RUN" actionListener="#{trayBean.run}"/>            
        </h:form>
    </h:body>
</html>
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

@ManagedBean
@ViewScoped
public class TrayBean implements Serializable {
    private Integer days = 1;
    public TrayBean() {}
    public void run() {
        System.out.println("do something here");
    }
    public Integer getDays() {  return days; }
    public void setDays(Integer days) { this.days = days; }
}

P.S. I also tried if (event.keyCode == 13) { this.submit(); }

ADDED AFTER ADDITIONAL RESEARCH: Much to my chagrin, I have found a Primefaces specific solution to this that I should have found earlier. It turns out that no JavaScript is needed at all with the simple addition of the p:focus tag. Here is the XHTML file that actually works. There is no change to the backing bean.

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui">

    <h:head>
        <title>Tray Report</title>
    </h:head>
    <h:body>
        <h:form id="thisform"> 
            <p:focus/>
            <p:panel id="panel" header="Report For Days">  
                <p:messages id="messages" />  
                <p:inputText id ="days" value="#{trayBean.days}" >
                </p:inputText>
            </p:panel>
            <p:commandButton id="btn" value="RUN" actionListener="#{trayBean.run}"/>            
        </h:form>
    </h:body>
</html>

This will allow me to complete the analysis of my original problem (since I have a p:focus tag on pages that don't work yet) which I will post separately.

Dean
  • 301
  • 4
  • 11

1 Answers1

1

Since PrimeFaces is based on jQuery, you should save yourself time and use jQuery for registering key handler of form. Of course you must allow enter on elements that support it and doesn't trigger (and should not trigger) form submit. If you disallow ENTER on text areas, you'll annoy your users greately.

From my experience, keypress is not enough, you need also handle keyup:

<script type="text/javascript">
$(document).ready(function () {
var handler = function(event){
        if (event.which == 13) {
            var el = event.target;
            if (/textarea/i.test(el.tagName) || /button/i.test(el.tagName))
                return true;
            if (/input/i.test(el.tagName) && /file/i.test(el.type))
                return true;
            if (_handler)
                setTimeout(_handler, 1);
            event.stopPropagation();
            return false;
        }
        return true;
};
$('form').keyup(handler).keypress(handler)
});
</script>

See also this topic: How to prevent ENTER keypress to submit a web form? for more non-primefaces-related issues.

Community
  • 1
  • 1
Danubian Sailor
  • 1
  • 38
  • 145
  • 223
  • Thanks! This worked great with one caveat for green javascript developers like me. I found it necessary to surround the functions with // <![CDATA[ // ]]> when placed in my xhtml page. – Dean Jul 29 '13 at 16:14
  • The CDATA was not needed when I moved the script to a separate JavaScript file. – Dean Jul 29 '13 at 16:50
  • FOLLOW UP: The above (p:focus) solution does not work with some Primefaces components. I found it necessary to use the defaultCommand tag to make SelectOneMenu work when I used it in place of the InputText above. – Dean Jul 29 '13 at 18:55
  • What exactly has not worked? As for default action, I was controlling it via additional handler, but there were some places, where no default action was required. I'm still improving this code when a problem is found, anyway. – Danubian Sailor Jul 29 '13 at 19:22
  • \@Lukasz The code you provided worked perfectly. In the process of digging around, I ran into an alternative solution that does not require JavaScript but uses Primefaces tags exclusively. The company prefers I not use JavaScript unless necessary. I discovered the only thing needed to make the original xhtml work was the addition of a Primefaces tag. However, that tag does not work if I replace the InputText field with a SelectOneMenu. I was able to solve that case with the tag. – Dean Jul 30 '13 at 20:12