summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLeif Åstrand <leif@vaadin.com>2013-03-12 18:34:18 +0200
committerVaadin Code Review <review@vaadin.com>2013-03-20 09:43:35 +0000
commit5ea677d377c96c60fbc546eb2381bb88f2d4b478 (patch)
tree36b3fefd6b1481c4f39f182f09e88b00d77d5818
parent17f64543bcc74f74017a3d1c13e5db83c7a4ec41 (diff)
downloadvaadin-framework-5ea677d377c96c60fbc546eb2381bb88f2d4b478.tar.gz
vaadin-framework-5ea677d377c96c60fbc546eb2381bb88f2d4b478.zip
Make TextArea.setCursorPosition work in all browsers (#8769)
svn changeset:25579/svn branch:6.8 Conflicts: client/src/com/vaadin/client/ui/VTextField.java Change-Id: I3b53be8df4ce0564f34d8aa9bc1ce1c34648eadd
-rw-r--r--client/src/com/vaadin/client/ui/VTextArea.java114
-rw-r--r--client/src/com/vaadin/client/ui/VTextField.java4
-rw-r--r--uitest/src/com/vaadin/tests/components/textarea/ScrollCursor.html169
-rw-r--r--uitest/src/com/vaadin/tests/components/textarea/ScrollCursor.java89
4 files changed, 376 insertions, 0 deletions
diff --git a/client/src/com/vaadin/client/ui/VTextArea.java b/client/src/com/vaadin/client/ui/VTextArea.java
index 4a5de23828..45e0532451 100644
--- a/client/src/com/vaadin/client/ui/VTextArea.java
+++ b/client/src/com/vaadin/client/ui/VTextArea.java
@@ -63,6 +63,120 @@ public class VTextArea extends VTextField {
getTextAreaElement().setRows(rows);
}
+ @Override
+ public void setSelectionRange(int pos, int length) {
+ super.setSelectionRange(pos, length);
+ final String value = getValue();
+ /*
+ * Align position to index inside string value
+ */
+ int index = pos;
+ if (index < 0) {
+ index = 0;
+ }
+ if (index > value.length()) {
+ index = value.length();
+ }
+ // Get pixels count required to scroll textarea vertically
+ int scrollTop = getScrollTop(value, index);
+ int scrollLeft = -1;
+ /*
+ * Check if textarea has wrap attribute set to "off". In the latter case
+ * horizontal scroll is also required.
+ */
+ if (!isWordwrap()) {
+ // Get pixels count required to scroll textarea horizontally
+ scrollLeft = getScrollLeft(value, index);
+ }
+ // Set back original text if previous methods calls changed it
+ if (!isWordwrap() || index < value.length()) {
+ setValue(value, false);
+ }
+ /*
+ * Call original method to set cursor position. In most browsers it
+ * doesn't lead to scrolling.
+ */
+ super.setSelectionRange(pos, length);
+ /*
+ * Align vertical scroll to middle of textarea view (height) if
+ * scrolling is reqiured at all.
+ */
+ if (scrollTop > 0) {
+ scrollTop += getElement().getClientHeight() / 2;
+ }
+ /*
+ * Align horizontal scroll to middle of textarea view (widht) if
+ * scrolling is reqiured at all.
+ */
+ if (scrollLeft > 0) {
+ scrollLeft += getElement().getClientWidth() / 2;
+ }
+ /*
+ * Scroll if computed scrollTop is greater than scroll after cursor
+ * setting
+ */
+ if (getElement().getScrollTop() < scrollTop) {
+ getElement().setScrollTop(scrollTop);
+ }
+ /*
+ * Scroll if computed scrollLeft is greater than scroll after cursor
+ * setting
+ */
+ if (getElement().getScrollLeft() < scrollLeft) {
+ getElement().setScrollLeft(scrollLeft);
+ }
+ }
+
+ /*
+ * Get horizontal scroll value required to get position visible. Method is
+ * called only when text wrapping is off. There is need to scroll
+ * horizontally in case words are wrapped.
+ */
+ private int getScrollLeft(String value, int index) {
+ String beginning = value.substring(0, index);
+ // Compute beginning of the current line
+ int begin = beginning.lastIndexOf('\n');
+ String line = value.substring(begin + 1);
+ index = index - begin - 1;
+ if (index < line.length()) {
+ index++;
+ }
+ line = line.substring(0, index);
+ /*
+ * Now <code>line</code> contains current line up to index position
+ */
+ setValue(line.trim(), false); // Set this line to the textarea.
+ /*
+ * Scroll textarea up to the end of the line (maximum possible
+ * horizontal scrolling value). Now the end line becomes visible.
+ */
+ getElement().setScrollLeft(getElement().getScrollWidth());
+ // Return resulting horizontal scrolling value.
+ return getElement().getScrollLeft();
+ }
+
+ /*
+ * Get vertical scroll value required to get position visible
+ */
+ private int getScrollTop(String value, int index) {
+ /*
+ * Trim text after position and set this trimmed text if index is not
+ * very end.
+ */
+ if (index < value.length()) {
+ String beginning = value.substring(0, index);
+ setValue(beginning, false);
+ }
+ /*
+ * Now textarea contains trimmed text and could be scrolled up to the
+ * top. Scroll it to maximum possible value to get end of the text
+ * visible.
+ */
+ getElement().setScrollTop(getElement().getScrollHeight());
+ // Return resulting vertical scrolling value.
+ return getElement().getScrollTop();
+ }
+
private class MaxLengthHandler implements KeyUpHandler, ChangeHandler {
@Override
diff --git a/client/src/com/vaadin/client/ui/VTextField.java b/client/src/com/vaadin/client/ui/VTextField.java
index 0fbed0dd90..da9445c811 100644
--- a/client/src/com/vaadin/client/ui/VTextField.java
+++ b/client/src/com/vaadin/client/ui/VTextField.java
@@ -446,4 +446,8 @@ public class VTextField extends TextBoxBase implements Field, ChangeHandler,
this.inputPrompt = inputPrompt;
}
+ protected boolean isWordwrap() {
+ String wrap = getElement().getAttribute("wrap");
+ return !"off".equals(wrap);
+ }
}
diff --git a/uitest/src/com/vaadin/tests/components/textarea/ScrollCursor.html b/uitest/src/com/vaadin/tests/components/textarea/ScrollCursor.html
new file mode 100644
index 0000000000..9eaa1ceada
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/textarea/ScrollCursor.html
@@ -0,0 +1,169 @@
+<?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.textarea.ScrollCursor?restartApplication</td>
+ <td></td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentstextareaScrollCursor::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/domChild[0]/domChild[0]</td>
+ <td>191,94</td>
+</tr>
+<tr>
+<!-- set begin position value -->
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentstextareaScrollCursor::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+<!-- set cursor position-->
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentstextareaScrollCursor::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>wrap-start</td>
+</tr>
+<tr>
+<!-- set middle position value -->
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentstextareaScrollCursor::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+<!-- set cursor position-->
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentstextareaScrollCursor::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>wrap-middle</td>
+</tr>
+<tr>
+<!-- set end position value -->
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentstextareaScrollCursor::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[5]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+<!-- set cursor position-->
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentstextareaScrollCursor::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>wrap-end</td>
+</tr>
+<tr>
+<!-- set start position value -->
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentstextareaScrollCursor::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+<!-- set cursor position : check that scrolling works from the end to the beginning-->
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentstextareaScrollCursor::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>wrap-end-start</td>
+</tr>
+<tr>
+<!-- set no wrap -->
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentstextareaScrollCursor::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[2]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+<!-- set start position value -->
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentstextareaScrollCursor::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+<!-- set cursor position -->
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentstextareaScrollCursor::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>nowrap-start</td>
+</tr>
+<tr>
+<!-- set middle position value -->
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentstextareaScrollCursor::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+<!-- set cursor position -->
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentstextareaScrollCursor::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>nowrap-middle</td>
+</tr>
+<tr>
+<!-- set end position value -->
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentstextareaScrollCursor::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[5]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+<!-- set cursor position -->
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentstextareaScrollCursor::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>nowrap-end</td>
+</tr>
+<tr>
+<!-- set start position value -->
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentstextareaScrollCursor::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+<!-- set cursor position : check scrolling from the end to the beginning-->
+ <td>click</td>
+ <td>vaadin=runcomvaadintestscomponentstextareaScrollCursor::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[1]/VButton[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>nowrap-end-start</td>
+</tr>
+
+</tbody></table>
+</body>
+</html>
diff --git a/uitest/src/com/vaadin/tests/components/textarea/ScrollCursor.java b/uitest/src/com/vaadin/tests/components/textarea/ScrollCursor.java
new file mode 100644
index 0000000000..c95731d94f
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/textarea/ScrollCursor.java
@@ -0,0 +1,89 @@
+package com.vaadin.tests.components.textarea;
+
+import com.vaadin.tests.components.TestBase;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Button.ClickListener;
+import com.vaadin.ui.TextArea;
+
+/**
+ * @author denis
+ *
+ */
+public class ScrollCursor extends TestBase {
+
+ private TextArea textArea;
+ private int position;
+
+ @Override
+ protected void setup() {
+ textArea = new TextArea();
+ textArea.setValue("saddddddddddd fdgdfgfdgfd\n"
+ + "aasddddddddddd\n" + "dsaffffffdsf\n" + "sdf\n"
+ + "dsfsdfsdfsdfsd\n\n" + "ffffffffffffffffffff\n"
+ + "sdfdsfdsfsdfsdfsd xxxxxxxxxxxxxxxx\n" + "sdgfsd\n"
+ + "dsf\n" + "ds\n" + "fds\n" + "fds\nfs");
+ addComponent(textArea);
+ Button button = new Button("Scroll");
+ button.addListener(new ClickListener() {
+
+ public void buttonClick(ClickEvent event) {
+ textArea.setCursorPosition(getPosition());
+ }
+ });
+ Button wrap = new Button("Set wrap");
+ wrap.addListener(new ClickListener() {
+
+ public void buttonClick(ClickEvent event) {
+ textArea.setWordwrap(false);
+ }
+ });
+
+ Button toBegin = new Button("To begin");
+ toBegin.addListener(new ClickListener() {
+
+ public void buttonClick(ClickEvent event) {
+ position = 3;
+ }
+ });
+
+ Button toMiddle = new Button("To middle");
+ toMiddle.addListener(new ClickListener() {
+
+ public void buttonClick(ClickEvent event) {
+ position = 130;
+ }
+ });
+
+ Button toEnd = new Button("To end");
+ toEnd.addListener(new ClickListener() {
+
+ public void buttonClick(ClickEvent event) {
+ position = textArea.getValue().toString().length();
+ }
+ });
+
+ addComponent(button);
+ addComponent(wrap);
+ addComponent(toBegin);
+ addComponent(toMiddle);
+ addComponent(toEnd);
+ }
+
+ @Override
+ protected String getDescription() {
+ return "Tests scrolling for TextArea with different word wrapping settings. "
+ + "Sets cursor position at the beginning, middle and the end "
+ + "of text and checks textarea is scrolled.";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 8769;
+ }
+
+ private int getPosition() {
+ return position;
+ }
+
+}