1 /* 2 * Copyright (C) 1997 Martin Jones (mjones (at) kde.org) 3 * (C) 1997 Torben Weis (weis (at) kde.org) 4 * (C) 1998 Waldo Bastian (bastian (at) kde.org) 5 * (C) 1999 Lars Knoll (knoll (at) kde.org) 6 * (C) 1999 Antti Koivisto (koivisto (at) kde.org) 7 * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. 8 * 9 * This library is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU Library General Public 11 * License as published by the Free Software Foundation; either 12 * version 2 of the License, or (at your option) any later version. 13 * 14 * This library is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * Library General Public License for more details. 18 * 19 * You should have received a copy of the GNU Library General Public License 20 * along with this library; see the file COPYING.LIB. If not, write to 21 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 22 * Boston, MA 02110-1301, USA. 23 */ 24 25 #include "config.h" 26 #include "HTMLTableRowElement.h" 27 28 #include "ExceptionCode.h" 29 #include "HTMLCollection.h" 30 #include "HTMLNames.h" 31 #include "HTMLTableCellElement.h" 32 #include "HTMLTableElement.h" 33 #include "HTMLTableSectionElement.h" 34 #include "NodeList.h" 35 #include "Text.h" 36 37 namespace WebCore { 38 39 using namespace HTMLNames; 40 41 HTMLTableRowElement::HTMLTableRowElement(const QualifiedName& tagName, Document* doc) 42 : HTMLTablePartElement(tagName, doc) 43 { 44 ASSERT(hasTagName(trTag)); 45 } 46 47 bool HTMLTableRowElement::checkDTD(const Node* newChild) 48 { 49 if (newChild->isTextNode()) 50 return static_cast<const Text*>(newChild)->containsOnlyWhitespace(); 51 return newChild->hasTagName(tdTag) || newChild->hasTagName(thTag) || 52 newChild->hasTagName(formTag) || newChild->hasTagName(scriptTag); 53 } 54 55 ContainerNode* HTMLTableRowElement::addChild(PassRefPtr<Node> child) 56 { 57 if (child->hasTagName(formTag)) { 58 // First add the child. 59 HTMLTablePartElement::addChild(child); 60 61 // Now simply return ourselves as the container to insert into. 62 // This has the effect of demoting the form to a leaf and moving it safely out of the way. 63 return this; 64 } 65 66 return HTMLTablePartElement::addChild(child); 67 } 68 69 int HTMLTableRowElement::rowIndex() const 70 { 71 Node *table = parentNode(); 72 if (!table) 73 return -1; 74 table = table->parentNode(); 75 if (!table || !table->hasTagName(tableTag)) 76 return -1; 77 78 // To match Firefox, the row indices work like this: 79 // Rows from the first <thead> are numbered before all <tbody> rows. 80 // Rows from the first <tfoot> are numbered after all <tbody> rows. 81 // Rows from other <thead> and <tfoot> elements don't get row indices at all. 82 83 int rIndex = 0; 84 85 if (HTMLTableSectionElement* head = static_cast<HTMLTableElement*>(table)->tHead()) { 86 for (Node *row = head->firstChild(); row; row = row->nextSibling()) { 87 if (row == this) 88 return rIndex; 89 if (row->hasTagName(trTag)) 90 ++rIndex; 91 } 92 } 93 94 for (Node *node = table->firstChild(); node; node = node->nextSibling()) { 95 if (node->hasTagName(tbodyTag)) { 96 HTMLTableSectionElement* section = static_cast<HTMLTableSectionElement*>(node); 97 for (Node* row = section->firstChild(); row; row = row->nextSibling()) { 98 if (row == this) 99 return rIndex; 100 if (row->hasTagName(trTag)) 101 ++rIndex; 102 } 103 } 104 } 105 106 if (HTMLTableSectionElement* foot = static_cast<HTMLTableElement*>(table)->tFoot()) { 107 for (Node *row = foot->firstChild(); row; row = row->nextSibling()) { 108 if (row == this) 109 return rIndex; 110 if (row->hasTagName(trTag)) 111 ++rIndex; 112 } 113 } 114 115 // We get here for rows that are in <thead> or <tfoot> sections other than the main header and footer. 116 return -1; 117 } 118 119 int HTMLTableRowElement::sectionRowIndex() const 120 { 121 int rIndex = 0; 122 const Node *n = this; 123 do { 124 n = n->previousSibling(); 125 if (n && n->hasTagName(trTag)) 126 rIndex++; 127 } 128 while (n); 129 130 return rIndex; 131 } 132 133 PassRefPtr<HTMLElement> HTMLTableRowElement::insertCell(int index, ExceptionCode& ec) 134 { 135 RefPtr<HTMLCollection> children = cells(); 136 int numCells = children ? children->length() : 0; 137 if (index < -1 || index > numCells) { 138 ec = INDEX_SIZE_ERR; 139 return 0; 140 } 141 142 RefPtr<HTMLTableCellElement> c = new HTMLTableCellElement(tdTag, document()); 143 if (index < 0 || index >= numCells) 144 appendChild(c, ec); 145 else { 146 Node* n; 147 if (index < 1) 148 n = firstChild(); 149 else 150 n = children->item(index); 151 insertBefore(c, n, ec); 152 } 153 return c.release(); 154 } 155 156 void HTMLTableRowElement::deleteCell(int index, ExceptionCode& ec) 157 { 158 RefPtr<HTMLCollection> children = cells(); 159 int numCells = children ? children->length() : 0; 160 if (index == -1) 161 index = numCells-1; 162 if (index >= 0 && index < numCells) { 163 RefPtr<Node> cell = children->item(index); 164 HTMLElement::removeChild(cell.get(), ec); 165 } else 166 ec = INDEX_SIZE_ERR; 167 } 168 169 PassRefPtr<HTMLCollection> HTMLTableRowElement::cells() 170 { 171 return HTMLCollection::create(this, TRCells); 172 } 173 174 void HTMLTableRowElement::setCells(HTMLCollection *, ExceptionCode& ec) 175 { 176 ec = NO_MODIFICATION_ALLOWED_ERR; 177 } 178 179 String HTMLTableRowElement::align() const 180 { 181 return getAttribute(alignAttr); 182 } 183 184 void HTMLTableRowElement::setAlign(const String &value) 185 { 186 setAttribute(alignAttr, value); 187 } 188 189 String HTMLTableRowElement::bgColor() const 190 { 191 return getAttribute(bgcolorAttr); 192 } 193 194 void HTMLTableRowElement::setBgColor(const String &value) 195 { 196 setAttribute(bgcolorAttr, value); 197 } 198 199 String HTMLTableRowElement::ch() const 200 { 201 return getAttribute(charAttr); 202 } 203 204 void HTMLTableRowElement::setCh(const String &value) 205 { 206 setAttribute(charAttr, value); 207 } 208 209 String HTMLTableRowElement::chOff() const 210 { 211 return getAttribute(charoffAttr); 212 } 213 214 void HTMLTableRowElement::setChOff(const String &value) 215 { 216 setAttribute(charoffAttr, value); 217 } 218 219 String HTMLTableRowElement::vAlign() const 220 { 221 return getAttribute(valignAttr); 222 } 223 224 void HTMLTableRowElement::setVAlign(const String &value) 225 { 226 setAttribute(valignAttr, value); 227 } 228 229 } 230