]> source.dussan.org Git - vaadin-framework.git/commitdiff
#6444 Ability to disable button on click
authorArtur Signell <artur.signell@itmill.com>
Mon, 18 Jul 2011 13:08:21 +0000 (13:08 +0000)
committerArtur Signell <artur.signell@itmill.com>
Mon, 18 Jul 2011 13:08:21 +0000 (13:08 +0000)
svn changeset:19820/svn branch:6.7

src/com/vaadin/terminal/gwt/client/ui/VButton.java
src/com/vaadin/terminal/gwt/client/ui/VNativeButton.java
src/com/vaadin/ui/Button.java
src/com/vaadin/ui/CheckBox.java
tests/src/com/vaadin/tests/components/button/ButtonDisableOnClick.html [new file with mode: 0644]
tests/src/com/vaadin/tests/components/button/Buttons2.java
tests/src/com/vaadin/tests/components/nativebutton/NativeButtonDisableOnClick.html [new file with mode: 0644]

index 46492a707c3b52d239fbf66384544df6e4066890..1cb2a92e2e15bc44b8449a45b3292025820514f7 100644 (file)
@@ -35,6 +35,8 @@ public class VButton extends FocusWidget implements Paintable, ClickHandler,
     public static final String CLASSNAME = "v-button";
     private static final String CLASSNAME_PRESSED = "v-pressed";
 
+    public static final String ATTR_DISABLE_ON_CLICK = "dc";
+
     // mouse movement is checked before synthesizing click event on mouseout
     protected static int MOVE_THRESHOLD = 3;
     protected int mousedownX = 0;
@@ -63,6 +65,8 @@ public class VButton extends FocusWidget implements Paintable, ClickHandler,
 
     private int tabIndex = 0;
 
+    private boolean disableOnClick = false;
+
     /*
      * BELOW PRIVATE MEMBERS COPY-PASTED FROM GWT CustomButton
      */
@@ -129,6 +133,8 @@ public class VButton extends FocusWidget implements Paintable, ClickHandler,
         // Set text
         setText(uidl.getStringAttribute("caption"));
 
