Author: rich
Date: Mon Feb 21 22:31:48 2005
New Revision: 154801

URL: http://svn.apache.org/viewcvs?view=rev&rev=154801
Log:
Fix for http://issues.apache.org/jira/browse/BEEHIVE-190 : The prevent double 
submit feature does not work if the back button is not using the cached page

The 'preventDoubleSubmit' attribute on @Jpf.Action/@Jpf.SimpleAction works in 
conjunction with NetUI tags (anchor, button, etc.) to throw an exception if an 
action is raised twice from the same page.  This works when the user 
double-clicks a link, but it doesn't always work when the user clicks the link, 
reaches a success page, goes back using the back button, and clicks the link 
again.  The specific case where this doesn't work is when the browser is 
instructed *not* to cache the original page, so each time you go back to it, a 
new one is rendered.  By default, pages reached through Page Flow actions 
included no-cache headers when the server was not in production mode (to make 
iterative development easier).

To mitigate this, I've added the ability to configure action/page caching 
(i.e., the headers that are sent to the browser to configure caching).  The 
default behavior now is *not* to prevent caching on pages, which fixes this 
bug.  If you *do* still want to prevent caching of pages, you can add either of 
the following snippets to netui-config.xml:

    <pageflow-config>
        <prevent-cache>always</prevent-cache>
    </pageflow-config>

        -or-

    <pageflow-config>
        <prevent-cache>inDevMode</prevent-cache>
    </pageflow-config>

The "always" value always prevents caching, and the "inDevMode" value prevents 
caching when the server is not in production mode.

I also added a 'disableOnClick' attribute to the Anchor, ImageAnchor, and 
Button tags.  When this is set to true, the button/link can't be clicked twice 
-- this eliminates the need for server-side checking in cases where JavaScript 
is enabled.

DRT/BVT: netui (WinXP)
BB: self (linux)



Added:
    incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/tags/disableOnClick/
    
incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/tags/disableOnClick/Controller.jpf
   (with props)
    
incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/tags/disableOnClick/cool.gif
   (with props)
    
incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/tags/disableOnClick/index.jsp
   (with props)
    
incubator/beehive/trunk/netui/test/webapps/drt/testRecorder/tests/DisableOnClick.xml
   (with props)
Modified:
    
incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowRequestProcessor.java
    
incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/JavaControlUtils.java
    
incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive/netui/tags/html/AnchorBase.java
    
incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive/netui/tags/html/Button.java
    
incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive/netui/tags/javascript/CoreScriptFeature.java
    
incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive/netui/tags/javascript/ScriptRequestState.java
    
incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive/netui/tags/javascript/javaScript.properties
    incubator/beehive/trunk/netui/src/util/schema/netui-config/netui-config.xsd
    
incubator/beehive/trunk/netui/test/webapps/drt/testRecorder/config/testRecorder-tests.xml

Modified: 
incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowRequestProcessor.java
URL: 
http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowRequestProcessor.java?view=diff&r1=154800&r2=154801
==============================================================================
--- 
incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowRequestProcessor.java
 (original)
+++ 
incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowRequestProcessor.java
 Mon Feb 21 22:31:48 2005
@@ -46,6 +46,8 @@
 import org.apache.beehive.netui.util.DiscoveryUtils;
 import org.apache.beehive.netui.util.FileUtils;
 import org.apache.beehive.netui.util.ServletUtils;
+import org.apache.beehive.netui.util.config.ConfigUtil;
+import org.apache.beehive.netui.util.config.bean.PageflowConfig;
 import org.apache.beehive.netui.util.logging.Logger;
 import org.apache.struts.Globals;
 import org.apache.struts.action.Action;
