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.html;
16  
17  import java.io.Serializable;
18  import java.util.ArrayList;
19  import java.util.List;
20  import java.util.function.Supplier;
21  
22  import org.htmlunit.html.DomElement;
23  import org.htmlunit.html.DomNode;
24  import org.htmlunit.html.HtmlPage;
25  import org.htmlunit.html.HtmlTable;
26  import org.htmlunit.html.HtmlTableRow;
27  import org.htmlunit.javascript.HtmlUnitScriptable;
28  import org.htmlunit.javascript.JavaScriptEngine;
29  import org.htmlunit.javascript.configuration.JsxClass;
30  import org.htmlunit.javascript.configuration.JsxConstructor;
31  import org.htmlunit.javascript.configuration.JsxFunction;
32  import org.htmlunit.javascript.configuration.JsxGetter;
33  import org.htmlunit.javascript.configuration.JsxSetter;
34  import org.htmlunit.javascript.host.dom.DOMException;
35  
36  /**
37   * The JavaScript object {@code HTMLTableRowElement}.
38   *
39   * @author Marc Guillemot
40   * @author Chris Erskine
41   * @author Ahmed Ashour
42   * @author Ronald Brill
43   * @author Frank Danek
44   */
45  @JsxClass(domClass = HtmlTableRow.class)
46  public class HTMLTableRowElement extends HTMLTableComponent {
47  
48      /**
49       * JavaScript constructor.
50       */
51      @Override
52      @JsxConstructor
53      public void jsConstructor() {
54          super.jsConstructor();
55      }
56  
57      /**
58       * Returns the index of the row within the parent table.
59       * @return the index of the row within the parent table
60       * @see <a href="http://msdn.microsoft.com/en-us/library/ms534377.aspx">MSDN Documentation</a>
61       */
62      @JsxGetter
63      public int getRowIndex() {
64          final HtmlTableRow row = (HtmlTableRow) getDomNodeOrDie();
65          final HtmlTable table = row.getEnclosingTable();
66          if (table == null) { // a not attached document.createElement('TR')
67              return -1;
68          }
69          return table.getRows().indexOf(row);
70      }
71  
72      /**
73       * Returns the index of the row within the enclosing thead, tbody or tfoot.
74       * @return the index of the row within the enclosing thead, tbody or tfoot
75       * @see <a href="http://msdn.microsoft.com/en-us/library/ms534621.aspx">MSDN Documentation</a>
76       * @see <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-79105901">
77       * DOM Level 1</a>
78       */
79      @JsxGetter
80      public int getSectionRowIndex() {
81          DomNode row = getDomNodeOrDie();
82          final HtmlTable table = ((HtmlTableRow) row).getEnclosingTable();
83          if (table == null) { // a not attached document.createElement('TR')
84              return -1;
85          }
86          int index = -1;
87          while (row != null) {
88              if (row instanceof HtmlTableRow) {
89                  index++;
90              }
91              row = row.getPreviousSibling();
92          }
93          return index;
94      }
95  
96      /**
97       * Returns the cells in the row.
98       * @return the cells in the row
99       */
100     @JsxGetter
101     public HTMLCollection getCells() {
102         final HtmlTableRow row = (HtmlTableRow) getDomNodeOrDie();
103 
104         final HTMLCollection cells = new HTMLCollection(row, false);
105         cells.setElementsSupplier((Supplier<List<DomNode>> & Serializable) () -> new ArrayList<>(row.getCells()));
106         return cells;
107     }
108 
109     /**
110      * Returns the value of the {@code bgColor} attribute.
111      * @return the value of the {@code bgColor} attribute
112      * @see <a href="http://msdn.microsoft.com/en-us/library/ms533505.aspx">MSDN Documentation</a>
113      */
114     @JsxGetter
115     public String getBgColor() {
116         return getDomNodeOrDie().getAttribute("bgColor");
117     }
118 
119     /**
120      * Sets the value of the {@code bgColor} attribute.
121      * @param bgColor the value of the {@code bgColor} attribute
122      * @see <a href="http://msdn.microsoft.com/en-us/library/ms533505.aspx">MSDN Documentation</a>
123      */
124     @JsxSetter
125     public void setBgColor(final String bgColor) {
126         setColorAttribute("bgColor", bgColor);
127     }
128 
129     /**
130      * Inserts a new cell at the specified index in the element's cells collection. If the index
131      * is -1 or there is no index specified, then the cell is appended at the end of the
132      * element's cells collection.
133      * @see <a href="http://msdn.microsoft.com/en-us/library/ms536455.aspx">MSDN Documentation</a>
134      * @param index specifies where to insert the cell in the tr.
135      *        The default value is -1, which appends the new cell to the end of the cells collection
136      * @return the newly-created cell
137      */
138     @JsxFunction
139     public HtmlUnitScriptable insertCell(final Object index) {
140         int position = -1;
141         if (!JavaScriptEngine.isUndefined(index)) {
142             position = (int) JavaScriptEngine.toNumber(index);
143         }
144         final HtmlTableRow htmlRow = (HtmlTableRow) getDomNodeOrDie();
145 
146         final boolean indexValid = position >= -1 && position <= htmlRow.getCells().size();
147         if (indexValid) {
148             final DomElement newCell = ((HtmlPage) htmlRow.getPage()).createElement("td");
149             if (position == -1 || position == htmlRow.getCells().size()) {
150                 htmlRow.appendChild(newCell);
151             }
152             else {
153                 htmlRow.getCell(position).insertBefore(newCell);
154             }
155             return getScriptableFor(newCell);
156         }
157         throw JavaScriptEngine.asJavaScriptException(
158                 getWindow(),
159                 "Index or size is negative or greater than the allowed amount",
160                 DOMException.INDEX_SIZE_ERR);
161     }
162 
163     /**
164      * Deletes the cell at the specified index in the element's cells collection. If the index
165      * is -1, then the last cell is deleted.
166      * @see <a href="http://msdn.microsoft.com/en-us/library/ms536406.aspx">MSDN Documentation</a>
167      * @see <a href="http://www.w3.org/TR/2003/REC-DOM-Level-2-HTML-20030109/html.html#ID-11738598">W3C DOM Level2</a>
168      * @param index specifies the cell to delete.
169      */
170     @JsxFunction
171     public void deleteCell(final Object index) {
172         if (JavaScriptEngine.isUndefined(index)) {
173             throw JavaScriptEngine.typeError("No enough arguments");
174         }
175 
176         int position = (int) JavaScriptEngine.toNumber(index);
177 
178         final HtmlTableRow htmlRow = (HtmlTableRow) getDomNodeOrDie();
179 
180         if (position == -1) {
181             position = htmlRow.getCells().size() - 1;
182         }
183         final boolean indexValid = position >= -1 && position <= htmlRow.getCells().size();
184         if (!indexValid) {
185             throw JavaScriptEngine.asJavaScriptException(
186                     getWindow(),
187                     "Index or size is negative or greater than the allowed amount",
188                     DOMException.INDEX_SIZE_ERR);
189         }
190 
191         htmlRow.getCell(position).remove();
192     }
193 
194     /**
195      * Overwritten to throw an exception.
196      * @param value the new value for replacing this node
197      */
198     @Override
199     public void setOuterHTML(final Object value) {
200         throw JavaScriptEngine.reportRuntimeError("outerHTML is read-only for tag 'tr'");
201     }
202 }