+        disableOnClick = uidl.hasAttribute(ATTR_DISABLE_ON_CLICK);
+
         // handle error
         if (uidl.hasAttribute("error")) {
             if (errorIndicatorElement == null) {
@@ -354,6 +360,11 @@ public class VButton extends FocusWidget implements Paintable, ClickHandler,
         if (BrowserInfo.get().isSafari()) {
             VButton.this.setFocus(true);
         }
+        if (disableOnClick) {
+            setEnabled(false);
+            client.updateVariable(id, "disabledOnClick", true, false);
+        }
+
         client.updateVariable(id, "state", true, false);
 
         // Add mouse details
index 49b878f611f8a51baddf0577324dc290f5d4b4d7..8ea2e1a68874d54f3c0f4d3f8b4e42203936471f 100644 (file)
@@ -54,6 +54,8 @@ public class VNativeButton extends Button implements Paintable, ClickHandler,
     private HandlerRegistration focusHandlerRegistration;
     private HandlerRegistration blurHandlerRegistration;
 
+    private boolean disableOnClick = false;
+
     public VNativeButton() {
         setStyleName(CLASSNAME);
 
@@ -75,6 +77,8 @@ public class VNativeButton extends Button implements Paintable, ClickHandler,
             return;
         }
 
+        disableOnClick = uidl.hasAttribute(VButton.ATTR_DISABLE_ON_CLICK);
+
         focusHandlerRegistration = EventHelper.updateFocusHandler(this, client,
                 focusHandlerRegistration);
         blurHandlerRegistration = EventHelper.updateBlurHandler(this, client,
@@ -201,6 +205,10 @@ public class VNativeButton extends Button implements Paintable, ClickHandler,
         if (BrowserInfo.get().isSafari()) {
             VNativeButton.this.setFocus(true);
         }
+        if (disableOnClick) {
+            setEnabled(false);
+            client.updateVariable(id, "disabledOnClick", true, false);
+        }
 
         // Add mouse details
         MouseEventDetails details = new MouseEventDetails(
index 122d155e0f091dc249d6836d1f24679d4aa07adc..16314f94c3704a3fafe79d80b431470c03ab97a5 100644 (file)
@@ -43,6 +43,8 @@ public class Button extends AbstractField implements FieldEvents.BlurNotifier,
 
     boolean switchMode = false;
 
+    boolean disableOnClick = false;
+
     /**
      * Creates a new push button. The value of the push button is false and it
      * is immediate by default.
@@ -148,6 +150,9 @@ public class Button extends AbstractField implements FieldEvents.BlurNotifier,
         }
         target.addVariable(this, "state", booleanValue());
 
+        if (isDisableOnClick()) {
+            target.addAttribute(VButton.ATTR_DISABLE_ON_CLICK, true);
+        }
         if (clickShortcut != null) {
             target.addAttribute("keycode", clickShortcut.getKeyCode());
         }
@@ -164,6 +169,12 @@ public class Button extends AbstractField implements FieldEvents.BlurNotifier,
     public void changeVariables(Object source, Map<String, Object> variables) {
         super.changeVariables(source, variables);
 
+        if (variables.containsKey("disabledOnClick")) {
+            // Could be optimized so the button is not repainted because of this
+            // (client side has already disabled the button)
+            setEnabled(false);
+        }
+
         if (!isReadOnly() && variables.containsKey("state")) {
             // Gets the new and old button states
             final Boolean newValue = (Boolean) variables.get("state");
@@ -651,4 +662,27 @@ public class Button extends AbstractField implements FieldEvents.BlurNotifier,
         }
     }
 
+    /**
+     * Determines if a button is automatically disabled when clicked. See
+     * {@link #setDisableOnClick(boolean)} for details.
+     * 
+     * @return true if the button is disabled when clicked, false otherwise
+     */
+    public boolean isDisableOnClick() {
+        return disableOnClick;
+    }
+
+    /**
+     * Determines if a button is automatically disabled when clicked. If this is
+     * set to true the button will be automatically disabled when clicked,
+     * typically to prevent (accidental) extra clicks on a button.
+     * 
+     * @param disableOnClick
+     *            true to disable button when it is clicked, false otherwise
+     */
+    public void setDisableOnClick(boolean disableOnClick) {
+        this.disableOnClick = disableOnClick;
+        requestRepaint();
+    }
+
 }
index 93138e10c0ca39cdd9f247a367a79289d0d61479..b9ae236cb0e24be4983ca6f7ea87303a253154b5 100644 (file)
@@ -104,4 +104,10 @@ public class CheckBox extends Button {
         super.setSwitchMode(true);
     }
 
+    @Override
+    public void setDisableOnClick(boolean disableOnClick) {
+        throw new UnsupportedOperationException(
+                "CheckBox does not support disable on click");
+    }
+
 }
diff --git a/tests/src/com/vaadin/tests/components/button/ButtonDisableOnClick.html b/tests/src/com/vaadin/tests/components/button/ButtonDisableOnClick.html
new file mode 100644 (file)
index 0000000..850d553
--- /dev/null
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="http://localhost:8888/" />
+<title>New Test</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">New Test</td></tr>
+</thead><tbody>
+<tr>
+       <td>open</td>
+       <td>/run/com.vaadin.tests.components.button.Buttons2?restartApplication</td>
+       <td></td>
+</tr>
+<!--value change listener-->
+<tr>
+       <td>mouseClick</td>
+       <td>vaadin=runcomvaadintestscomponentsbuttonButtons2::PID_Smenu#item0</td>
+       <td>37,10</td>
+</tr>
+<tr>
+       <td>mouseClick</td>
+       <td>vaadin=runcomvaadintestscomponentsbuttonButtons2::Root/VOverlay[0]/VMenuBar[0]#item3</td>
+       <td>28,7</td>
+</tr>
+<tr>
+       <td>mouseClick</td>
+       <td>vaadin=runcomvaadintestscomponentsbuttonButtons2::Root/VOverlay[1]/VMenuBar[0]#item4</td>
+       <td>35,8</td>
+</tr>
+<!--disable on click-->
+<tr>
+       <td>mouseClick</td>
+       <td>vaadin=runcomvaadintestscomponentsbuttonButtons2::PID_Smenu#item0</td>
+       <td>39,10</td>
+</tr>
+<tr>
+       <td>mouseClick</td>
+       <td>vaadin=runcomvaadintestscomponentsbuttonButtons2::Root/VOverlay[0]/VMenuBar[0]#item4</td>
+       <td>33,7</td>
+</tr>
+<tr>
+       <td>mouseClick</td>
+       <td>vaadin=runcomvaadintestscomponentsbuttonButtons2::Root/VOverlay[1]/VMenuBar[0]#item1</td>
+       <td>22,4</td>
+</tr>
+<tr>
+       <td>assertText</td>
+       <td>vaadin=runcomvaadintestscomponentsbuttonButtons2::PID_SLog_row_0</td>
+       <td>1. Command: /Disable on click(true)</td>
+</tr>
+<!--click button-->
+<tr>
+       <td>click</td>
+       <td>vaadin=runcomvaadintestscomponentsbuttonButtons2::PID_StestComponent/domChild[0]/domChild[0]</td>
+       <td></td>
+</tr>
+<tr>
+       <td>assertCSSClass</td>
+       <td>vaadin=runcomvaadintestscomponentsbuttonButtons2::PID_StestComponent</td>
+       <td>v-disabled</td>
+</tr>
+<tr>
+       <td>assertText</td>
+       <td>vaadin=runcomvaadintestscomponentsbuttonButtons2::PID_SLog_row_0</td>
+       <td>2. ClickEvent</td>
+</tr>
+<tr>
+       <td>click</td>
+       <td>vaadin=runcomvaadintestscomponentsbuttonButtons2::PID_StestComponent/domChild[0]/domChild[0]</td>
+       <td></td>
+</tr>
+<tr>
+       <td>assertText</td>
+       <td>vaadin=runcomvaadintestscomponentsbuttonButtons2::PID_SLog_row_0</td>
+       <td>2. ClickEvent</td>
+</tr>
+<!--re-enable-->
+<tr>
+       <td>mouseClick</td>
+       <td>vaadin=runcomvaadintestscomponentsbuttonButtons2::PID_Smenu#item0</td>
+       <td>35,13</td>
+</tr>
+<tr>
+       <td>mouseClick</td>
+       <td>vaadin=runcomvaadintestscomponentsbuttonButtons2::Root/VOverlay[0]/VMenuBar[0]#item0</td>
+       <td>34,12</td>
+</tr>
+<tr>
+       <td>mouseClick</td>
+       <td>vaadin=runcomvaadintestscomponentsbuttonButtons2::Root/VOverlay[1]/VMenuBar[0]#item1</td>
+       <td>15,13</td>
+</tr>
+<tr>
+       <td>mouseClick</td>
+       <td>vaadin=runcomvaadintestscomponentsbuttonButtons2::PID_Smenu#item0</td>
+       <td>43,4</td>
+</tr>
+<tr>
+       <td>mouseClick</td>
+       <td>vaadin=runcomvaadintestscomponentsbuttonButtons2::Root/VOverlay[0]/VMenuBar[0]#item0</td>
+       <td>37,8</td>
+</tr>
+<tr>
+       <td>mouseClick</td>
+       <td>vaadin=runcomvaadintestscomponentsbuttonButtons2::Root/VOverlay[1]/VMenuBar[0]#item1</td>
+       <td>33,6</td>
+</tr>
+<tr>
+       <td>assertText</td>
+       <td>vaadin=runcomvaadintestscomponentsbuttonButtons2::PID_SLog_row_0</td>
+       <td>4. Command: /Enabled(true)</td>
+</tr>
+<tr>
+       <td>assertNotCSSClass</td>
+       <td>vaadin=runcomvaadintestscomponentsbuttonButtons2::PID_StestComponent</td>
+       <td>v-disabled</td>
+</tr>
+<!--no longer disable on click-->
+<tr>
+       <td>mouseClick</td>
+       <td>vaadin=runcomvaadintestscomponentsbuttonButtons2::PID_Smenu#item0</td>
+       <td>25,9</td>
+</tr>
+<tr>
+       <td>mouseClick</td>
+       <td>vaadin=runcomvaadintestscomponentsbuttonButtons2::Root/VOverlay[0]/VMenuBar[0]#item4</td>
+       <td>39,13</td>
+</tr>
+<tr>
+       <td>mouseClick</td>
+       <td>vaadin=runcomvaadintestscomponentsbuttonButtons2::Root/VOverlay[1]/VMenuBar[0]#item1</td>
+       <td>36,3</td>
+</tr>
+<tr>
+       <td>click</td>
+       <td>vaadin=runcomvaadintestscomponentsbuttonButtons2::PID_StestComponent/domChild[0]/domChild[0]</td>
+       <td></td>
+</tr>
+<tr>
+       <td>assertText</td>
+       <td>vaadin=runcomvaadintestscomponentsbuttonButtons2::PID_SLog_row_0</td>
+       <td>6. ClickEvent</td>
+</tr>
+<tr>
+       <td>assertNotCSSClass</td>
+       <td>vaadin=runcomvaadintestscomponentsbuttonButtons2::PID_StestComponent</td>
+       <td>v-disabled</td>
+</tr>
+
+</tbody></table>
+</body>
+</html>
index 491e19919ca9f159b2edd73fc3774e65400009f2..c18e73608240baca43d429f73275b755d2d1f053 100644 (file)
@@ -19,6 +19,13 @@ public class Buttons2<T extends Button> extends AbstractFieldTest<T> implements
         }\r
     };\r
 \r