@@ -1907,20 +1909,51 @@
     }
     
     /**
-     * Set the no-cache headers for all responses.  This overrides the base 
Struts behavior to
-     * prevent caching entirely in iterative dev mode.
+     * Set the no-cache headers.  This overrides the base Struts behavior to 
prevent caching even for the pages.
      */
     protected void processNoCache( HttpServletRequest request, 
HttpServletResponse response )
     {
-        if ( moduleConfig.getControllerConfig().getNocache() || ! 
_servletContainerAdapter.isInProductionMode() )
+        //
+        // Set the no-cache headers if:
+        //    1) the module is configured for it, or
+        //    2) netui-config.xml has an "always" value for 
<pageflow-config><prevent-cache>, or
+        //    3) netui-config.xml has an "inDevMode" value for 
<pageflow-config><prevent-cache>, and we're not in
+        //       production mode.
+        //
+        boolean noCache = moduleConfig.getControllerConfig().getNocache();
+        
+        if ( ! noCache )
+        {
+            PageflowConfig pfConfig = 
ConfigUtil.getConfig().getPageflowConfig();
+            
+            if ( pfConfig != null )
+            {
+                PageflowConfig.PreventCache.Enum preventCache = 
pfConfig.getPreventCache();
+                
+                if ( preventCache != null )
+                {
+                    switch ( preventCache.intValue() )
+                    {
+                        case PageflowConfig.PreventCache.INT_ALWAYS:
+                            noCache = true;
+                            break;
+                        case PageflowConfig.PreventCache.INT_IN_DEV_MODE:
+                            noCache = ! 
_servletContainerAdapter.isInProductionMode();
+                            break;
+                    }
+                }
+            }
+        }
+        
+        if ( noCache )
         {
             //
-            // The call to PageFlowJspFilter.preventCache() will cause caching 
to be prevented
-            // even when we end up forwarding to a JSP.  Normally, no-cache 
headers are lost
+            // The call to PageFlowPageFilter.preventCache() will cause 
caching to be prevented
+            // even when we end up forwarding to a pagee.  Normally, no-cache 
headers are lost
             // when a server forward occurs.
             //
             ServletUtils.preventCache( response );
-            PageFlowJspFilter.preventCache( request );
+            PageFlowPageFilter.preventCache( request );
         }
     }
 

Modified: 
incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/JavaControlUtils.java
URL: 
http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/JavaControlUtils.java?view=diff&r1=154800&r2=154801
==============================================================================
--- 
incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/JavaControlUtils.java
 (original)
+++ 
incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/JavaControlUtils.java
 Mon Feb 21 22:31:48 2005
@@ -149,7 +149,8 @@
         
         try
         {
-            Object instance = Controls.instantiate( 
Thread.currentThread().getContextClassLoader(), controlClassName,  properties, 
beanContext, controlID );
+            Object instance = Controls.instantiate( 
Thread.currentThread().getContextClassLoader(), controlClassName, 
+                                                    properties, beanContext, 
controlID );
             assert instance instanceof ControlBean : 
instance.getClass().getName();
             return ( ControlBean ) instance;
         }

Modified: 
incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive/netui/tags/html/AnchorBase.java
URL: 
http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive/netui/tags/html/AnchorBase.java?view=diff&r1=154800&r2=154801
==============================================================================
--- 
incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive/netui/tags/html/AnchorBase.java
 (original)
+++ 
incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive/netui/tags/html/AnchorBase.java
 Mon Feb 21 22:31:48 2005
@@ -45,6 +45,7 @@
     private Form _form;                         // the nearest form
     private boolean _formSubmit = false;        // should the anchor submit an 
enclosing form?
     private PopupSupport _popupSupport = null;  // popup support, if the popup 
attribute is set to true
+    private boolean _disableOnClick = false;    // When clicked, this anchor 
will disable itself after being clicked.
 
     /**
      * Base support for the attribute tag.  This is overridden to prevent 
setting the <code>href</code>
@@ -195,8 +196,25 @@
     {
         _popupSupport = new PopupSupport();
     }
+    
+    
+    /**
+     * When true, this anchor will disable itself after being clicked.
+     * @param disableOnClick - when true, this anchor will disable itself 
after being clicked.
+     * @jsptagref.attributedescription Boolean.  If 
<code>disableOnClick</code> is set to true,
+     * the anchor will disable itself after being clicked.
+     * @jsptagref.databindable true
+     * @jsptagref.attributesyntaxvalue <i>boolean_disableOnClick</i>
+     * @netui:attribute required="false" rtexprvalue="true" type="boolean"
+     * description="When true, this anchor will disable itself after being 
clicked."
+     * @netui.tldx:attribute
+     */
+    public void setDisableOnClick(boolean disableOnClick)
+    {
+        _disableOnClick = disableOnClick;
+    }
 
