9 Replies Latest reply on Jan 29, 2008 8:25 AM by Piotr Walczyszyn

    different behaviour when clicking on a button or using enter

    Carsten Hoehne Master

      Hello,
      we experience this problem:
      Clicking on a button behaves different than pressing the button via return/enter key.

      Scenario:
      Displaying a form (long-running-conversation active)
      Inside this form the user can activate a new page which starts a nested conversation.

      <ui:composition xmlns=[...]
       <ui:define name="body">
       <h:form>
      [...]
       <h:commandButton action="#{tgw.save}" value="save"></h:commandButton>
       </h:form>
       </ui:define>
      </ui:composition>
      

      The save action is annotated with @End and it performs a endAndRedirect:
      @End()
       public void save(){
      [...] Events.instance().raiseEvent("CALCYIELD",plot);
       Conversation.instance().endAndRedirect();
       }
      

      When clicking on the button, the user is redirected to the enclosing form and the nested conversation has ended.
      But when the user presses the return/enter key inside the form a redirection to the enclosing form happend but the nested conversation has not ended.
      What is going on here?
      This is happening inside a seam-gen generated project (with Seam2.0.0Beta1)
      I've just reassured that the save action is really called when pressing enter/return

      Another related question (which has little relation to seam but to JSF in general. Perhaps someone has a hint)
      I have to deal with a couple of peoples who are used to press enter when they enter a numeric value in a field.
      I do not want to submit the form in this case. The only way to catch this scenario for me, is to place a default button at the top of the form which does nothing.
      Are there better ways?
      Ciao,
      Carsten

        • 1. Re: different behaviour when clicking on a button or using e
          Christian Bauer Master

          This looks like a big hole in JSF and it has been discussed here recently. I need a solution for this as well. So the logic in JSF seems to be that some crappy Javascript starts searching for the "nearest" commandButton/Link when you press enter in a form and then invokes the other crap Javascript that submits the form. This is of course an unacceptable strategy, and we need a way to wire the action that is called when Enter is pressed into the form somehow.

          • 2. Re: different behaviour when clicking on a button or using e
            Carsten Hoehne Master

            Thanks, Christian, for your answer.
            I'd like to read the recent discussion you mentioned. But i was not able to find it, unfortunately.
            Can you give me a pointer, please?

            • 3. Re: different behaviour when clicking on a button or using e
              Mike Jekimov Newbie

              Maybe this helps

              /**
               * This JSF component marks the enclosing action component (e.g. h:commandButton) as default, i.e.
               * if the user presses Enter key the enclosing component's action will be performed, e.g.:
               * <code>
               * <h:commandButton action="#{myBean.myAction}">
               * <myprefix:defaultAction//>
               * </h:commandButton>
               * <code>
               * Only one defaultAction per scope is allowed. You can specify the scope by setting
               * the scope attribute. If you set scope="document" (default) then only one component can be marked as
               * defaultAction in the entire HTML document. If you set scope="form" you can have one defaultAction per
               * HTML form.
               *
               */
              public class UIDefaultAction extends UIOutput {
              
               public static final String SCOPE_DOCUMENT = "document";
              
               public static final String SCOPE_FORM = "form";
              
               private String scope = SCOPE_DOCUMENT;
              
               public void encodeBegin(FacesContext context) throws IOException {
               return;
               }
              
               public void decode(FacesContext context) {
               return;
               }
              
               public void encodeEnd(FacesContext context) throws IOException {
               ResponseWriter writer = context.getResponseWriter();
               UIComponent actionComponent = super.getParent();
               String acId = actionComponent.getClientId(context);
               UIForm form = getForm(actionComponent);
               if (form != null) {
              
               String formId = form.getClientId(context);
              
               writer.startElement("script", null);
              
               StringBuilder javascript = new StringBuilder();
              
               javascript.append("function processKeyPress(keyCode) {");
               javascript.append(" if (keyCode == 13) {");
               javascript.append(" document.getElementById('" + acId + "').click();");
               javascript.append(" }");
               javascript.append("}");
              
               javascript.append("function clickEnter(event) {");
               javascript.append(" processKeyPress(event.which);");
               javascript.append("}");
              
               javascript.append("function clickEnterIE() {");
               javascript.append(" processKeyPress(event.keyCode);");
               javascript.append("}");
              
               javascript.append("if (document.all) {");
               javascript.append(" " + getKeyPressEventSource(formId) + " = clickEnterIE;");
               javascript.append("} else {");
               javascript.append(" " + getKeyPressEventSource(formId) + " = clickEnter;");
               javascript.append("}");
              
               writer.write(javascript.toString());
              
               writer.endElement("script");
               }
               }
              
               public String getScope() {
               return scope;
               }
              
               public void setScope(String scope) {
               this.scope = scope;
               }
              
               @Override
               public void restoreState(FacesContext context, Object state) {
               Object[] values = (Object[]) state;
               super.restoreState(context, values[0]);
               this.scope = (String) values[1];
               }
              
               /**
               * @see javax.faces.component.UIComponentBase#saveState(javax.faces.context.FacesContext)
               */
               @Override
               public Object saveState(FacesContext context) {
               Object[] values = new Object[2];
               values[0] = super.saveState(context);
               values[1] = this.scope;
               return values;
              
               }
              
               private String getKeyPressEventSource(String formId) {
               if (SCOPE_FORM.equals(getScope())) {
               return "document.forms['" + formId + "'].onkeypress";
               } else {
               return "document.onkeypress";
               }
               }
              
               private UIForm getForm(UIComponent component) {
               while (component != null) {
               if (component instanceof UIForm) {
               break;
               }
               component = component.getParent();
               }
               return (UIForm) component;
               }
              
              }
              

              Works for me in myfaces

              • 5. Re: different behaviour when clicking on a button or using e
                Piotr Walczyszyn Newbie

                Was this issue resolved, I can't find it in the latest 2.0.1.CR2 source code?

                • 6. Re: different behaviour when clicking on a button or using e
                  Pete Muir Master

                  Yup. Just use

                  <s:defaultAction />


                  • 7. Re: different behaviour when clicking on a button or using e
                    Piotr Walczyszyn Newbie

                    Thank you, I found it but unfortunetly it only works with buttons (h:commandButton etc) and what I'm looking for is a solution that will work with h:commandLink also.

                    • 8. Re: different behaviour when clicking on a button or using e
                      Pete Muir Master

                      http://jira.jboss.com/jira/browse/JBSEAM-2270 - probably we want to extract the relevant js from jquery rather than make seam depend on jquery. Fancy having a go?