View Javadoc
1   /*
2    * Copyright (c) 2002-2017 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    * http://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 com.gargoylesoftware.htmlunit.javascript.host.dom;
16  
17  import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.JS_DOM_CDATA_DELETE_THROWS_NEGATIVE_COUNT;
18  import static com.gargoylesoftware.htmlunit.javascript.configuration.SupportedBrowser.CHROME;
19  import static com.gargoylesoftware.htmlunit.javascript.configuration.SupportedBrowser.EDGE;
20  import static com.gargoylesoftware.htmlunit.javascript.configuration.SupportedBrowser.FF;
21  
22  import com.gargoylesoftware.htmlunit.html.DomCharacterData;
23  import com.gargoylesoftware.htmlunit.html.DomElement;
24  import com.gargoylesoftware.htmlunit.javascript.configuration.JsxClass;
25  import com.gargoylesoftware.htmlunit.javascript.configuration.JsxConstructor;
26  import com.gargoylesoftware.htmlunit.javascript.configuration.JsxFunction;
27  import com.gargoylesoftware.htmlunit.javascript.configuration.JsxGetter;
28  import com.gargoylesoftware.htmlunit.javascript.configuration.JsxSetter;
29  import com.gargoylesoftware.htmlunit.javascript.host.Element;
30  
31  import net.sourceforge.htmlunit.corejs.javascript.Context;
32  import net.sourceforge.htmlunit.corejs.javascript.Function;
33  import net.sourceforge.htmlunit.corejs.javascript.Scriptable;
34  
35  /**
36   * A JavaScript object for {@code CharacterData}.
37   *
38   * @author David K. Taylor
39   * @author Chris Erskine
40   * @author Ahmed Ashour
41   */
42  @JsxClass
43  public class CharacterData extends Node {
44  
45      /**
46       * Creates an instance.
47       */
48      @JsxConstructor({CHROME, FF, EDGE})
49      public CharacterData() {
50      }
51  
52      /**
53       * Gets the JavaScript property {@code data} for this character data.
54       * @return the String of data
55       */
56      @JsxGetter
57      public Object getData() {
58          return getDomCharacterDataOrDie().getData();
59      }
60  
61      /**
62       * Sets the JavaScript property {@code data} for this character data.
63       * @param newValue the new String of data
64       */
65      @JsxSetter
66      public void setData(final String newValue) {
67          getDomCharacterDataOrDie().setData(newValue);
68      }
69  
70      /**
71       * Gets the number of character in the character data.
72       * @return the number of characters
73       */
74      @JsxGetter
75      public int getLength() {
76          return getDomCharacterDataOrDie().getLength();
77      }
78  
79      /**
80       * Append a string to character data.
81       * @param arg the string to be appended to the character data
82       */
83      @JsxFunction
84      public void appendData(final String arg) {
85          getDomCharacterDataOrDie().appendData(arg);
86      }
87  
88      /**
89       * Delete characters from character data.
90       * @param offset the position of the first character to be deleted
91       * @param count the number of characters to be deleted
92       */
93      @JsxFunction
94      public void deleteData(final int offset, final int count) {
95          if (offset < 0) {
96              throw Context.reportRuntimeError("Provided offset: " + offset + " is less than zero.");
97          }
98  
99          if (getBrowserVersion().hasFeature(JS_DOM_CDATA_DELETE_THROWS_NEGATIVE_COUNT)) {
100             if (count < 0) {
101                 throw Context.reportRuntimeError("Provided count: " + count + " is less than zero.");
102             }
103             if (count == 0) {
104                 return;
105             }
106         }
107 
108         final DomCharacterData domCharacterData = getDomCharacterDataOrDie();
109         if (offset > domCharacterData.getLength()) {
110             throw Context.reportRuntimeError("Provided offset: " + offset + " is greater than length.");
111         }
112 
113         domCharacterData.deleteData(offset, count);
114     }
115 
116     /**
117      * Insert a string into character data.
118      * @param offset the position within the first character at which
119      * the string is to be inserted.
120      * @param arg the string to insert
121      */
122     @JsxFunction
123     public void insertData(final int offset, final String arg) {
124         getDomCharacterDataOrDie().insertData(offset, arg);
125     }
126 
127     /**
128      * Replace characters of character data with a string.
129      * @param offset the position within the first character at which
130      * the string is to be replaced.
131      * @param count the number of characters to be replaced
132      * @param arg the string that replaces the count characters beginning at
133      * the character at offset.
134      */
135     @JsxFunction
136     public void replaceData(final int offset, final int count, final String arg) {
137         getDomCharacterDataOrDie().replaceData(offset, count, arg);
138     }
139 
140     /**
141      * Extract a substring from character data.
142      * @param offset the position of the first character to be extracted
143      * @param count the number of characters to be extracted
144      * @return a string that consists of the count characters of the character
145      *         data starting from the character at position offset
146      */
147     @JsxFunction
148     public String substringData(final int offset, final int count) {
149         return getDomCharacterDataOrDie().substringData(offset, count);
150     }
151 
152     private DomCharacterData getDomCharacterDataOrDie() {
153         return (DomCharacterData) super.getDomNodeOrDie();
154     }
155 
156     /**
157      * Returns the next element sibling.
158      * @return the next element sibling
159      */
160     @JsxGetter({CHROME, FF})
161     public Element getNextElementSibling() {
162         final DomElement child = getDomNodeOrDie().getNextElementSibling();
163         if (child != null) {
164             return (Element) child.getScriptableObject();
165         }
166         return null;
167     }
168 
169     /**
170      * Returns the previous element sibling.
171      * @return the previous element sibling
172      */
173     @JsxGetter({CHROME, FF})
174     public Element getPreviousElementSibling() {
175         final DomElement child = getDomNodeOrDie().getPreviousElementSibling();
176         if (child != null) {
177             return (Element) child.getScriptableObject();
178         }
179         return null;
180     }
181 
182     /**
183      * {@inheritDoc}
184      */
185     @Override
186     @JsxFunction({CHROME, FF, EDGE})
187     public void remove() {
188         super.remove();
189     }
190 
191     /**
192      * Inserts a set of Node or DOMString objects in the children list of this ChildNode's parent,
193      * just before this ChildNode.
194      * @param context the context
195      * @param thisObj this object
196      * @param args the arguments
197      * @param function the function
198      */
199     @JsxFunction({CHROME, FF})
200     public static void before(final Context context, final Scriptable thisObj, final Object[] args,
201             final Function function) {
202         Node.before(context, thisObj, args, function);
203     }
204 
205     /**
206      * Inserts a set of Node or DOMString objects in the children list of this ChildNode's parent,
207      * just after this ChildNode.
208      * @param context the context
209      * @param thisObj this object
210      * @param args the arguments
211      * @param function the function
212      */
213     @JsxFunction({CHROME, FF})
214     public static void after(final Context context, final Scriptable thisObj, final Object[] args,
215             final Function function) {
216         Node.after(context, thisObj, args, function);
217     }
218 
219     /**
220      * Replaces the node wit a set of Node or DOMString objects.
221      * @param context the context
222      * @param thisObj this object
223      * @param args the arguments
224      * @param function the function
225      */
226     @JsxFunction({CHROME, FF})
227     public static void replaceWith(final Context context, final Scriptable thisObj, final Object[] args,
228             final Function function) {
229         Node.replaceWith(context, thisObj, args, function);
230     }
231 }