-
+    
     /**
      * Sets the tabIndex of the rendered html tag.
      * @param tabindex - the tab index.
@@ -436,8 +454,8 @@
         if (onclick == null) {
             if (_formSubmit && formAction != null) {
                 String realFormName = getFormId();
-                String entry = 
ScriptRequestState.getString("anchorFormSubmitAction",
-                        new Object[]{realFormName, _state.href});
+                String key = (_disableOnClick ? 
"anchorDisableAndSubmitFormAction" : "anchorFormSubmitAction");
+                String entry = ScriptRequestState.getString(key, new 
Object[]{realFormName, _state.href});
                 _state.registerAttribute(AbstractHtmlState.ATTR_JAVASCRIPT, 
ONCLICK, entry);
                 // Jira 299
                 //_state.onClick = 
ScriptRequestState.getString("anchorFormSubmitAction",
@@ -445,6 +463,10 @@
                 if (_form != null)
                     _form.insureRealId();
             }
+            else if (_disableOnClick) {
+                String entry = 
ScriptRequestState.getString("anchorDisableAction", null);
+                _state.registerAttribute(AbstractHtmlState.ATTR_JAVASCRIPT, 
ONCLICK, entry);
+            }
             else if (_popupSupport != null) {
                 _state.registerAttribute(AbstractHtmlState.ATTR_JAVASCRIPT, 
ONCLICK, _popupSupport.getOnClick(_state.href));
                 // Jira 299
@@ -588,6 +610,7 @@
         _form = null;
         _formSubmit = false;
         _popupSupport = null;
+        _disableOnClick = false;
     }
 
     public PopupSupport getPopupSupport()

Modified: 
incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive/netui/tags/html/Button.java
URL: 
http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive/netui/tags/html/Button.java?view=diff&r1=154800&r2=154801
==============================================================================
--- 
incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive/netui/tags/html/Button.java
 (original)
+++ 
incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive/netui/tags/html/Button.java
 Mon Feb 21 22:31:48 2005
@@ -24,6 +24,8 @@
 import org.apache.beehive.netui.tags.HtmlUtils;
 import org.apache.beehive.netui.tags.IHtmlAccessable;
 import org.apache.beehive.netui.tags.javascript.ScriptRequestState;
+import org.apache.beehive.netui.tags.javascript.CoreScriptFeature;
+import org.apache.beehive.netui.tags.javascript.IScriptReporter;
 import org.apache.beehive.netui.tags.internal.PageFlowTagUtils;
 import org.apache.beehive.netui.tags.rendering.AbstractHtmlState;
 import org.apache.beehive.netui.tags.rendering.InputSubmitTag;
@@ -84,6 +86,7 @@
     private Map _params;                        // Any parameters to the submit
     private String _targetScope;                // Target page flow scope; see 
comments on setTargetScope()
     private PopupSupport _popupSupport = null;  // popup support, if the popup 
attribute is set to true
+    private boolean _disableOnClick = false;    // When clicked, this button 
will disable itself before submitting.
 
     /**
      * Return the name of the Tag.
@@ -202,13 +205,29 @@
      * @jsptagref.databindable true
      * @jsptagref.attributesyntaxvalue <i>boolean_popup</i>
      * @netui:attribute required="false" rtexprvalue="true" type="boolean"
-     * description="If popup is set to true, the button will open a popup 
window.
+     * description="If popup is set to true, the button will open a popup 
window."
      * @netui.tldx:attribute
      */
     public void setPopup(boolean popup)
     {
         _popupSupport = new PopupSupport();
     }
