diff options
5 files changed, 194 insertions, 35 deletions
diff --git a/client/src/main/java/com/vaadin/client/ui/upload/UploadConnector.java b/client/src/main/java/com/vaadin/client/ui/upload/UploadConnector.java index 87f726eb15..3986bf3a2a 100644 --- a/client/src/main/java/com/vaadin/client/ui/upload/UploadConnector.java +++ b/client/src/main/java/com/vaadin/client/ui/upload/UploadConnector.java @@ -19,6 +19,7 @@ package com.vaadin.client.ui.upload; import com.vaadin.client.ApplicationConnection; import com.vaadin.client.Paintable; import com.vaadin.client.UIDL; +import com.vaadin.client.annotations.OnStateChange; import com.vaadin.client.communication.StateChangeEvent; import com.vaadin.client.ui.AbstractComponentConnector; import com.vaadin.client.ui.VUpload; @@ -52,17 +53,6 @@ public class UploadConnector extends AbstractComponentConnector final String action = client .translateVaadinUri(uidl.getStringVariable("action")); upload.element.setAction(action); - if (uidl.hasAttribute("buttoncaption")) { - upload.submitButton - .setText(uidl.getStringAttribute("buttoncaption")); - if (uidl.hasAttribute("buttonstylename")) { - upload.submitButton.setStyleName( - uidl.getStringAttribute("buttonstylename")); - } - upload.submitButton.setVisible(true); - } else { - upload.submitButton.setVisible(false); - } upload.fu.setName(upload.paintableId + "_file"); if (!isEnabled()) { @@ -81,6 +71,29 @@ public class UploadConnector extends AbstractComponentConnector getWidget().disableTitle(hasTooltip()); } + /** + * Updates the caption, style name, display mode, and visibility of the + * submit button. + * <p> + * For internal use only. May be removed or replaced in the future. + */ + @OnStateChange({ "buttonCaption", "buttonStyleName", + "buttonCaptionAsHtml" }) + private void updateSubmitButton() { + VUpload upload = getWidget(); + if (getState().buttonCaption != null) { + if (getState().buttonCaptionAsHtml) { + upload.submitButton.setHtml(getState().buttonCaption); + } else { + upload.submitButton.setText(getState().buttonCaption); + } + upload.submitButton.setStyleName(getState().buttonStyleName); + upload.submitButton.setVisible(true); + } else { + upload.submitButton.setVisible(false); + } + } + @Override public VUpload getWidget() { return (VUpload) super.getWidget(); diff --git a/server/src/main/java/com/vaadin/ui/Upload.java b/server/src/main/java/com/vaadin/ui/Upload.java index de2d520438..a7375f468e 100644 --- a/server/src/main/java/com/vaadin/ui/Upload.java +++ b/server/src/main/java/com/vaadin/ui/Upload.java @@ -98,10 +98,6 @@ public class Upload extends AbstractComponent private int totalBytes; - private String buttonCaption = "Upload"; - - private String buttonStyleName; - /** * ProgressListeners to which information about progress is sent during * upload @@ -184,13 +180,6 @@ public class Upload extends AbstractComponent target.addAttribute("state", isUploading); - if (buttonCaption != null) { - target.addAttribute("buttoncaption", buttonCaption); - if (buttonStyleName != null) { - target.addAttribute("buttonstylename", buttonStyleName); - } - } - target.addAttribute("nextid", nextid); // Post file to this stream variable @@ -982,17 +971,31 @@ public class Upload extends AbstractComponent * @return String to be rendered into button that fires uploading */ public String getButtonCaption() { - return buttonCaption; + return getState(false).buttonCaption; } /** - * Returns the stylename rendered into button that fires uploading. + * Returns the style name rendered into button that fires uploading. * - * @return Stylename to be rendered into button that fires uploading + * @return Style name to be rendered into button that fires uploading * @since 8.2 */ public String getButtonStyleName() { - return buttonStyleName; + return getState(false).buttonStyleName; + } + + /** + * Checks whether the caption of the button that fires uploading is rendered + * as HTML + * <p> + * The default is {@code false}, i.e. to render that caption as plain text. + * + * @return {@code true} if the caption is rendered as HTML, {@code false} if + * rendered as plain text + * @since + */ + public boolean isButtonCaptionAsHtml() { + return getState(false).buttonCaptionAsHtml; } /** @@ -1005,8 +1008,8 @@ public class Upload extends AbstractComponent * {@link #submitUpload()}. * <p> * In case the Upload is used in immediate mode using - * {@link #setImmediateMode(boolean)}, the file choose (html input with type - * "file") is hidden and only the button with this text is shown. + * {@link #setImmediateMode(boolean)}, the file chooser (HTML input with + * type "file") is hidden and only the button with this text is shown. * <p> * * <p> @@ -1018,23 +1021,46 @@ public class Upload extends AbstractComponent * text for upload components button. */ public void setButtonCaption(String buttonCaption) { - this.buttonCaption = buttonCaption; - markAsDirty(); + getState().buttonCaption = buttonCaption; } /** * In addition to the actual file chooser, upload components have button - * that starts actual upload progress. This method is used to set a - * stylename to that button. + * that starts actual upload progress. This method is used to set a style + * name to that button. + * <p> + * Note: Unlike {@code Button.setStyleName()} this method overrides all the + * styles from the button. If you wish to preserve the default styles, enter + * the style name as {@code "v-button yourStyleName"}. * * @param buttonStyleName - * styleName for upload components button. + * style name for upload components button. * @see #setButtonCaption(String) about when the button is shown / hidden. * @since 8.2 */ public void setButtonStyleName(String buttonStyleName) { - this.buttonStyleName = buttonStyleName; - markAsDirty(); + getState().buttonStyleName = buttonStyleName; + } + + /** + * In addition to the actual file chooser, upload components have button + * that starts actual upload progress. This method is used to set whether + * the caption on that button is rendered as HTML. + * <p> + * If set to {@code true}, the caption is rendered in the browser as HTML + * and the developer is responsible for ensuring no harmful HTML is used. If + * set to {@code false}, the caption is rendered in the browser as plain + * text. + * <p> + * The default is {@code false}, i.e. to render the caption as plain text. + * + * @param buttonCaptionAsHtml + * {@code true} if the caption is rendered as HTML, {@code false} + * if rendered as plain text + * @since + */ + public void setButtonCaptionAsHtml(boolean buttonCaptionAsHtml) { + getState().buttonCaptionAsHtml = buttonCaptionAsHtml; } /** diff --git a/shared/src/main/java/com/vaadin/shared/ui/upload/UploadState.java b/shared/src/main/java/com/vaadin/shared/ui/upload/UploadState.java index 217946391c..81b4bdf8c4 100644 --- a/shared/src/main/java/com/vaadin/shared/ui/upload/UploadState.java +++ b/shared/src/main/java/com/vaadin/shared/ui/upload/UploadState.java @@ -33,7 +33,20 @@ public class UploadState extends AbstractComponentState { primaryStyleName = "v-upload"; } + /** Upload component's list of accepted content-types. */ @DelegateToWidget @NoLayout public String acceptMimeTypes; + + /** Caption of the button that fires uploading. */ + public String buttonCaption = "Upload"; + + /** Style name of the button that fires uploading. */ + public String buttonStyleName = "v-button"; + + /** + * Should the caption of the button that fires uploading be rendered as + * HTML. + */ + public boolean buttonCaptionAsHtml; } diff --git a/uitest/src/main/java/com/vaadin/tests/components/upload/UploadHtmlCaption.java b/uitest/src/main/java/com/vaadin/tests/components/upload/UploadHtmlCaption.java new file mode 100644 index 0000000000..b48092d14a --- /dev/null +++ b/uitest/src/main/java/com/vaadin/tests/components/upload/UploadHtmlCaption.java @@ -0,0 +1,40 @@ +package com.vaadin.tests.components.upload; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Button; +import com.vaadin.ui.Upload; + +public class UploadHtmlCaption extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + Upload upload = new Upload(); + upload.setImmediateMode(false); + upload.setButtonCaption("<b>Submit button</b>"); + upload.setCaption("This is the caption of the <b>entire</b> component"); + addComponent(upload); + + Button toggleButtonCaption = new Button("Toggle button caption", + e -> upload.setButtonCaptionAsHtml( + !upload.isButtonCaptionAsHtml())); + toggleButtonCaption.setId("toggleButtonCaption"); + addComponent(toggleButtonCaption); + + Button toggleComponentCaption = new Button("Toggle component caption", + e -> upload.setCaptionAsHtml(!upload.isCaptionAsHtml())); + toggleComponentCaption.setId("toggleComponentCaption"); + addComponent(toggleComponentCaption); + } + + @Override + protected Integer getTicketNumber() { + return 11810; + } + + @Override + protected String getTestDescription() { + return "It should be possible to set component caption and submit button caption " + + "to allow HTML display mode independently of each other."; + } +} diff --git a/uitest/src/test/java/com/vaadin/tests/components/upload/UploadHtmlCaptionTest.java b/uitest/src/test/java/com/vaadin/tests/components/upload/UploadHtmlCaptionTest.java new file mode 100644 index 0000000000..0008e78351 --- /dev/null +++ b/uitest/src/test/java/com/vaadin/tests/components/upload/UploadHtmlCaptionTest.java @@ -0,0 +1,67 @@ +package com.vaadin.tests.components.upload; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; + +import com.vaadin.testbench.elements.ButtonElement; +import com.vaadin.testbench.elements.UploadElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class UploadHtmlCaptionTest extends MultiBrowserTest { + + @Test + public void htmlCaptionToggle() { + openTestURL(); + + UploadElement upload = $(UploadElement.class).first(); + WebElement submitButtonCaption = upload + .findElement(By.className("v-button-caption")); + WebElement componentCaption = findElement(By.className("v-caption")); + ButtonElement toggleButtonCaption = $(ButtonElement.class) + .id("toggleButtonCaption"); + ButtonElement toggleComponentCaption = $(ButtonElement.class) + .id("toggleComponentCaption"); + + assertTrue( + "Unexpected submit button caption: " + + submitButtonCaption.getText(), + submitButtonCaption.getText().contains("<b>")); + assertTrue( + "Unexpected component caption: " + componentCaption.getText(), + componentCaption.getText().contains("<b>")); + + toggleButtonCaption.click(); + + assertFalse( + "Unexpected submit button caption: " + + submitButtonCaption.getText(), + submitButtonCaption.getText().contains("<b>")); + assertTrue( + "Unexpected component caption: " + componentCaption.getText(), + componentCaption.getText().contains("<b>")); + + toggleComponentCaption.click(); + + assertFalse( + "Unexpected submit button caption: " + + submitButtonCaption.getText(), + submitButtonCaption.getText().contains("<b>")); + assertFalse( + "Unexpected component caption: " + componentCaption.getText(), + componentCaption.getText().contains("<b>")); + + toggleButtonCaption.click(); + + assertTrue( + "Unexpected submit button caption: " + + submitButtonCaption.getText(), + submitButtonCaption.getText().contains("<b>")); + assertFalse( + "Unexpected component caption: " + componentCaption.getText(), + componentCaption.getText().contains("<b>")); + } +} |