5 Replies Latest reply on Feb 9, 2012 11:03 AM by jgoodfellow

    Richfaces 4 menu onclick ignores return value.

    jgoodfellow

      I was reading the discussion: http://community.jboss.org/message/584893 and I realized that I use the menuitem in the same way by using the onclick event to confirm an action.  Unfortunately, after upgrading to 4.0.0.Final I see that the menu item action will process whether or not you return false from onclick.  Is there any way to get the behavior of a confirm before executing a menu item action?  Here's my code:

       

      <rich:menuItem id="myMenuItem"

                     mode="server"

                     label="Delete Everything"

                    action="#{myBean.deleteEverything}"

                    onclick="if ( !confirm('Are you sure?') ){return false;}" />

       

      I have tried event.preventDefault(); and event.stopPropagation(); in the onclick handler and that doesn't seem to work.

       

       

      Thanks,

      Jamie.

        • 1. Re: Richfaces 4 menu onclick ignores return value.
          jacky.cheung

          James G wrote:

           

          <rich:menuItem id="myMenuItem"

                         mode="server"

                         label="Delete Everything"

                        action="#{myBean.deleteEverything}"

                        onclick="if ( !confirm('Are you sure?') ){return false;}" />

           

          Are you sure you it works in Richfaces 3? menuItem ignores onclick if submitMode = "server" in Richfaces 3. In Richfaces 3, you need to use "ajax" submitMode and reRender your page. I would suggest you to change it to "ajax".

           

          Jacky

          • 2. Re: Richfaces 4 menu onclick ignores return value.
            jgoodfellow

            Yes, in Richfaces 3 the onclick parameter is appended before the richfaces submit command so the generated html is, for example (in server mode):

             

            <div onclick="if ( !confirm('Are you sure?') ){return false;};RichFaces.Menu.submitForm(event,this)" id="theForm:myMenuItem" class="rich-menu-item rich-menu-item-enabled  " style=""><span id="theForm:j_id165:icon" class="rich-menu-item-icon "><img height="16" width="16" src="/faces/a4j/g/3_3_3.Finalimages/spacer.gif" alt=""></span><span id="theForm:j_id165:anchor" class="rich-menu-item-label">Delete</span></div>

             

            • 3. Re: Richfaces 4 menu onclick ignores return value.
              jacky.cheung

              James G wrote:

               

              Yes, in Richfaces 3 the onclick parameter is appended before the richfaces submit command so the generated html is, for example (in server mode):

               

              <div onclick="if ( !confirm('Are you sure?') ){return false;};RichFaces.Menu.submitForm(event,this)" id="theForm:myMenuItem" class="rich-menu-item rich-menu-item-enabled  " style=""><span id="theForm:j_id165:icon" class="rich-menu-item-icon "><img height="16" width="16" src="/faces/a4j/g/3_3_3.Finalimages/spacer.gif" alt=""></span><span id="theForm:j_id165:anchor" class="rich-menu-item-label">Delete</span></div>

               

               

              That's strange. It does not generate "if ( !confirm(..." if I set submitMode to "server". Which version did you use? I am using Richfaces 3.3.1.GA.

               

              BTW, I don't use Richfaces 4. Can you tell me if the javascript confirm works if submitMode is set to "ajax"? In 3.3.1.GA, it works if I set the submitMode to "ajax".  Thanks.

               

              Jacky

              • 4. Re: Richfaces 4 menu onclick ignores return value.
                healeyb

                James, did you file a JIRA for this? I've just encountered the same problem. As a workaround move the action onto

                a jsFunction and conditionally call it:

                 

                <rich:menuItem label="Delete"

                                       mode="ajax"

                                       onclick="confirmAction();"/>

                 

                <script type="text/javascript">

                  confirmAction = function() {

                    if(!confirm('are you sure?')) {

                      return;

                    } else {

                      callAction();

                    }

                  }

                </script>

                 

                <a4j:jsFunction name="callAction" action="#{bean.doSomething}"/>

                 

                I've logged this jira https://issues.jboss.org/browse/RF-11971

                 

                Regards,

                Brendan.

                • 5. Re: Richfaces 4 menu onclick ignores return value.
                  jgoodfellow

                  Hi Brendan, to be honest with you I still use RichFaces but I don't log issues anymore.  It seemed that simple bugs I logged were pushed to future without much review.  Many of the RF components I use are overriden in some way to either fix bugs or add basic features.  For menu items, along with the ability to "cancel" an onclick action from javascript I also need the ability to enable and disable the items through javascript to avoid ajax calls.  To do this I've overriden MenuItemRenderer and some of the menu item javascript.  If you choose to override RF, this is a dump of my changes (hope it works for you):

                  Add this to a javascript file you include after the richfaces includes:

                  // Richfaces overrides
                  // Add a disable method to the menu item
                  if ( typeof(RichFaces) != "undefined" && 
                       typeof(RichFaces.ui) != "undefined" && 
                       typeof(RichFaces.ui.MenuItem) != "undefined" )
                  {
                      var subspanItemCss = "rf-ddm-itm-lbl";

                   

                      RichFaces.ui.MenuItem.prototype.disable = function( disabled ) {
                          var alreadyDisabled = false;
                          var parentMenu = this.__getParentMenu();
                          var alreadyDisabled = parentMenu.__isDisabled( this.element );
                          if ( disabled == alreadyDisabled ) return;
                          if ( disabled ) {
                              this.element.toggleClass( this.options.unselectItemCss, false );
                              this.element.toggleClass( parentMenu.options.disabledItemCss, true );
                              $( "div[id='" + this.element.get(0).id + "'] span[class*='" + subspanItemCss + "']" ).toggleClass( subspanItemCss, false );
                              
                              RichFaces.Event.unbindById(this.id, 'click');
                              RichFaces.Event.unbindById(this.id, 'mouseenter');
                              RichFaces.Event.unbindById(this.id, 'mouseleave');
                          }
                          else {
                              this.element.toggleClass( parentMenu.options.disabledItemCss, false );
                              this.element.toggleClass( this.options.unselectItemCss, true );
                              $( "div[id='" + this.element.get(0).id + "'] span[class='']" ).toggleClass( subspanItemCss, true );
                              
                              RichFaces.Event.bindById(this.id, 'click', this.__clickHandler, this);
                              RichFaces.Event.bindById(this.id, 'mouseenter', this.select, this);
                              RichFaces.Event.bindById(this.id, 'mouseleave', this.unselect, this);
                          }
                      };

                   

                      RichFaces.ui.MenuItem.prototype.__clickHandler2 = RichFaces.ui.MenuItem.prototype.__clickHandler;
                      RichFaces.ui.MenuItem.prototype.__clickHandler = function(e) {
                          if (jQuery(e.target).is(":input:not(:button):not(:reset):not(:submit)")) {
                              return;
                          }
                          if( this.options.clickHandler != undefined &&
                              this.options.clickHandler != null )
                          {
                              var result = this.options.clickHandler(e);
                              if ( result != undefined && result != null && !result )
                              {
                                  this.unselect();
                                  var parentMenu = this.__getParentMenu();
                                  if (parentMenu) {
                                      parentMenu.hide();
                                  }
                                  return;
                              }
                          }
                          this.__clickHandler2(e);
                      };
                  }

                  And here's MenuItemRenderer.java:

                  import static org.richfaces.renderkit.RenderKitUtils.addToScriptHash;
                  import static org.richfaces.renderkit.RenderKitUtils.attributes;
                  import static org.richfaces.renderkit.RenderKitUtils.renderPassThroughAttributes;
                  import static org.richfaces.renderkit.RenderKitUtils.shouldRenderAttribute;
                  import static org.richfaces.renderkit.RenderKitUtils.toScriptArgs;

                   

                  import java.io.IOException;
                  import java.util.LinkedHashMap;
                  import java.util.Map;

                   

                  import javax.faces.application.ResourceDependencies;
                  import javax.faces.application.ResourceDependency;
                  import javax.faces.component.UIComponent;
                  import javax.faces.context.FacesContext;
                  import javax.faces.context.ResponseWriter;

                   

                  import org.ajax4jsf.javascript.JSFunctionDefinition;
                  import org.richfaces.renderkit.RenderKitUtils;
                  import org.richfaces.renderkit.RenderKitUtils.Attributes;
                  import org.richfaces.renderkit.RenderKitUtils.ScriptHashVariableWrapper;
                  import org.richfaces.renderkit.html.MenuItemRendererBase;
                  import org.richfaces.renderkit.util.RendererUtils;

                   

                  @ResourceDependencies( {
                          @ResourceDependency( name = "ajax.reslib", library = "org.richfaces", target = "" ),
                          @ResourceDependency( name = "base-component.reslib", library = "org.richfaces", target = "" ),
                          @ResourceDependency( name = "richfaces-event.js", library = "", target = "" ),
                          @ResourceDependency( name = "menuitem.js", library = "org.richfaces", target = "" )
                          @ResourceDependency(name="dropdownmenu.ecss",library="org.richfaces",target="") })
                  public class MenuItemRenderer extends MenuItemRendererBase
                  {
                      private static final Attributes PASS_THROUGH_ATTRIBUTES32 = attributes()
                              .generic( "align", "align" )
                              .generic( "dir", "dir" )
                              .generic( "lang", "lang" )
                              //.generic( "onclick", "onclick", "click" )
                              .generic( "ondblclick", "ondblclick", "dbflclick" )
                              .generic( "onkeydown", "onkeydown", "keydown" )
                              .generic( "onkeypress", "onkeypress", "keypress" )
                              .generic( "onkeyup", "onkeyup", "keyup" )
                              .generic( "onmousedown", "onmousedown", "mousedown" )
                              .generic( "onmousemove", "onmousemove", "mousemove" )
                              .generic( "onmouseout", "onmouseout", "mouseout" )
                              .generic( "onmouseover", "onmouseover", "mouseover" )
                              .generic( "onmouseup", "onmouseup", "mouseup" )
                              .generic( "title", "title" );

                   

                      private static String convertToString( Object object )
                      {
                          return object != null ? object.toString() : "";
                      }

                   

                      private static boolean convertToBoolean( Object object )
                      {
                          if( object == null )
                          {
                              return false;
                          }

                   

                          if( object instanceof Boolean )
                          {
                              return Boolean.TRUE.equals( object );
                          }

                   

                          return Boolean.valueOf( object.toString() );

                   

                      }

                   

                      private static boolean isEmpty( Object object )
                      {
                          return object == null || object.toString().length() == 0;
                      }

                   

                      @Override
                      public void encodeEnd( FacesContext facesContext, UIComponent component )
                              throws IOException
                      {
                          ResponseWriter responseWriter = facesContext.getResponseWriter();
                          String clientId = component.getClientId( facesContext );
                          Object style = component.getAttributes().get( "style" );
                          String iconClass = this.getStyleClass( facesContext,
                                                                 component,
                                                                 "",
                                                                 "iconClass",
                                                                 "iconClass" );
                          String labelClass = this.getStyleClass( facesContext,
                                                                  component,
                                                                  "",
                                                                  "labelClass",
                                                                  "labelClass" );
                          String styleClass = this.getStyleClass( facesContext,
                                                                  component,
                                                                  "itemClass",
                                                                  "styleClass",
                                                                  "styleClass" );
                          String disabledClass = this.getStyleClass( facesContext,
                                                                     component,
                                                                     "disabledItemClass",
                                                                     "disabledClass",
                                                                     "disabledClass" );
                          boolean isDisabled = this.isDisabled( facesContext, component );
                          UIComponent iconFacet = this.getIconFacet( facesContext, component );
                          String iconAttribute = this.getIconAttribute( facesContext, component );
                          responseWriter.startElement( "div", component );
                          {
                              String value = "rf-ddm-itm "
                                      + convertToString( ( convertToBoolean( isDisabled ) ? ( "rf-ddm-itm-dis " + disabledClass )
                                              : ( "rf-ddm-itm-unsel " + styleClass ) ) );
                              if( null != value && value.length() > 0 )
                              {
                                  responseWriter.writeAttribute( "class", value, null );
                              }

                   

                          }

                   

                          {
                              String value = clientId;
                              if( null != value && value.length() > 0 )
                              {
                                  responseWriter.writeAttribute( "id", value, null );
                              }

                   

                          }

                   

                          {
                              Object value = style;
                              if( null != value && shouldRenderAttribute( value ) )
                              {
                                  responseWriter.writeAttribute( "style", value, null );
                              }
                          }

                   

                          renderPassThroughAttributes( facesContext,
                                                       component,
                                                       PASS_THROUGH_ATTRIBUTES32 );

                   

                          responseWriter.startElement( "span", component );
                          {
                              String value = "rf-ddm-itm-ic " + convertToString( iconClass );
                              if( null != value && value.length() > 0 )
                              {
                                  responseWriter.writeAttribute( "class", value, null );
                              }
                          }

                   

                          if( ( ( iconFacet != null ) && convertToBoolean( iconFacet.isRendered() ) ) )
                          {
                              iconFacet.encodeAll( facesContext );
                          }
                          else if( ( !convertToBoolean( this.isStringEmpty( iconAttribute ) ) ) )
                          {
                              responseWriter.startElement( "img", component );
                              responseWriter.writeAttribute( "alt", "", null );

                   

                              responseWriter.writeAttribute( "height", "16", null );

                   

                              {
                                  Object value = RenderKitUtils.getResourceURL( iconAttribute,
                                                                                facesContext );
                                  if( null != value && value.toString().length() > 0 )
                                  {
                                      responseWriter.writeURIAttribute( "src", value, null );
                                  }
                              }

                   

                              responseWriter.writeAttribute( "width", "16", null );
                              responseWriter.endElement( "img" );
                          }
                          else
                          {
                              responseWriter.startElement( "div", component );
                              responseWriter.writeAttribute( "class", "rf-ddm-emptyIcon", null );

                   

                              responseWriter.endElement( "div" );
                          }
                          responseWriter.endElement( "span" );
                          if( ( !convertToBoolean( isDisabled ) ) )
                          {
                              responseWriter.startElement( "span", component );
                              {
                                  String value = "rf-ddm-itm-lbl " + convertToString( labelClass );
                                  if( null != value && value.length() > 0 )
                                  {
                                      responseWriter.writeAttribute( "class", value, null );
                                  }
                              }

                   

                              if( ( !isEmpty( component.getAttributes().get( "label" ) ) ) )
                              {
                                  {
                                      Object text = component.getAttributes().get( "label" );
                                      if( text != null )
                                      {
                                          responseWriter.writeText( text, null );
                                      }
                                  }

                   

                              }
                              else
                              {
                                  renderChildren( facesContext, component );
                              }
                              responseWriter.endElement( "span" );
                          }
                          else
                          {
                              if( ( !isEmpty( component.getAttributes().get( "label" ) ) ) )
                              {
                                  {
                                      Object text = component.getAttributes().get( "label" );
                                      if( text != null )
                                      {
                                          responseWriter.writeText( text, null );
                                      }
                                  }

                   

                              }
                              else
                              {
                                  renderChildren( facesContext, component );
                              }
                          }
                          if( ( !convertToBoolean( isDisabled ) ) )
                          {
                              responseWriter.startElement( "script", component );
                              responseWriter.writeAttribute( "type", "text/javascript", null );

                   

                              Map< String, Object > options = new LinkedHashMap< String, Object >();
                              addToScriptHash( options, "params", RendererUtils.getInstance()
                                      .createParametersMap( facesContext, component ), null, null );

                   

                              addToScriptHash( options,
                                               "mode",
                                               this.getSubmitMode( component ),
                                               org.richfaces.component.Mode.server,
                                               null );

                   

                              addToScriptHash( options,
                                               "submitFunction",
                                               this.getOnClickFunction( facesContext, component ),
                                               null,
                                               ScriptHashVariableWrapper.eventHandler );

                   

                              String onclick = convertToString( RenderKitUtils.getAttributeAndBehaviorsValue( 
                                                   facesContext, component, attributes().generic( "onclick", "onclick", "click" ).first() ) );
                              if ( !onclick.isEmpty() )
                              {
                                  JSFunctionDefinition functionDefinition = new JSFunctionDefinition( "event" );
                                  functionDefinition.addToBody( onclick );
                                  functionDefinition.addToBody( ";return true;" );
                                  options.put( "clickHandler", functionDefinition );
                              }
                              
                              {
                                  Object text = "new RichFaces.ui.MenuItem("
                                          + convertToString( toScriptArgs( clientId, options ) )
                                          + ");";
                                  if( text != null )
                                  {
                                      responseWriter.writeText( text, null );
                                  }
                              }

                   

                              responseWriter.endElement( "script" );
                          }
                          else
                          {
                          }
                          responseWriter.endElement( "div" );

                   

                      }

                   

                      @Override
                      public boolean getRendersChildren()
                      {
                          return true;
                      }
                  }

                  In faces-config.xml add this entry:

                  <renderer>

                   

                  <component-family>org.richfaces.DropDownMenu</component-family>

                   

                  <renderer-type>org.richfaces.MenuItemRenderer</renderer-type>

                   

                  <renderer-class>yourpackage.MenuItemRenderer</renderer-class>

                   

                  <renderer-extension>

                   

                  <cdk:renders-children>true</cdk:renders-children>

                   

                  </renderer-extension>

                  </renderer>