+    
+    /**
+     * When true, this button will disable itself before submitting.
+     * @param disableOnClick - when true, this button will disable itself 
before submitting.
+     * @jsptagref.attributedescription Boolean.  If 
<code>disableOnClick</code> is set to true,
+     * the button will disable itself before submitting.
+     * @jsptagref.databindable true
+     * @jsptagref.attributesyntaxvalue <i>boolean_disableOnClick</i>
+     * @netui:attribute required="false" rtexprvalue="true" type="boolean"
+     * description="When true, this button will disable itself before 
submitting."
+     * @netui.tldx:attribute
+     */
+    public void setDisableOnClick(boolean disableOnClick)
+    {
+        _disableOnClick = disableOnClick;
+    }
 
     /**
      * Adds a URL parameter to the generated hyperlink.
@@ -327,27 +346,30 @@
             idScript = renderNameAndId(request, _state, null);
         }
 
+        boolean buttonDisableAndSubmit = false;
+        boolean buttonDisable = false;
+        
         // if the user overrides the onclick we will ignore this
         if (getOnClick() == null) {
-            if (_popupSupport != null) {
-                String href = null;
-                if (_action != null) {
-                    ServletContext servletContext = 
pageContext.getServletContext();
-                    boolean forXML = TagRenderingBase.Factory.isXHTML(request);
-                    try {
-                        href = 
PageFlowUtils.getRewrittenActionURI(servletContext, request, response, _action, 
_params, null, forXML);
-                    } catch (URISyntaxException e) {
-                        // report the error...
-                        
logger.error(Bundle.getString("Tags_URISyntaxException"));
-                        String s = Bundle.getString("Tags_Button_URLException",
-                                                    new Object[]{_action, 
e.getMessage()});
-                        registerTagError(s, e);
-                    }
+            if (_disableOnClick) {
+                Form parentForm = getNearestForm();
+                String href = getActionUrl(request, response);
+                String entry;
+                if (parentForm != null && href != null && (_state.type == null 
|| _state.type == INPUT_SUBMIT)) {
+                    entry = 
ScriptRequestState.getString("buttonDisableAndSubmitFormAction",
+                        new Object[]{parentForm.getRealFormId(), href});
+                    buttonDisableAndSubmit = true;
                 }
                 else {
-                    Form parentForm = getNearestForm();
-                    href = HtmlUtils.addParams(parentForm.getActionUrl(), 
_params, response.getCharacterEncoding());
+                    entry = 
ScriptRequestState.getString("buttonDisableAction", null);
+                    buttonDisable = true;
                 }
+                _state.registerAttribute(AbstractHtmlState.ATTR_JAVASCRIPT, 
ONCLICK, entry);
+                if (parentForm != null)
+                    parentForm.insureRealId();
+            }
+            else if (_popupSupport != null) {
+                String href = getActionUrl(request, response);
                 
                 if (href != null) {
                     href = response.encodeURL(href);
@@ -366,11 +388,16 @@
         br.doEndTag(writer);
 
         //Emit javascript if this button needs to sumbit the form or open a 
popup window
-        if (idScript != null || _popupSupport != null) {
+        if (idScript != null || _popupSupport != null || buttonDisable || 
buttonDisableAndSubmit) {
             ScriptRequestState srs = 
ScriptRequestState.getScriptRequestState(request);
             StringBuilder script = new StringBuilder(32);
             StringBuilderRenderAppender scriptWriter = new 
StringBuilderRenderAppender(script);
+            IScriptReporter sr = getScriptReporter();
 
+            if (buttonDisableAndSubmit)
+                srs.writeFeature(sr, scriptWriter, 
CoreScriptFeature.BUTTON_DISABLE_AND_SUBMIT, true, false, null);
+            if (buttonDisable)
+                srs.writeFeature(sr, scriptWriter, 
CoreScriptFeature.BUTTON_DISABLE, true, false, null);
             if (_popupSupport != null)
                 _popupSupport.writeScript(request, srs, getScriptReporter(), 
scriptWriter);
             if (idScript != null)
@@ -383,6 +410,33 @@
         return EVAL_PAGE;
     }
 
+    private String getActionUrl(HttpServletRequest request, 
HttpServletResponse response)
+        throws JspException
+    {
+        String href = null;
+        
+        if (_action != null) {
+            ServletContext servletContext = pageContext.getServletContext();
+            boolean forXML = TagRenderingBase.Factory.isXHTML(request);
+            try {
+                href = PageFlowUtils.getRewrittenActionURI(servletContext, 
request, response, _action, _params, null, forXML);
+            } catch (URISyntaxException e) {
+                // report the error...
+                logger.error(Bundle.getString("Tags_URISyntaxException"));
+                String s = Bundle.getString("Tags_Button_URLException",
+                                            new Object[]{_action, 
e.getMessage()});
+                registerTagError(s, e);
+            }
+        }
+        else {
+            Form parentForm = getNearestForm();
+            if (parentForm != null)
+                href = HtmlUtils.addParams(parentForm.getActionUrl(), _params, 
response.getCharacterEncoding());
+        } 
+        
+        return href;
+    }
+    
     /**
      * Release any acquired resources.
      */
@@ -396,6 +450,7 @@
         _params = null;
         _targetScope = null;
         _popupSupport = null;
+        _disableOnClick = false;
     }
 
     /* ==================================================================

Modified: 
incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive/netui/tags/javascript/CoreScriptFeature.java
URL: 
http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive/netui/tags/javascript/CoreScriptFeature.java?view=diff&r1=154800&r2=154801
==============================================================================
--- 
incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive/netui/tags/javascript/CoreScriptFeature.java
 (original)
+++ 
incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive/netui/tags/javascript/CoreScriptFeature.java
 Mon Feb 21 22:31:48 2005
@@ -22,20 +22,22 @@
  */
 public enum CoreScriptFeature
 {
-    LEGACY_LOOKUP       (0x0001),
-    ID_LOOKUP           (0x0002),
-    NAME_LOOKUP         (0x0004),
-    SCOPE_LOOKUP        (0x0008),
-    ROLLOVER            (0x0010),
-    ANCHOR_SUBMIT       (0x0020),
-    POPUP_FUNC          (0x0040),
-    ALLOCATE_LEGACY     (0x0080),
-    ALLOCATE_ID         (0x0100),
-    ALLOCATE_NAME       (0x0200),
-    LEGACY_SCOPE_LOOKUP (0x0400),
-    TREE_INIT           (0x0800),
-    DIVPANEL_INIT       (0x1000),
-    DYNAMIC_INIT        (0x2000),
+    LEGACY_LOOKUP               (0x0001),
+    ID_LOOKUP                   (0x0002),
+    NAME_LOOKUP                 (0x0004),
+    SCOPE_LOOKUP                (0x0008),
+    ROLLOVER                    (0x0010),
+    ANCHOR_SUBMIT               (0x0020),
+    POPUP_FUNC                  (0x0040),
+    ALLOCATE_LEGACY             (0x0080),
+    ALLOCATE_ID                 (0x0100),
+    ALLOCATE_NAME               (0x0200),
+    LEGACY_SCOPE_LOOKUP         (0x0400),
+    TREE_INIT                   (0x0800),
+    DIVPANEL_INIT               (0x1000),
+    DYNAMIC_INIT                (0x2000),
+    BUTTON_DISABLE_AND_SUBMIT   (0x4000),
+    BUTTON_DISABLE              (0x8000),
 
     // These features are not written out once.  They are identified by 
setting the top bit
     SET_FOCUS           (0x10000001);

Modified: 
incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive/netui/tags/javascript/ScriptRequestState.java
URL: 
http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive/netui/tags/javascript/ScriptRequestState.java?view=diff&r1=154800&r2=154801
==============================================================================
--- 
incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive/netui/tags/javascript/ScriptRequestState.java
 (original)
+++ 
incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive/netui/tags/javascript/ScriptRequestState.java
 Mon Feb 21 22:31:48 2005
@@ -292,6 +292,10 @@
                 return "initDivPanel";
             case DYNAMIC_INIT:
                 return "writeWebAppName";
+            case BUTTON_DISABLE_AND_SUBMIT:
+                return "buttonDisableAndSubmitForm";
+            case BUTTON_DISABLE:
+                return "buttonDisable";
         }
         assert(false) : "getFeature fell through on feature:" + feature;
         return null;

