001: /*
002: * Copyright (c) 2002-2008 Gargoyle Software Inc. All rights reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * 1. Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: * 2. Redistributions in binary form must reproduce the above copyright notice,
010: * this list of conditions and the following disclaimer in the documentation
011: * and/or other materials provided with the distribution.
012: * 3. The end-user documentation included with the redistribution, if any, must
013: * include the following acknowledgment:
014: *
015: * "This product includes software developed by Gargoyle Software Inc.
016: * (http://www.GargoyleSoftware.com/)."
017: *
018: * Alternately, this acknowledgment may appear in the software itself, if
019: * and wherever such third-party acknowledgments normally appear.
020: * 4. The name "Gargoyle Software" must not be used to endorse or promote
021: * products derived from this software without prior written permission.
022: * For written permission, please contact info@GargoyleSoftware.com.
023: * 5. Products derived from this software may not be called "HtmlUnit", nor may
024: * "HtmlUnit" appear in their name, without prior written permission of
025: * Gargoyle Software Inc.
026: *
027: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
028: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
029: * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARGOYLE
030: * SOFTWARE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
031: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
032: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
033: * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
034: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
035: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
036: * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
037: */
038: package com.gargoylesoftware.htmlunit.html;
039:
040: import java.util.Map;
041: import java.util.List;
042: import java.util.ArrayList;
043: import java.util.Collections;
044: import java.util.Iterator;
045: import java.util.NoSuchElementException;
046:
047: /**
048: * Wrapper for the html element "tr"
049: *
050: * @version $Revision: 2132 $
051: * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
052: * @author David K. Taylor
053: * @author <a href="mailto:cse@dynabean.de">Christian Sell</a>
054: * @author Ahmed Ashour
055: */
056: public class HtmlTableRow extends ClickableElement {
057:
058: private static final long serialVersionUID = 1296770669696592851L;
059:
060: /** the HTML tag represented by this element */
061: public static final String TAG_NAME = "tr";
062:
063: /**
064: * Create an instance
065: *
066: * @param page The page that this element is contained within
067: * @param attributes the initial attributes
068: * @deprecated You should not directly construct HtmlTableRow.
069: */
070: //TODO: to be removed, deprecated after 1.11
071: public HtmlTableRow(final HtmlPage page, final Map attributes) {
072: this (null, TAG_NAME, page, attributes);
073: }
074:
075: /**
076: * Create an instance
077: *
078: * @param namespaceURI the URI that identifies an XML namespace.
079: * @param qualifiedName The qualified name of the element type to instantiate
080: * @param page The page that this element is contained within
081: * @param attributes the initial attributes
082: */
083: HtmlTableRow(final String namespaceURI, final String qualifiedName,
084: final HtmlPage page, final Map attributes) {
085: super (namespaceURI, qualifiedName, page, attributes);
086: }
087:
088: /**
089: * @return an Iterator over the all HtmlTableCell objects in this row
090: */
091: public CellIterator getCellIterator() {
092: return new CellIterator();
093: }
094:
095: /**
096: * @return an immutable list containing all the HtmlTableCells held by this object
097: * @see #getCellIterator
098: */
099: public List getCells() {
100: final List result = new ArrayList();
101: for (final CellIterator iterator = getCellIterator(); iterator
102: .hasNext();) {
103: result.add(iterator.next());
104: }
105: return Collections.unmodifiableList(result);
106: }
107:
108: /**
109: * @param index the 0-based index
110: * @return the cell at the given index
111: * @throws IndexOutOfBoundsException if there is no cell at the given index
112: */
113: public HtmlTableCell getCell(final int index)
114: throws IndexOutOfBoundsException {
115: int count = 0;
116: for (final CellIterator iterator = getCellIterator(); iterator
117: .hasNext(); count++) {
118: final HtmlTableCell next = iterator.nextCell();
119: if (count == index) {
120: return next;
121: }
122: }
123: throw new IndexOutOfBoundsException();
124: }
125:
126: /**
127: * Return the value of the attribute "align". Refer to the
128: * <a href='http://www.w3.org/TR/html401/'>HTML 4.01</a>
129: * documentation for details on the use of this attribute.
130: *
131: * @return The value of the attribute "align"
132: * or an empty string if that attribute isn't defined.
133: */
134: public final String getAlignAttribute() {
135: return getAttributeValue("align");
136: }
137:
138: /**
139: * Return the value of the attribute "char". Refer to the
140: * <a href='http://www.w3.org/TR/html401/'>HTML 4.01</a>
141: * documentation for details on the use of this attribute.
142: *
143: * @return The value of the attribute "char"
144: * or an empty string if that attribute isn't defined.
145: */
146: public final String getCharAttribute() {
147: return getAttributeValue("char");
148: }
149:
150: /**
151: * Return the value of the attribute "charoff". Refer to the
152: * <a href='http://www.w3.org/TR/html401/'>HTML 4.01</a>
153: * documentation for details on the use of this attribute.
154: *
155: * @return The value of the attribute "charoff"
156: * or an empty string if that attribute isn't defined.
157: */
158: public final String getCharoffAttribute() {
159: return getAttributeValue("charoff");
160: }
161:
162: /**
163: * Return the value of the attribute "valign". Refer to the
164: * <a href='http://www.w3.org/TR/html401/'>HTML 4.01</a>
165: * documentation for details on the use of this attribute.
166: *
167: * @return The value of the attribute "valign"
168: * or an empty string if that attribute isn't defined.
169: */
170: public final String getValignAttribute() {
171: return getAttributeValue("valign");
172: }
173:
174: /**
175: * Gets the table containing this row
176: * @return the table
177: */
178: public HtmlTable getEnclosingTable() {
179: return (HtmlTable) getEnclosingElement("table");
180: }
181:
182: /**
183: * Return the value of the attribute "bgcolor". Refer to the
184: * <a href='http://www.w3.org/TR/html401/'>HTML 4.01</a>
185: * documentation for details on the use of this attribute.
186: *
187: * @return The value of the attribute "bgcolor"
188: * or an empty string if that attribute isn't defined.
189: */
190: public final String getBgcolorAttribute() {
191: return getAttributeValue("bgcolor");
192: }
193:
194: /**
195: * an Iterator over the HtmlTableCells contained in this row. It will also dive
196: * into nested forms, even though that is illegal HTML
197: */
198: public class CellIterator implements Iterator {
199: private HtmlTableCell nextCell_;
200: private HtmlForm currentForm_;
201:
202: /** create an instance */
203: public CellIterator() {
204: setNextCell(getFirstDomChild());
205: }
206:
207: /** @return whether there is another cell available */
208: public boolean hasNext() {
209: return nextCell_ != null;
210: }
211:
212: /**
213: * @return the next cell
214: * @throws NoSuchElementException if no cell is available
215: */
216: public Object next() throws NoSuchElementException {
217: return nextCell();
218: }
219:
220: /**
221: * remove the cell under the cursor from the current row
222: * @throws IllegalStateException if there is no currenr row
223: */
224: public void remove() throws IllegalStateException {
225: if (nextCell_ == null) {
226: throw new IllegalStateException();
227: }
228: final DomNode sibling = nextCell_.getPreviousDomSibling();
229: if (sibling != null) {
230: sibling.remove();
231: }
232: }
233:
234: /**
235: * @return the next cell
236: * @throws NoSuchElementException if no cell is available
237: */
238: public HtmlTableCell nextCell() throws NoSuchElementException {
239:
240: if (nextCell_ != null) {
241: final HtmlTableCell result = nextCell_;
242: setNextCell(nextCell_.getNextDomSibling());
243: return result;
244: } else {
245: throw new NoSuchElementException();
246: }
247: }
248:
249: /**
250: * set the internal position to the next cell, starting at the given node
251: * @param node the node to mark as the next cell. If this is not a cell, the
252: * next reachable cell will be marked
253: */
254: private void setNextCell(final DomNode node) {
255:
256: nextCell_ = null;
257: for (DomNode next = node; next != null; next = next
258: .getNextDomSibling()) {
259: if (next instanceof HtmlTableCell) {
260: nextCell_ = (HtmlTableCell) next;
261: return;
262: } else if (currentForm_ == null
263: && next instanceof HtmlForm) {
264: // Completely illegal html but some of the big sites (ie amazon) do this
265: currentForm_ = (HtmlForm) next;
266: setNextCell(next.getFirstDomChild());
267: return;
268: }
269: }
270: if (currentForm_ != null) {
271: final DomNode form = currentForm_;
272: currentForm_ = null;
273: setNextCell(form.getNextDomSibling());
274: }
275: }
276: }
277: }
|