+    private Command<T, Boolean> disableOnClickCommand = new Command<T, Boolean>() {\r
+\r
+        public void execute(T c, Boolean value, Object data) {\r
+            c.setDisableOnClick(value);\r
+        }\r
+    };\r
+\r
     private Command<T, Boolean> clickListenerCommand = new Command<T, Boolean>() {\r
 \r
         public void execute(T c, Boolean value, Object data) {\r
@@ -42,6 +49,8 @@ public class Buttons2<T extends Button> extends AbstractFieldTest<T> implements
 \r
         createBooleanAction("Switch mode", CATEGORY_FEATURES, false,\r
                 switchModeCommand);\r
+        createBooleanAction("Disable on click", CATEGORY_FEATURES, false,\r
+                disableOnClickCommand);\r
         addClickListener(CATEGORY_LISTENERS);\r
     }\r
 \r
diff --git a/tests/src/com/vaadin/tests/components/nativebutton/NativeButtonDisableOnClick.html b/tests/src/com/vaadin/tests/components/nativebutton/NativeButtonDisableOnClick.html
new file mode 100644 (file)
index 0000000..75eab71
--- /dev/null
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="http://localhost:8888/" />
+<title>New Test</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">New Test</td></tr>
+</thead><tbody>
+<tr>
+       <td>open</td>
+       <td>/run/com.vaadin.tests.components.nativebutton.NativeButtonTest?restartApplication</td>
+       <td></td>
+</tr>
+<!--value change listener-->
+<tr>
+       <td>mouseClick</td>
+       <td>vaadin=runcomvaadintestscomponentsnativebuttonNativeButtonTest::PID_Smenu#item0</td>
+       <td>37,10</td>
+</tr>
+<tr>
+       <td>mouseClick</td>
+       <td>vaadin=runcomvaadintestscomponentsnativebuttonNativeButtonTest::Root/VOverlay[0]/VMenuBar[0]#item3</td>
+       <td>28,7</td>
+</tr>
+<tr>
+       <td>mouseClick</td>
+       <td>vaadin=runcomvaadintestscomponentsnativebuttonNativeButtonTest::Root/VOverlay[1]/VMenuBar[0]#item4</td>
+       <td>35,8</td>
+</tr>
+<!--disable on click-->
+<tr>
+       <td>mouseClick</td>
+       <td>vaadin=runcomvaadintestscomponentsnativebuttonNativeButtonTest::PID_Smenu#item0</td>
+       <td>39,10</td>
+</tr>
+<tr>
+       <td>mouseClick</td>
+       <td>vaadin=runcomvaadintestscomponentsnativebuttonNativeButtonTest::Root/VOverlay[0]/VMenuBar[0]#item4</td>
+       <td>33,7</td>
+</tr>
+<tr>
+       <td>mouseClick</td>
+       <td>vaadin=runcomvaadintestscomponentsnativebuttonNativeButtonTest::Root/VOverlay[1]/VMenuBar[0]#item1</td>
+       <td>22,4</td>
+</tr>
+<tr>
+       <td>assertText</td>
+       <td>vaadin=runcomvaadintestscomponentsnativebuttonNativeButtonTest::PID_SLog_row_0</td>
+       <td>1. Command: /Disable on click(true)</td>
+</tr>
+<!--click button-->
+<tr>
+       <td>click</td>
+       <td>vaadin=runcomvaadintestscomponentsnativebuttonNativeButtonTest::PID_StestComponent</td>
+       <td></td>
+</tr>
+<tr>
+       <td>assertCSSClass</td>
+       <td>vaadin=runcomvaadintestscomponentsnativebuttonNativeButtonTest::PID_StestComponent</td>
+       <td>v-disabled</td>
+</tr>
+<tr>
+       <td>assertText</td>
+       <td>vaadin=runcomvaadintestscomponentsnativebuttonNativeButtonTest::PID_SLog_row_0</td>
+       <td>2. ClickEvent</td>
+</tr>
+<tr>
+       <td>click</td>
+       <td>vaadin=runcomvaadintestscomponentsnativebuttonNativeButtonTest::PID_StestComponent</td>
+       <td></td>
+</tr>
+<tr>
+       <td>assertText</td>
+       <td>vaadin=runcomvaadintestscomponentsnativebuttonNativeButtonTest::PID_SLog_row_0</td>
+       <td>2. ClickEvent</td>
+</tr>
+<!--re-enable-->
+<tr>
+       <td>mouseClick</td>
+       <td>vaadin=runcomvaadintestscomponentsnativebuttonNativeButtonTest::PID_Smenu#item0</td>
+       <td>35,13</td>
+</tr>
+<tr>
+       <td>mouseClick</td>
+       <td>vaadin=runcomvaadintestscomponentsnativebuttonNativeButtonTest::Root/VOverlay[0]/VMenuBar[0]#item0</td>
+       <td>34,12</td>
+</tr>
+<tr>
+       <td>mouseClick</td>
+       <td>vaadin=runcomvaadintestscomponentsnativebuttonNativeButtonTest::Root/VOverlay[1]/VMenuBar[0]#item1</td>
+       <td>15,13</td>
+</tr>
+<tr>
+       <td>mouseClick</td>
+       <td>vaadin=runcomvaadintestscomponentsnativebuttonNativeButtonTest::PID_Smenu#item0</td>
+       <td>43,4</td>
+</tr>
+<tr>
+       <td>mouseClick</td>
+       <td>vaadin=runcomvaadintestscomponentsnativebuttonNativeButtonTest::Root/VOverlay[0]/VMenuBar[0]#item0</td>
+       <td>37,8</td>
+</tr>
+<tr>
+       <td>mouseClick</td>
+       <td>vaadin=runcomvaadintestscomponentsnativebuttonNativeButtonTest::Root/VOverlay[1]/VMenuBar[0]#item1</td>
+       <td>33,6</td>
+</tr>
+<tr>
+       <td>assertText</td>
+       <td>vaadin=runcomvaadintestscomponentsnativebuttonNativeButtonTest::PID_SLog_row_0</td>
+       <td>4. Command: /Enabled(true)</td>
+</tr>
+<tr>
+       <td>assertNotCSSClass</td>
+       <td>vaadin=runcomvaadintestscomponentsnativebuttonNativeButtonTest::PID_StestComponent</td>
+       <td>v-disabled</td>
+</tr>
+<!--no longer disable on click-->
+<tr>
+       <td>mouseClick</td>
+       <td>vaadin=runcomvaadintestscomponentsnativebuttonNativeButtonTest::PID_Smenu#item0</td>
+       <td>25,9</td>
+</tr>
+<tr>
+       <td>mouseClick</td>
+       <td>vaadin=runcomvaadintestscomponentsnativebuttonNativeButtonTest::Root/VOverlay[0]/VMenuBar[0]#item4</td>
+       <td>39,13</td>
+</tr>
+<tr>
+       <td>mouseClick</td>
+       <td>vaadin=runcomvaadintestscomponentsnativebuttonNativeButtonTest::Root/VOverlay[1]/VMenuBar[0]#item1</td>
+       <td>36,3</td>
+</tr>
+<tr>
+       <td>click</td>
+       <td>vaadin=runcomvaadintestscomponentsnativebuttonNativeButtonTest::PID_StestComponent</td>
+       <td></td>
+</tr>
+<tr>
+       <td>assertText</td>
+       <td>vaadin=runcomvaadintestscomponentsnativebuttonNativeButtonTest::PID_SLog_row_0</td>
+       <td>6. ClickEvent</td>
+</tr>
+<tr>
+       <td>assertNotCSSClass</td>
+       <td>vaadin=runcomvaadintestscomponentsnativebuttonNativeButtonTest::PID_StestComponent</td>
+       <td>v-disabled</td>
+</tr>
+</tbody></table>
+</body>
+</html>