Modified: 
incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive/netui/tags/javascript/javaScript.properties
URL: 
http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive/netui/tags/javascript/javaScript.properties?view=diff&r1=154800&r2=154801
==============================================================================
--- 
incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive/netui/tags/javascript/javaScript.properties
 (original)
+++ 
incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive/netui/tags/javascript/javaScript.properties
 Mon Feb 21 22:31:48 2005
@@ -30,6 +30,48 @@
 legacyAnchorFormSubmitAction=anchor_submit_form("{0}","{1}");return false;
 anchorFormSubmitAction=anchor_submit_form(''{0}'',''{1}'');return false;
 
+# The action event that will call the form submit javascript only if this link 
has not been clicked.
+anchorDisableAndSubmitFormAction=if (this.clicked) return false; 
anchor_submit_form(''{0}'',''{1}''); \
+this.clicked=true; return false;
+
+# The action event that will disable the anchor after it has been clicked.
+anchorDisableAction=if (this.clicked) return false; this.clicked=true;
+
+# generic method to disable a button and submit a form, used by Button.
+# The following method will be written out once an may be called by
+# multiple buttons.  The event JavaScript is defined following it.
+buttonDisableAndSubmitForm=\
+// submit the form from an Button after disabling the Button\n\
+// Search for the form by actionName,\n\
+// Replace the action with the passed in action\n\
+// Submit the form\n\
+function button_disable_and_submit_form(button, netuiName, newAction)\n\
+{\n\
+\  button.disabled = true;\n\
+\  for (var i=0; i<document.forms.length; i++) {\n\
+\     if (document.forms[i].id == netuiName) {\n\
+\        document.forms[i].method = "POST";\n\
+\        document.forms[i].action = newAction;\n\
+\        document.forms[i].submit();\n\
+\     }\n\
+\   }\n\
+}\n
+
+# The action event that will call the form submit javascript
+buttonDisableAndSubmitFormAction=button_disable_and_submit_form(this,''{0}'',''{1}'');return
 false;
+
+# generic method to disable a Button, used by Button.
+# The following method will be written out once an may be called by
+# multiple buttons.  The event JavaScript is defined following it.
+buttonDisable=\
+function button_disable(button)\n\
+{\n\
+\  button.disabled = true;\n\
+}\n
+
+# The action event that will call the form submit javascript
+buttonDisableAction=button_disable(this);return false;
+
 # generic method to open a popup window
 popupFunc=\
 function netui_popup(url, name, features, replace)\n\

Modified: 
incubator/beehive/trunk/netui/src/util/schema/netui-config/netui-config.xsd
URL: 
http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/util/schema/netui-config/netui-config.xsd?view=diff&r1=154800&r2=154801
==============================================================================
--- incubator/beehive/trunk/netui/src/util/schema/netui-config/netui-config.xsd 
(original)
+++ incubator/beehive/trunk/netui/src/util/schema/netui-config/netui-config.xsd 
Mon Feb 21 22:31:48 2005
@@ -132,6 +132,15 @@
                     </xsd:restriction>
                 </xsd:simpleType>
             </xsd:element>
