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.html;
16  
17  import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.JS_TABLE_ROW_DELETE_CELL_REQUIRES_INDEX;
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  import static com.gargoylesoftware.htmlunit.javascript.configuration.SupportedBrowser.IE;
22  
23  import java.util.ArrayList;
24  import java.util.List;
25  
26  import com.gargoylesoftware.htmlunit.html.DomElement;
27  import com.gargoylesoftware.htmlunit.html.DomNode;
28  import com.gargoylesoftware.htmlunit.html.HtmlPage;
29  import com.gargoylesoftware.htmlunit.html.HtmlTable;
30  import com.gargoylesoftware.htmlunit.html.HtmlTableRow;
31  import com.gargoylesoftware.htmlunit.javascript.configuration.JsxClass;
32  import com.gargoylesoftware.htmlunit.javascript.configuration.JsxConstructor;
33  import com.gargoylesoftware.htmlunit.javascript.configuration.JsxFunction;
34  import com.gargoylesoftware.htmlunit.javascript.configuration.JsxGetter;
35  import com.gargoylesoftware.htmlunit.javascript.configuration.JsxSetter;
36  
37  import net.sourceforge.htmlunit.corejs.javascript.Context;
38  import net.sourceforge.htmlunit.corejs.javascript.Undefined;
39  
40  /**
41   * The JavaScript object {@code HTMLTableRowElement}.
42   *
43   * @author Marc Guillemot
44   * @author Chris Erskine
45   * @author Ahmed Ashour
46   * @author Ronald Brill
47   * @author Frank Danek
48   */
49  @JsxClass(domClass = HtmlTableRow.class)
50  public class HTMLTableRowElement extends HTMLTableComponent {
51  
52      /**
53       * Creates an instance.
54       */
55      @JsxConstructor({CHROME, FF, EDGE})
56      public HTMLTableRowElement() {
57      }
58  
59      /**
60       * Returns the index of the row within the parent table.
61       * @return the index of the row within the parent table
62       * @see <a href="http://msdn.microsoft.com/en-us/library/ms534377.aspx">MSDN Documentation</a>
63       */
64      @JsxGetter
65      public int getRowIndex() {
66          final HtmlTableRow row = (HtmlTableRow) getDomNodeOrDie();
67          final HtmlTable table = row.getEnclosingTable();
68          if (table == null) { // a not attached document.createElement('TR')
69              return -1;
70          }
71          return table.getRows().indexOf(row);
72      }
73  
74      /**
75       * Returns the index of the row within the enclosing thead, tbody or tfoot.
76       * @return the index of the row within the enclosing thead, tbody or tfoot
77       * @see <a href="http://msdn.microsoft.com/en-us/library/ms534621.aspx">MSDN Documentation</a>
78       * @see <a href="http://www.w3.org/TR/2000/WD-DOM-Level-1-20000929/level-one-html.html#ID-79105901">
79       * DOM Level 1</a>
80       */
81      @JsxGetter
82      public int getSectionRowIndex() {
83          DomNode row = getDomNodeOrDie();
84          final HtmlTable table = ((HtmlTableRow) row).getEnclosingTable();
85          if (table == null) { // a not attached document.createElement('TR')
86              return -1;
87          }
88          int index = -1;
89          while (row != null) {
90              if (row instanceof HtmlTableRow) {
91                  index++;
92              }
93              row = row.getPreviousSibling();
94          }
95          return index;
96      }
97  
98      /**
99       * Returns the cells in the row.
100      * @return the cells in the row
101      */
102     @JsxGetter
103     public Object getCells() {
104         final HtmlTableRow row = (HtmlTableRow) getDomNodeOrDie();
105         return new HTMLCollection(row, false) {
106             @Override
107             protected List<DomNode> computeElements() {
108                 return new ArrayList<>(row.getCells());
109             }
110         };
111     }
112 
113     /**
114      * Returns the value of the {@code bgColor} attribute.
115      * @return the value of the {@code bgColor} attribute
116      * @see <a href="http://msdn.microsoft.com/en-us/library/ms533505.aspx">MSDN Documentation</a>
117      */
118     @JsxGetter
119     public String getBgColor() {
120         return getDomNodeOrDie().getAttribute("bgColor");
121     }
122 
123     /**
124      * Sets the value of the {@code bgColor} attribute.
125      * @param bgColor the value of the {@code bgColor} attribute
126      * @see <a href="http://msdn.microsoft.com/en-us/library/ms533505.aspx">MSDN Documentation</a>
127      */
128     @JsxSetter
129     public void setBgColor(final String bgColor) {
130         setColorAttribute("bgColor", bgColor);
131     }
132 
133     /**
134      * Inserts a new cell at the specified index in the element's cells collection. If the index
135      * is -1 or there is no index specified, then the cell is appended at the end of the
136      * element's cells collection.
137      * @see <a href="http://msdn.microsoft.com/en-us/library/ms536455.aspx">MSDN Documentation</a>
138      * @param index specifies where to insert the cell in the tr.
139      *        The default value is -1, which appends the new cell to the end of the cells collection
140      * @return the newly-created cell
141      */
142     @JsxFunction
143     public Object insertCell(final Object index) {
144         int position = -1;
145         if (index != Undefined.instance) {
146             position = (int) Context.toNumber(index);
147         }
148         final HtmlTableRow htmlRow = (HtmlTableRow) getDomNodeOrDie();
149 
150         final boolean indexValid = position >= -1 && position <= htmlRow.getCells().size();
151         if (indexValid) {
152             final DomElement newCell = ((HtmlPage) htmlRow.getPage()).createElement("td");
153             if (position == -1 || position == htmlRow.getCells().size()) {
154                 htmlRow.appendChild(newCell);
155             }
156             else {
157                 htmlRow.getCell(position).insertBefore(newCell);
158             }
159             return getScriptableFor(newCell);
160         }
161         throw Context.reportRuntimeError("Index or size is negative or greater than the allowed amount");
162     }
163 
164     /**
165      * Deletes the cell at the specified index in the element's cells collection. If the index
166      * is -1 (or while simulating IE, when there is no index specified), then the last cell is deleted.
167      * @see <a href="http://msdn.microsoft.com/en-us/library/ms536406.aspx">MSDN Documentation</a>
168      * @see <a href="http://www.w3.org/TR/2003/REC-DOM-Level-2-HTML-20030109/html.html#ID-11738598">W3C DOM Level2</a>
169      * @param index specifies the cell to delete.
170      */
171     @JsxFunction
172     public void deleteCell(final Object index) {
173         int position = -1;
174         if (index != Undefined.instance) {
175             position = (int) Context.toNumber(index);
176         }
177         else if (getBrowserVersion().hasFeature(JS_TABLE_ROW_DELETE_CELL_REQUIRES_INDEX)) {
178             throw Context.reportRuntimeError("No enough arguments");
179         }
180 
181         final HtmlTableRow htmlRow = (HtmlTableRow) getDomNodeOrDie();
182 
183         if (position == -1) {
184             position = htmlRow.getCells().size() - 1;
185         }
186         final boolean indexValid = position >= -1 && position <= htmlRow.getCells().size();
187         if (!indexValid) {
188             throw Context.reportRuntimeError("Index or size is negative or greater than the allowed amount");
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 Context.reportRuntimeError("outerHTML is read-only for tag 'tr'");
201     }
202 
203     /**
204      * Gets the {@code borderColor} attribute.
205      * @return the attribute
206      */
207     @JsxGetter(IE)
208     public String getBorderColor() {
209         return getDomNodeOrDie().getAttribute("borderColor");
210     }
211 
212     /**
213      * Sets the {@code borderColor} attribute.
214      * @param borderColor the new attribute
215      */
216     @JsxSetter(IE)
217     public void setBorderColor(final String borderColor) {
218         setColorAttribute("borderColor", borderColor);
219     }
220 
221     /**
222      * Gets the {@code borderColor} attribute.
223      * @return the attribute
224      */
225     @JsxGetter(IE)
226     public String getBorderColorDark() {
227         return getDomNodeOrDie().getAttribute("borderColorDark");
228     }
229 
230     /**
231      * Sets the {@code borderColor} attribute.
232      * @param borderColor the new attribute
233      */
234     @JsxSetter(IE)
235     public void setBorderColorDark(final String borderColor) {
236         setColorAttribute("borderColorDark", borderColor);
237     }
238 
239     /**
240      * Gets the {@code borderColor} attribute.
241      * @return the attribute
242      */
243     @JsxGetter(IE)
244     public String getBorderColorLight() {
245         return getDomNodeOrDie().getAttribute("borderColorLight");
246     }
247 
248     /**
249      * Sets the {@code borderColor} attribute.
250      * @param borderColor the new attribute
251      */
252     @JsxSetter(IE)
253     public void setBorderColorLight(final String borderColor) {
254         setColorAttribute("borderColorLight", borderColor);
255     }
256 }