]> source.dussan.org Git - vaadin-framework.git/commitdiff
Fix RTA's CreateLink in Firefox & IE11 (#11979)
authorTarek Oraby <42799254+tarekoraby@users.noreply.github.com>
Fri, 8 May 2020 12:46:59 +0000 (15:46 +0300)
committerGitHub <noreply@github.com>
Fri, 8 May 2020 12:46:59 +0000 (15:46 +0300)
In Firefox and IE11, the 'Create Link' button of the RichTextArea (RTA) only works by turning some highlighted text into a link (by adding the inserted URI as the href property of the text). In that, the RTA in these two browsers behave similarly to the way it does in Chrome and Edge. However, in Firefox and IE11, clicking the 'Create Link' button has no effect if no text is pre-selected by the user. This is different from the button's behavior in Chrome and Edge where the user's provided URI is inserted, both, as the displayed text and its href property if no text is highlighted.

This fix enables the RTA's 'Create Link' button to work consistently across the supported browsers. Specifically, (and in addition to enabling adding the href property of a highlighted text), this fix enables Firefox and IE11 to also insert a new Uri as a text and its href property if no text is already highlighted.

fixes #11888

client/src/main/java/com/vaadin/client/ui/richtextarea/VRichTextToolbar.java
uitest/src/main/java/com/vaadin/tests/components/richtextarea/RichTextAreaCreateLink.java [new file with mode: 0644]
uitest/src/test/java/com/vaadin/tests/components/richtextarea/RichTextAreaCreateLinkTest.java [new file with mode: 0644]

index d0fc5a239691335f01a6b7727be636b62bc8994a..6da1e71b03cee7c6808f94addc086203ec514fb5 100644 (file)
@@ -242,7 +242,7 @@ public class VRichTextToolbar extends Composite {
                 final String url = Window.prompt("Enter a link URL:",
                         "http://");
                 if (url != null) {
-                    extended.createLink(url);
+                    createLinkViaJSNI(extended, url);
                 }
             } else if (sender == removeLink) {
                 extended.removeLink();
@@ -273,6 +273,30 @@ public class VRichTextToolbar extends Composite {
                 updateStatus();
             }
         }
+
+        private native void createLinkViaJSNI(
+                RichTextArea.ExtendedFormatter formatter, String url)
+        /*-{
+            var elem = formatter.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem;
+            var wnd = elem.contentWindow;
+            var selectedText = "";
+            if (wnd.getSelection) {
+                selectedText = wnd.getSelection().toString();
+            }
+        
+            wnd.focus();
+            if (selectedText) {
+                // Add url as the href property of the highlighted text
+                wnd.document.execCommand("createLink", false, url);
+            } else {
+                // Insert url both as a new text and its href-property value
+                var range = wnd.document.getSelection().getRangeAt(0)
+                var node = wnd.document.createElement("a");
+                node.innerHTML = url;
+                node.setAttribute("href", url);
+                range.insertNode(node);
+            }
+          }-*/;
     }
 
     private static final RichTextArea.FontSize[] FONT_SIZES_CONSTANTS = {
diff --git a/uitest/src/main/java/com/vaadin/tests/components/richtextarea/RichTextAreaCreateLink.java b/uitest/src/main/java/com/vaadin/tests/components/richtextarea/RichTextAreaCreateLink.java
new file mode 100644 (file)
index 0000000..cb89e91
--- /dev/null
@@ -0,0 +1,38 @@
+package com.vaadin.tests.components.richtextarea;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.shared.ui.ContentMode;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.RichTextArea;
+
+public class RichTextAreaCreateLink extends AbstractTestUI {
+
+    @Override
+    protected String getTestDescription() {
+        return "Test the 'Create Link' button of a rich text area in supported browsers.";
+    }
+
+    @Override
+    protected Integer getTicketNumber() {
+        return 11888;
+    }
+
+    @Override
+    protected void setup(VaadinRequest request) {
+        final RichTextArea area = new RichTextArea();
+
+        final Label label = new Label(area.getValue(),
+                ContentMode.PREFORMATTED);
+        label.setCaption("Value recieved from RichTextArea:");
+
+        final Button button = new Button("get area value",
+                event -> label.setValue(area.getValue()));
+
+        addComponent(area);
+        addComponent(button);
+        addComponent(label);
+    }
+
+}
diff --git a/uitest/src/test/java/com/vaadin/tests/components/richtextarea/RichTextAreaCreateLinkTest.java b/uitest/src/test/java/com/vaadin/tests/components/richtextarea/RichTextAreaCreateLinkTest.java
new file mode 100644 (file)
index 0000000..c93079b
--- /dev/null
@@ -0,0 +1,77 @@
+package com.vaadin.tests.components.richtextarea;
+
+import static org.junit.Assert.assertTrue;
+
+import java.time.Duration;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.openqa.selenium.Alert;
+import org.openqa.selenium.By;
+import org.openqa.selenium.Keys;
+import org.openqa.selenium.NoSuchElementException;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.support.ui.ExpectedConditions;
+import org.openqa.selenium.support.ui.FluentWait;
+import org.openqa.selenium.support.ui.Wait;
+
+import com.vaadin.testbench.elements.RichTextAreaElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class RichTextAreaCreateLinkTest extends MultiBrowserTest {
+
+    private static final Duration PROMPT_POLLING_INTERVAL = Duration
+            .ofSeconds(5);
+    private static final Duration PROMPT_TIMEOUT_INTERVAL = Duration
+            .ofSeconds(30);
+    private static final String TESTING_URI = "https://vaadin.com/";
+    private static final String TESTING_TEXT = "Vaadin company name";
+
+    RichTextAreaElement rta;
+
+    @Before
+    public void init() {
+        openTestURL();
+        rta = $(RichTextAreaElement.class).first();
+    }
+
+    @Test
+    public void createLinkButtonShouldInsertUriAsTextAndHrefIfNoTextIsHighlighted() {
+        createLinkViaButton(rta, TESTING_URI);
+        String expected = "<a href=\"" + TESTING_URI + "\">" + TESTING_URI
+                + "</a>";
+        assertTrue(String.format(
+                "RichTextArea's expected value is: %s. However, the following value was received: %s.",
+                expected, rta.getValue()), rta.getValue().equals(expected));
+    }
+
+    @Test
+    public void createLinkButtonShouldAddUriAsHrefIfTextIsHighlighted() {
+        rta.setValue(TESTING_TEXT);
+        WebElement textArea = rta.findElement(By.className("gwt-RichTextArea"));
+        textArea.sendKeys(Keys.CONTROL, "a");
+        createLinkViaButton(rta, TESTING_URI);
+        String expected = "<a href=\"" + TESTING_URI + "\">" + TESTING_TEXT
+                + "</a>";
+        assertTrue(String.format(
+                "RichTextArea's expected value is: %s. However, the following value was received: %s.",
+                expected, rta.getValue()), rta.getValue().equals(expected));
+    }
+
+    private void createLinkViaButton(RichTextAreaElement rta, String Uri) {
+        rta.findElement(By.cssSelector("div[title='Create Link']")).click();
+
+        Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
+                .withTimeout(PROMPT_TIMEOUT_INTERVAL)
+                .pollingEvery(PROMPT_POLLING_INTERVAL)
+                .ignoring(NoSuchElementException.class);
+
+        // Wait for the alert to be displayed and store it in a variable
+        Alert alert = wait.until(ExpectedConditions.alertIsPresent());
+        // Type the URI
+        alert.sendKeys(Uri);
+        // Press the OK button
+        alert.accept();
+    }
+}