+            <xsd:element name="prevent-cache" minOccurs="0" maxOccurs="1" 
default="default">
+                <xsd:simpleType>
+                    <xsd:restriction base="xsd:string">
+                        <xsd:enumeration value="default"/>
+                        <xsd:enumeration value="always"/>
+                        <xsd:enumeration value="inDevMode"/>
+                    </xsd:restriction>
+                </xsd:simpleType>
+            </xsd:element>
             <xsd:element name="module-config-locators" 
type="netui:module-config-locators" minOccurs="0" maxOccurs="1"/>
         </xsd:sequence>
     </xsd:complexType>

Added: 
incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/tags/disableOnClick/Controller.jpf
URL: 
http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/tags/disableOnClick/Controller.jpf?view=auto&rev=154801
==============================================================================
--- 
incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/tags/disableOnClick/Controller.jpf
 (added)
+++ 
incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/tags/disableOnClick/Controller.jpf
 Mon Feb 21 22:31:48 2005
@@ -0,0 +1,40 @@
+package tags.disableOnClick;
+
+import org.apache.beehive.netui.pageflow.*;
+import org.apache.beehive.netui.pageflow.annotations.*;
+
[EMAIL PROTECTED](
+    simpleActions={
+        @Jpf.SimpleAction(name="begin", path="index.jsp")
+    }
+)
+public class Controller extends PageFlowController
+{
+    private static int count = 0;
+
+    @Jpf.Action(
+        forwards={
+            @Jpf.Forward(name="index", path="index.jsp")
+        }
+    )
+    public Forward someAction()
+        throws InterruptedException
+    {
+        System.err.println( "****** in someAction " + ++count );
+        Thread.sleep( 3000 );
+        return new Forward( "index" );
+    }
+
+    @Jpf.Action(
+        forwards={
+            @Jpf.Forward(name="index", path="index.jsp")
+        }
+    )
+    public Forward anotherAction()
+        throws InterruptedException
+    {
+        System.err.println( "****** in anotherAction " + ++count );
+        Thread.sleep( 3000 );
+        return new Forward( "index" );
+    }
+}

Propchange: 
incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/tags/disableOnClick/Controller.jpf
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/tags/disableOnClick/cool.gif
URL: 
http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/tags/disableOnClick/cool.gif?view=auto&rev=154801
==============================================================================
Binary file - no diff available.

Propchange: 
incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/tags/disableOnClick/cool.gif
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: 
incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/tags/disableOnClick/index.jsp
URL: 
http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/tags/disableOnClick/index.jsp?view=auto&rev=154801
==============================================================================
--- 
incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/tags/disableOnClick/index.jsp
 (added)
+++ 
incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/tags/disableOnClick/index.jsp
 Mon Feb 21 22:31:48 2005
@@ -0,0 +1,45 @@
+<%@ page language="java" contentType="text/html;charset=UTF-8"%>
+<%@ taglib prefix="netui" uri="http://beehive.apache.org/netui/tags-html-1.0"%>
+<%@ taglib prefix="netui-data" 
uri="http://beehive.apache.org/netui/tags-databinding-1.0"%>
+<%@ taglib prefix="netui-template" 
uri="http://beehive.apache.org/netui/tags-template-1.0"%>
+
+
+<netui:html>
+    <head>
+        <netui:base/>
+    </head>
+    <netui:body>
+        <h3>${pageFlow.URI}</h3>
+
+        This test merely verifies that the right JavaScript is rendered; it 
can't actually test the disabling behavior.
+        <br/>
+        <br/>
+        <netui:form action="someAction">
+            <netui:button value="submit"/>
+            <br/>
+            <netui:button value="submit (disableOnClick)" 
disableOnClick="true"/>
+            <br/>
+            <br/>
+            <netui:button value="submit with action override" 
action="anotherAction"/>
+            <br/>
+            <netui:button value="submit with action override (disableOnClick)" 
action="anotherAction" disableOnClick="true"/>
+            <br/>
+            <br/>
+            <netui:anchor formSubmit="true">submit</netui:anchor>
+            <br/>
+            <netui:anchor formSubmit="true" disableOnClick="true">submit 
(disableOnClick)</netui:anchor>
+        </netui:form>
+
+        <netui:anchor action="someAction">non-submit</netui:anchor>
+        <br/>
+        <netui:anchor action="someAction" disableOnClick="true">non-submit 
(disableOnClick)</netui:anchor>
+        <br/>
+        <br/>
+        non-submit: <netui:imageAnchor action="someAction" src="cool.gif"/>
+        <br/>
+        non-submit (disableOnClick): <netui:imageAnchor action="someAction" 
disableOnClick="true" src="cool.gif"/>
+    </netui:body>
+</netui:html>
+
+  
+

