1 /*
2 * Copyright (c) 2002-2025 Gargoyle Software Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 * https://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 package org.htmlunit.html.impl;
16
17 import org.htmlunit.html.DomNode;
18
19 /**
20 * Contains standard selection-related functionality used by various input elements.
21 *
22 * <p>From <a href="http://www.whatwg.org/specs/web-apps/current-work/#selection">the HTML5 spec</a>:
23 *
24 * <blockquote>Mostly for historical reasons, in addition to the browsing context's selection, each
25 * textarea and input element has an independent selection. These are the text field selections.</blockquote>
26 *
27 * @author Daniel Gredler
28 * @author Ronald Brill
29 * @author Ahmed Ashour
30 */
31 public class SelectableTextSelectionDelegate implements SelectionDelegate {
32
33 /** The owner element. */
34 private final SelectableTextInput element_;
35
36 /** The field selection, which is independent of the browsing context's selection. */
37 private final SimpleRange selection_;
38
39 /**
40 * Creates a new instance for the specified element.
41 * @param element the owner element
42 */
43 public SelectableTextSelectionDelegate(final SelectableTextInput element) {
44 element_ = element;
45 selection_ = new SimpleRange((DomNode) element, 0);
46 }
47
48 /**
49 * Focuses the owner element and selects all of its text.
50 */
51 public void select() {
52 element_.focus();
53 setSelectionStart(0);
54 setSelectionEnd(element_.getText().length());
55 }
56
57 /**
58 * Returns the selected text in the owner element, or {@code null} if there is no selected text.
59 * @return the selected text in the owner element, or {@code null} if there is no selected text
60 */
61 public String getSelectedText() {
62 return selection_.toString();
63 }
64
65 /**
66 * {@inheritDoc}
67 */
68 @Override
69 public int getSelectionStart() {
70 return selection_.getStartOffset();
71 }
72
73 /**
74 * {@inheritDoc}
75 */
76 @Override
77 public void setSelectionStart(int selectionStart) {
78 if (selectionStart < 0) {
79 return;
80 }
81
82 final int length = element_.getText().length();
83 selectionStart = Math.max(0, Math.min(selectionStart, length));
84 selection_.setStart((DomNode) element_, selectionStart);
85 if (selection_.getEndOffset() < selectionStart) {
86 selection_.setEnd((DomNode) element_, selectionStart);
87 }
88 }
89
90 /**
91 * {@inheritDoc}
92 */
93 @Override
94 public int getSelectionEnd() {
95 return selection_.getEndOffset();
96 }
97
98 /**
99 * {@inheritDoc}
100 */
101 @Override
102 public void setSelectionEnd(int selectionEnd) {
103 final int length = element_.getText().length();
104 selectionEnd = Math.min(length, Math.max(selectionEnd, 0));
105 selection_.setEnd((DomNode) element_, selectionEnd);
106 if (selection_.getStartOffset() > selectionEnd) {
107 selection_.setStart((DomNode) element_, selectionEnd);
108 }
109 }
110 }