View Javadoc
1   /*
2    * Copyright (c) 2002-2026 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.javascript.host.dom;
16  
17  import org.htmlunit.html.impl.SimpleRange;
18  import org.htmlunit.javascript.HtmlUnitScriptable;
19  import org.htmlunit.javascript.JavaScriptEngine;
20  import org.htmlunit.javascript.configuration.JsxClass;
21  import org.htmlunit.javascript.configuration.JsxConstructor;
22  import org.htmlunit.javascript.configuration.JsxGetter;
23  
24  /**
25   * The JavaScript object that represents an AbstractRange.
26   *
27   * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/AbstractRange">MDN Documentation</a>
28   * @author Ronald Brill
29   */
30  @JsxClass
31  public class AbstractRange extends HtmlUnitScriptable {
32  
33      private Node startContainer_;
34      private Node endContainer_;
35      private int startOffset_;
36      private int endOffset_;
37  
38      /**
39       * Creates an instance.
40       */
41      public AbstractRange() {
42          super();
43      }
44  
45      /**
46       * Creates an instance.
47       */
48      @JsxConstructor
49      public void jsConstructor() {
50          throw JavaScriptEngine.typeErrorIllegalConstructor();
51      }
52  
53      /**
54       * Creates a new instance.
55       *
56       * @param startContainer the start node
57       * @param endContainer the end node
58       * @param startOffset the start offset
59       * @param endOffset the end offset
60       */
61      protected AbstractRange(final Node startContainer, final Node endContainer,
62              final int startOffset, final int endOffset) {
63          super();
64          startContainer_ = startContainer;
65          endContainer_ = endContainer;
66  
67          startOffset_ = startOffset;
68          endOffset_ = endOffset;
69      }
70  
71      /**
72       * Returns the start container.
73       * @return the start container
74       */
75      protected Node internGetStartContainer() {
76          return startContainer_;
77      }
78  
79      /**
80       * Sets the start container.
81       *
82       * @param startContainer the new start container
83       */
84      protected void internSetStartContainer(final Node startContainer) {
85          startContainer_ = startContainer;
86      }
87  
88      /**
89       * Returns the end container.
90       * @return the end container
91       */
92      protected Node internGetEndContainer() {
93          return endContainer_;
94      }
95  
96      /**
97       * Sets the end container.
98       *
99       * @param endContainer the new end container
100      */
101     protected void internSetEndContainer(final Node endContainer) {
102         endContainer_ = endContainer;
103     }
104 
105     /**
106      * Returns the start offset.
107      * @return the start offset
108      */
109     protected int internGetStartOffset() {
110         return startOffset_;
111     }
112 
113     /**
114      * Sets the start offset.
115      *
116      * @param startOffset the new start offset
117      */
118     protected void internSetStartOffset(final int startOffset) {
119         startOffset_ = startOffset;
120     }
121 
122     /**
123      * Returns the end offset.
124      * @return the end offset
125      */
126     protected int internGetEndOffset() {
127         return endOffset_;
128     }
129 
130     /**
131      * Sets the end offset.
132      *
133      * @param endOffset the new end offset
134      */
135     protected void internSetEndOffset(final int endOffset) {
136         endOffset_ = endOffset;
137     }
138 
139     /**
140      * {@inheritDoc}
141      */
142     @Override
143     public Object getDefaultValue(final Class<?> hint) {
144         if (getPrototype() == null
145                 || startContainer_ == null
146                 || endContainer_ == null) {
147             return super.getDefaultValue(hint);
148         }
149         return getSimpleRange().toString();
150     }
151 
152     /**
153      * Gets the node within which the Range begins.
154      * @return <code>undefined</code> if not initialized
155      */
156     @JsxGetter
157     public Object getStartContainer() {
158         if (startContainer_ == null) {
159             return JavaScriptEngine.UNDEFINED;
160         }
161         return startContainer_;
162     }
163 
164     /**
165      * Gets the node within which the Range ends.
166      * @return <code>undefined</code> if not initialized
167      */
168     @JsxGetter
169     public Object getEndContainer() {
170         if (endContainer_ == null) {
171             return JavaScriptEngine.UNDEFINED;
172         }
173         return endContainer_;
174     }
175 
176     /**
177      * Gets the offset within the starting node of the Range.
178      * @return <code>0</code> if not initialized
179      */
180     @JsxGetter
181     public int getStartOffset() {
182         return startOffset_;
183     }
184 
185     /**
186      * Gets the offset within the end node of the Range.
187      * @return <code>0</code> if not initialized
188      */
189     @JsxGetter
190     public int getEndOffset() {
191         return endOffset_;
192     }
193 
194     /**
195      * Indicates if the range is collapsed.
196      * @return {@code true} if the range is collapsed
197      */
198     @JsxGetter
199     public boolean isCollapsed() {
200         return startContainer_ == endContainer_ && startOffset_ == endOffset_;
201     }
202 
203     /**
204      * Returns a {@link SimpleRange} version of this object.
205      * @return a {@link SimpleRange} version of this object
206      */
207     public SimpleRange getSimpleRange() {
208         return new SimpleRange(startContainer_.getDomNodeOrNull(), startOffset_,
209             endContainer_.getDomNodeOrDie(), endOffset_);
210     }
211 
212     @Override
213     protected Object equivalentValues(final Object value) {
214         if (!(value instanceof AbstractRange other)) {
215             return false;
216         }
217         return startContainer_ == other.startContainer_
218                 && endContainer_ == other.endContainer_
219                 && startOffset_ == other.startOffset_
220                 && endOffset_ == other.endOffset_;
221     }
222 }