View Javadoc
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.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 a AbstractRange.
26   *
27   * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/AbstractRange">AbstractRange</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       * @return the start container
73       */
74      protected Node internGetStartContainer() {
75          return startContainer_;
76      }
77  
78      /**
79       * Sets the start container.
80       *
81       * @param startContainer the new start container
82       */
83      protected void internSetStartContainer(final Node startContainer) {
84          startContainer_ = startContainer;
85      }
86  
87      /**
88       * @return the end container
89       */
90      protected Node internGetEndContainer() {
91          return endContainer_;
92      }
93  
94      /**
95       * Sets the end container.
96       *
97       * @param endContainer the new end container
98       */
99      protected void internSetEndContainer(final Node endContainer) {
100         endContainer_ = endContainer;
101     }
102 
103     /**
104      * @return the start offset
105      */
106     protected int internGetStartOffset() {
107         return startOffset_;
108     }
109 
110     /**
111      * Sets the start offset.
112      *
113      * @param startOffset the new start offset
114      */
115     protected void internSetStartOffset(final int startOffset) {
116         startOffset_ = startOffset;
117     }
118 
119     /**
120      * @return the end offset
121      */
122     protected int internGetEndOffset() {
123         return endOffset_;
124     }
125 
126     /**
127      * Sets the end offset.
128      *
129      * @param endOffset the new end offset
130      */
131     protected void internSetEndOffset(final int endOffset) {
132         endOffset_ = endOffset;
133     }
134 
135     /**
136      * {@inheritDoc}
137      */
138     @Override
139     public Object getDefaultValue(final Class<?> hint) {
140         if (getPrototype() == null
141                 || startContainer_ == null
142                 || endContainer_ == null) {
143             return super.getDefaultValue(hint);
144         }
145         return getSimpleRange().toString();
146     }
147 
148     /**
149      * Gets the node within which the Range begins.
150      * @return <code>undefined</code> if not initialized
151      */
152     @JsxGetter
153     public Object getStartContainer() {
154         if (startContainer_ == null) {
155             return JavaScriptEngine.UNDEFINED;
156         }
157         return startContainer_;
158     }
159 
160     /**
161      * Gets the node within which the Range ends.
162      * @return <code>undefined</code> if not initialized
163      */
164     @JsxGetter
165     public Object getEndContainer() {
166         if (endContainer_ == null) {
167             return JavaScriptEngine.UNDEFINED;
168         }
169         return endContainer_;
170     }
171 
172     /**
173      * Gets the offset within the starting node of the Range.
174      * @return <code>0</code> if not initialized
175      */
176     @JsxGetter
177     public int getStartOffset() {
178         return startOffset_;
179     }
180 
181     /**
182      * Gets the offset within the end node of the Range.
183      * @return <code>0</code> if not initialized
184      */
185     @JsxGetter
186     public int getEndOffset() {
187         return endOffset_;
188     }
189 
190     /**
191      * Indicates if the range is collapsed.
192      * @return {@code true} if the range is collapsed
193      */
194     @JsxGetter
195     public boolean isCollapsed() {
196         return startContainer_ == endContainer_ && startOffset_ == endOffset_;
197     }
198 
199     /**
200      * @return a {@link SimpleRange} version of this object
201      */
202     public SimpleRange getSimpleRange() {
203         return new SimpleRange(startContainer_.getDomNodeOrNull(), startOffset_,
204             endContainer_.getDomNodeOrDie(), endOffset_);
205     }
206 
207     @Override
208     protected Object equivalentValues(final Object value) {
209         if (!(value instanceof AbstractRange)) {
210             return false;
211         }
212         final AbstractRange other = (AbstractRange) value;
213         return startContainer_ == other.startContainer_
214                 && endContainer_ == other.endContainer_
215                 && startOffset_ == other.startOffset_
216                 && endOffset_ == other.endOffset_;
217     }
218 }