Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / html / HTMLTableRowsCollection.cpp
1 /*
2  * Copyright (C) 2008, 2011, 2012, 2014 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include "config.h"
30 #include "core/html/HTMLTableRowsCollection.h"
31
32 #include "core/HTMLNames.h"
33 #include "core/dom/ElementTraversal.h"
34 #include "core/html/HTMLTableElement.h"
35 #include "core/html/HTMLTableRowElement.h"
36
37 namespace blink {
38
39 using namespace HTMLNames;
40
41 static inline bool isInSection(HTMLTableRowElement& row, const HTMLQualifiedName& sectionTag)
42 {
43     // Because we know that the parent is a table or a section, it's safe to cast it to an HTMLElement
44     // giving us access to the faster hasTagName overload from that class.
45     return toHTMLElement(row.parentNode())->hasTagName(sectionTag);
46 }
47
48 HTMLTableRowElement* HTMLTableRowsCollection::rowAfter(HTMLTableElement& table, HTMLTableRowElement* previous)
49 {
50     // Start by looking for the next row in this section.
51     // Continue only if there is none.
52     if (previous && previous->parentNode() != table) {
53         if (HTMLTableRowElement* row = Traversal<HTMLTableRowElement>::nextSibling(*previous))
54             return row;
55     }
56
57     // If still looking at head sections, find the first row in the next head section.
58     HTMLElement* child = 0;
59     if (!previous)
60         child = Traversal<HTMLElement>::firstChild(table);
61     else if (isInSection(*previous, theadTag))
62         child = Traversal<HTMLElement>::nextSibling(*previous->parentNode());
63     for (; child; child = Traversal<HTMLElement>::nextSibling(*child)) {
64         if (child->hasTagName(theadTag)) {
65             if (HTMLTableRowElement* row = Traversal<HTMLTableRowElement>::firstChild(*child))
66                 return row;
67         }
68     }
69
70     // If still looking at top level and bodies, find the next row in top level or the first in the next body section.
71     if (!previous || isInSection(*previous, theadTag))
72         child = Traversal<HTMLElement>::firstChild(table);
73     else if (previous->parentNode() == table)
74         child = Traversal<HTMLElement>::nextSibling(*previous);
75     else if (isInSection(*previous, tbodyTag))
76         child = Traversal<HTMLElement>::nextSibling(*previous->parentNode());
77     for (; child; child = Traversal<HTMLElement>::nextSibling(*child)) {
78         if (isHTMLTableRowElement(child))
79             return toHTMLTableRowElement(child);
80         if (child->hasTagName(tbodyTag)) {
81             if (HTMLTableRowElement* row = Traversal<HTMLTableRowElement>::firstChild(*child))
82                 return row;
83         }
84     }
85
86     // Find the first row in the next foot section.
87     if (!previous || !isInSection(*previous, tfootTag))
88         child = Traversal<HTMLElement>::firstChild(table);
89     else
90         child = Traversal<HTMLElement>::nextSibling(*previous->parentNode());
91     for (; child; child = Traversal<HTMLElement>::nextSibling(*child)) {
92         if (child->hasTagName(tfootTag)) {
93             if (HTMLTableRowElement* row = Traversal<HTMLTableRowElement>::firstChild(*child))
94                 return row;
95         }
96     }
97
98     return nullptr;
99 }
100
101 HTMLTableRowElement* HTMLTableRowsCollection::lastRow(HTMLTableElement& table)
102 {
103     for (HTMLElement* tfoot = Traversal<HTMLElement>::lastChild(table, HasHTMLTagName(tfootTag)); tfoot; tfoot = Traversal<HTMLElement>::previousSibling(*tfoot, HasHTMLTagName(tfootTag))) {
104         if (HTMLTableRowElement* lastRow = Traversal<HTMLTableRowElement>::lastChild(*tfoot))
105                 return lastRow;
106     }
107
108     for (HTMLElement* child = Traversal<HTMLElement>::lastChild(table); child; child = Traversal<HTMLElement>::previousSibling(*child)) {
109         if (isHTMLTableRowElement(child))
110             return toHTMLTableRowElement(child);
111         if (child->hasTagName(tbodyTag)) {
112             if (HTMLTableRowElement* lastRow = Traversal<HTMLTableRowElement>::lastChild(*child))
113                 return lastRow;
114         }
115     }
116
117     for (HTMLElement* thead = Traversal<HTMLElement>::lastChild(table, HasHTMLTagName(theadTag)); thead; thead = Traversal<HTMLElement>::previousSibling(*thead, HasHTMLTagName(theadTag))) {
118         if (HTMLTableRowElement* lastRow = Traversal<HTMLTableRowElement>::lastChild(*thead))
119             return lastRow;
120     }
121
122     return nullptr;
123 }
124
125 // Must call get() on the table in case that argument is compiled before dereferencing the
126 // table to get at the collection cache. Order of argument evaluation is undefined and can
127 // differ between compilers.
128 HTMLTableRowsCollection::HTMLTableRowsCollection(ContainerNode& table)
129     : HTMLCollection(table, TableRows, OverridesItemAfter)
130 {
131     ASSERT(isHTMLTableElement(table));
132 }
133
134 PassRefPtrWillBeRawPtr<HTMLTableRowsCollection> HTMLTableRowsCollection::create(ContainerNode& table, CollectionType type)
135 {
136     ASSERT_UNUSED(type, type == TableRows);
137     return adoptRefWillBeNoop(new HTMLTableRowsCollection(table));
138 }
139
140 Element* HTMLTableRowsCollection::virtualItemAfter(Element* previous) const
141 {
142     return rowAfter(toHTMLTableElement(ownerNode()), toHTMLTableRowElement(previous));
143 }
144
145 }