Propchange: 
incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/tags/disableOnClick/index.jsp
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: 
incubator/beehive/trunk/netui/test/webapps/drt/testRecorder/config/testRecorder-tests.xml
URL: 
http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/test/webapps/drt/testRecorder/config/testRecorder-tests.xml?view=diff&r1=154800&r2=154801
==============================================================================
--- 
incubator/beehive/trunk/netui/test/webapps/drt/testRecorder/config/testRecorder-tests.xml
 (original)
+++ 
incubator/beehive/trunk/netui/test/webapps/drt/testRecorder/config/testRecorder-tests.xml
 Mon Feb 21 22:31:48 2005
@@ -3252,6 +3252,23 @@
          </features>
       </test>
       <test>
+         <name>DisableOnClick</name>
+         <description>Test of the rendered JavaScript for disabling anchors, 
imageAnchors and buttons when they are clicked.</description>
+         <webapp>coreWeb</webapp>
+         <categories>
+            <category>bvt</category>
+            <category>bvt.struts11</category>
+            <category>tags</category>
+         </categories>
+         <features>
+            <feature>Anchor</feature>
+            <feature>Button</feature>
+            <feature>Form</feature>
+            <feature>ImageAnchor</feature>
+            <feature>JavaScript</feature>
+         </features>
+      </test>
+      <test>
          <name>DivPanel</name>
          <description>Basic test of the DivPanel</description>
          <webapp>coreWeb</webapp>

Added: 
incubator/beehive/trunk/netui/test/webapps/drt/testRecorder/tests/DisableOnClick.xml
URL: 
http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/test/webapps/drt/testRecorder/tests/DisableOnClick.xml?view=auto&rev=154801
==============================================================================
--- 
incubator/beehive/trunk/netui/test/webapps/drt/testRecorder/tests/DisableOnClick.xml
 (added)
+++ 
incubator/beehive/trunk/netui/test/webapps/drt/testRecorder/tests/DisableOnClick.xml
 Mon Feb 21 22:31:48 2005
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ses:recorderSession 
xmlns:ses="http://beehive.apache.org/netui/tools/testrecorder/2004/session";>
+   <ses:sessionName>DisableOnClick</ses:sessionName>
+   <ses:tester>rich</ses:tester>
+   <ses:startDate>21 Feb 2005, 10:23:51.042 PM MST</ses:startDate>
+   <ses:description>Test of the rendered JavaScript for disabling anchors, 
imageAnchors and buttons when they are clicked.</ses:description>
+   <ses:tests>
+      <ses:test>
+         <ses:testNumber>1</ses:testNumber>
+         <ses:request>
+            <ses:protocol>HTTP</ses:protocol>
+            <ses:protocolVersion>1.1</ses:protocolVersion>
+            <ses:host>localhost</ses:host>
+            <ses:port>8080</ses:port>
+            <ses:uri>/coreWeb/tags/disableOnClick/Controller.jpf</ses:uri>
+            <ses:method>GET</ses:method>
+            <ses:parameters/>
+            <ses:cookies>
+               <ses:cookie>
+                  <ses:name>JSESSIONID</ses:name>
+                  <ses:value>6A62187DDD224AFCABABC688F6FAA7C5</ses:value>
+               </ses:cookie>
+            </ses:cookies>
+            <ses:headers>
+               <ses:header>
+                  <ses:name>accept</ses:name>
+                  
<ses:value>text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5</ses:value>
+               </ses:header>
+               <ses:header>
+                  <ses:name>accept-charset</ses:name>
+                  <ses:value>ISO-8859-1,utf-8;q=0.7,*;q=0.7</ses:value>
+               </ses:header>
+               <ses:header>
+                  <ses:name>accept-encoding</ses:name>
+                  <ses:value>gzip,deflate</ses:value>
+               </ses:header>
+               <ses:header>
+                  <ses:name>accept-language</ses:name>
+                  <ses:value>en-us,en;q=0.5</ses:value>
+               </ses:header>
+               <ses:header>
+                  <ses:name>connection</ses:name>
+                  <ses:value>keep-alive</ses:value>
+               </ses:header>
+               <ses:header>
+                  <ses:name>cookie</ses:name>
+                  
<ses:value>JSESSIONID=6A62187DDD224AFCABABC688F6FAA7C5</ses:value>
+               </ses:header>
+               <ses:header>
+                  <ses:name>host</ses:name>
+                  <ses:value>localhost:8080</ses:value>
+               </ses:header>
+               <ses:header>
+                  <ses:name>keep-alive</ses:name>
+                  <ses:value>300</ses:value>
+               </ses:header>
+               <ses:header>
+                  <ses:name>user-agent</ses:name>
+                  <ses:value>Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; 
rv:1.7.5) Gecko/20041107 Firefox/1.0</ses:value>
+               </ses:header>
+            </ses:headers>
+         </ses:request>
+         <ses:response>
+            <ses:statusCode>200</ses:statusCode>
+            <ses:reason/>
+            <ses:responseBody>&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 
Transitional//EN"
+       "http://www.w3.org/TR/html4/loose.dtd";>
+&lt;html lang="en">
+
+    &lt;head>
+        &lt;base 
href="http://localhost:8080/coreWeb/tags/disableOnClick/index.jsp";>
+    &lt;/head>
+    &lt;body>
+        &lt;h3>/tags/disableOnClick/Controller.jpf&lt;/h3>
+
+        This test merely verifies that the right JavaScript is rendered; it 
can't actually test the disabling behavior.
+        &lt;br/>
+        &lt;br/>
+        &lt;form name="Netui_Form_0" id="Netui_Form_0" 
action="/coreWeb/tags/disableOnClick/someAction.do" method="post">
+            &lt;input type="submit" value="submit">
+            &lt;br/>
+            &lt;input type="submit" value="submit (disableOnClick)" 
onclick="button_disable_and_submit_form(this,'Netui_Form_0','/coreWeb/tags/disableOnClick/someAction.do');return
 false;">
+            &lt;br/>
+            &lt;br/>
+            &lt;input type="submit" name="actionOverride:anotherAction" 
value="submit with action override">
+            &lt;br/>
+            &lt;input type="submit" name="actionOverride:anotherAction" 
value="submit with action override (disableOnClick)" 
onclick="button_disable_and_submit_form(this,'Netui_Form_0','/coreWeb/tags/disableOnClick/anotherAction.do');return
 false;">
+            &lt;br/>
+            &lt;br/>
+            &lt;a href="/coreWeb/tags/disableOnClick/someAction.do" 
onclick="anchor_submit_form('Netui_Form_0','/coreWeb/tags/disableOnClick/someAction.do');return
 false;">submit&lt;/a>
+            &lt;br/>
+            &lt;a href="/coreWeb/tags/disableOnClick/someAction.do" 
onclick="if (this.clicked) return false; 
anchor_submit_form('Netui_Form_0','/coreWeb/tags/disableOnClick/someAction.do');
 this.clicked=true; return false;">submit (disableOnClick)&lt;/a>
+        &lt;/form>
+
+        &lt;a 
href="/coreWeb/tags/disableOnClick/someAction.do">non-submit&lt;/a>
+        &lt;br/>
+        &lt;a href="/coreWeb/tags/disableOnClick/someAction.do" onclick="if 
(this.clicked) return false; this.clicked=true;">non-submit 
(disableOnClick)&lt;/a>
+        &lt;br/>
+        &lt;br/>
+        non-submit: &lt;a 
href="/coreWeb/tags/disableOnClick/someAction.do">&lt;img 
src="/coreWeb/tags/disableOnClick/cool.gif">&lt;/a>
+        &lt;br/>
+        non-submit (disableOnClick): &lt;a 
href="/coreWeb/tags/disableOnClick/someAction.do" onclick="if (this.clicked) 
return false; this.clicked=true;">&lt;img 
src="/coreWeb/tags/disableOnClick/cool.gif">&lt;/a>
+    &lt;script language="JavaScript" type="text/JavaScript">
+&lt;!--
+
+// **** Start the NetUI Framework Generated JavaScript ****
+
+// submit the form from an Button after disabling the Button
+// Search for the form by actionName,
+// Replace the action with the passed in action
+// Submit the form
+function button_disable_and_submit_form(button, netuiName, newAction)
+{
+  button.disabled = true;
+  for (var i=0; i&lt;document.forms.length; i++) {
+     if (document.forms[i].id == netuiName) {
+        document.forms[i].method = "POST";
+        document.forms[i].action = newAction;
+        document.forms[i].submit();
+     }
+   }
+}
+
+// submit the form from an Anchor or ImageAnchor
+// Search for the form by actionName,
+// Replace the action with the passed in action
+// Submit the form
+function anchor_submit_form(netuiName, newAction)
+{
+  for (var i=0; i&lt;document.forms.length; i++) {
+     if (document.forms[i].id == netuiName) {
+        document.forms[i].method = "POST";
+        document.forms[i].action = newAction;
+        document.forms[i].submit();
+     }
+   }
+}
+-->
+&lt;/script>&lt;/body>
+
+&lt;/html></ses:responseBody>
+         </ses:response>
+      </ses:test>
+   </ses:tests>
+   <ses:endDate>21 Feb 2005, 10:24:00.566 PM MST</ses:endDate>
+   <ses:testCount>1</ses:testCount>
+</ses:recorderSession>

Propchange: 
incubator/beehive/trunk/netui/test/webapps/drt/testRecorder/tests/DisableOnClick.xml
------------------------------------------------------------------------------
    svn:eol-style = native


Reply via email to