📄 htmltableelement.cpp
字号:
/* * Copyright (C) 1997 Martin Jones (mjones@kde.org) * (C) 1997 Torben Weis (weis@kde.org) * (C) 1998 Waldo Bastian (bastian@kde.org) * (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * Copyright (C) 2003, 2004, 2005, 2006, 2008 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */#include "config.h"#include "HTMLTableElement.h"#include "CSSPropertyNames.h"#include "CSSStyleSheet.h"#include "CSSValueKeywords.h"#include "ExceptionCode.h"#include "HTMLNames.h"#include "HTMLTableCaptionElement.h"#include "HTMLTableRowsCollection.h"#include "HTMLTableRowElement.h"#include "HTMLTableSectionElement.h"#include "RenderTable.h"#include "Text.h"namespace WebCore {using namespace HTMLNames;HTMLTableElement::HTMLTableElement(const QualifiedName& tagName, Document* doc) : HTMLElement(tagName, doc) , m_borderAttr(false) , m_borderColorAttr(false) , m_frameAttr(false) , m_rulesAttr(UnsetRules) , m_padding(1){ ASSERT(hasTagName(tableTag));}bool HTMLTableElement::checkDTD(const Node* newChild){ if (newChild->isTextNode()) return static_cast<const Text*>(newChild)->containsOnlyWhitespace(); return newChild->hasTagName(captionTag) || newChild->hasTagName(colTag) || newChild->hasTagName(colgroupTag) || newChild->hasTagName(theadTag) || newChild->hasTagName(tfootTag) || newChild->hasTagName(tbodyTag) || newChild->hasTagName(formTag) || newChild->hasTagName(scriptTag);}HTMLTableCaptionElement* HTMLTableElement::caption() const{ for (Node* child = firstChild(); child; child = child->nextSibling()) { if (child->hasTagName(captionTag)) return static_cast<HTMLTableCaptionElement*>(child); } return 0;}void HTMLTableElement::setCaption(PassRefPtr<HTMLTableCaptionElement> newCaption, ExceptionCode& ec){ deleteCaption(); insertBefore(newCaption, firstChild(), ec);}HTMLTableSectionElement* HTMLTableElement::tHead() const{ for (Node* child = firstChild(); child; child = child->nextSibling()) { if (child->hasTagName(theadTag)) return static_cast<HTMLTableSectionElement*>(child); } return 0;}void HTMLTableElement::setTHead(PassRefPtr<HTMLTableSectionElement> newHead, ExceptionCode& ec){ deleteTHead(); Node* child; for (child = firstChild(); child; child = child->nextSibling()) if (child->isElementNode() && !child->hasTagName(captionTag) && !child->hasTagName(colgroupTag)) break; insertBefore(newHead, child, ec);}HTMLTableSectionElement* HTMLTableElement::tFoot() const{ for (Node* child = firstChild(); child; child = child->nextSibling()) { if (child->hasTagName(tfootTag)) return static_cast<HTMLTableSectionElement*>(child); } return 0;}void HTMLTableElement::setTFoot(PassRefPtr<HTMLTableSectionElement> newFoot, ExceptionCode& ec){ deleteTFoot(); Node* child; for (child = firstChild(); child; child = child->nextSibling()) if (child->isElementNode() && !child->hasTagName(captionTag) && !child->hasTagName(colgroupTag) && !child->hasTagName(theadTag)) break; insertBefore(newFoot, child, ec);}PassRefPtr<HTMLElement> HTMLTableElement::createTHead(){ if (HTMLTableSectionElement* existingHead = tHead()) return existingHead; RefPtr<HTMLTableSectionElement> head = new HTMLTableSectionElement(theadTag, document()); ExceptionCode ec; setTHead(head, ec); return head.release();}void HTMLTableElement::deleteTHead(){ ExceptionCode ec; removeChild(tHead(), ec);}PassRefPtr<HTMLElement> HTMLTableElement::createTFoot(){ if (HTMLTableSectionElement* existingFoot = tFoot()) return existingFoot; RefPtr<HTMLTableSectionElement> foot = new HTMLTableSectionElement(tfootTag, document()); ExceptionCode ec; setTFoot(foot, ec); return foot.release();}void HTMLTableElement::deleteTFoot(){ ExceptionCode ec; removeChild(tFoot(), ec);}PassRefPtr<HTMLElement> HTMLTableElement::createCaption(){ if (HTMLTableCaptionElement* existingCaption = caption()) return existingCaption; RefPtr<HTMLTableCaptionElement> caption = new HTMLTableCaptionElement(captionTag, document()); ExceptionCode ec; setCaption(caption, ec); return caption.release();}void HTMLTableElement::deleteCaption(){ ExceptionCode ec; removeChild(caption(), ec);}HTMLTableSectionElement* HTMLTableElement::lastBody() const{ for (Node* child = lastChild(); child; child = child->previousSibling()) { if (child->hasTagName(tbodyTag)) return static_cast<HTMLTableSectionElement*>(child); } return 0;}PassRefPtr<HTMLElement> HTMLTableElement::insertRow(int index, ExceptionCode& ec){ if (index < -1) { ec = INDEX_SIZE_ERR; return 0; } HTMLTableRowElement* lastRow = 0; HTMLTableRowElement* row = 0; if (index == -1) lastRow = HTMLTableRowsCollection::lastRow(this); else { for (int i = 0; i <= index; ++i) { row = HTMLTableRowsCollection::rowAfter(this, lastRow); if (!row) { if (i != index) { ec = INDEX_SIZE_ERR; return 0; } break; } lastRow = row; } } Node* parent; if (lastRow) parent = row ? row->parent() : lastRow->parent(); else { parent = lastBody(); if (!parent) { RefPtr<HTMLTableSectionElement> newBody = new HTMLTableSectionElement(tbodyTag, document()); RefPtr<HTMLTableRowElement> newRow = new HTMLTableRowElement(trTag, document()); newBody->appendChild(newRow, ec); appendChild(newBody.release(), ec); return newRow.release(); } } RefPtr<HTMLTableRowElement> newRow = new HTMLTableRowElement(trTag, document()); parent->insertBefore(newRow, row, ec); return newRow.release();}void HTMLTableElement::deleteRow(int index, ExceptionCode& ec){ HTMLTableRowElement* row = 0; if (index == -1) row = HTMLTableRowsCollection::lastRow(this); else { for (int i = 0; i <= index; ++i) { row = HTMLTableRowsCollection::rowAfter(this, row); if (!row) break; } } if (!row) { ec = INDEX_SIZE_ERR; return; } row->remove(ec);}ContainerNode* HTMLTableElement::addChild(PassRefPtr<Node> child){ if (child->hasTagName(formTag)) { // First add the child. HTMLElement::addChild(child); // Now simply return ourselves as the container to insert into. // This has the effect of demoting the form to a leaf and moving it safely out of the way. return this; } return HTMLElement::addChild(child.get());}bool HTMLTableElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const{ if (attrName == backgroundAttr) { result = (MappedAttributeEntry)(eLastEntry + document()->docID()); return false; } if (attrName == widthAttr || attrName == heightAttr || attrName == bgcolorAttr || attrName == cellspacingAttr || attrName == vspaceAttr || attrName == hspaceAttr || attrName == valignAttr) { result = eUniversal; return false; } if (attrName == bordercolorAttr || attrName == frameAttr || attrName == rulesAttr) { result = eUniversal; return true; } if (attrName == borderAttr) { result = eTable; return true; } if (attrName == alignAttr) { result = eTable; return false; } return HTMLElement::mapToEntry(attrName, result);}static inline bool isTableCellAncestor(Node* n){ return n->hasTagName(theadTag) || n->hasTagName(tbodyTag) || n->hasTagName(tfootTag) || n->hasTagName(trTag) || n->hasTagName(thTag);}static bool setTableCellsChanged(Node* n){ ASSERT(n); bool cellChanged = false; if (n->hasTagName(tdTag)) cellChanged = true; else if (isTableCellAncestor(n)) { for (Node* child = n->firstChild(); child; child = child->nextSibling()) cellChanged |= setTableCellsChanged(child); } if (cellChanged) n->setChanged(); return cellChanged;}void HTMLTableElement::parseMappedAttribute(MappedAttribute* attr){ CellBorders bordersBefore = cellBorders(); unsigned short oldPadding = m_padding; if (attr->name() == widthAttr) addCSSLength(attr, CSSPropertyWidth, attr->value()); else if (attr->name() == heightAttr) addCSSLength(attr, CSSPropertyHeight, attr->value()); else if (attr->name() == borderAttr) { m_borderAttr = true; if (attr->decl()) { RefPtr<CSSValue> val = attr->decl()->getPropertyCSSValue(CSSPropertyBorderLeftWidth); if (val && val->isPrimitiveValue()) { CSSPrimitiveValue* primVal = static_cast<CSSPrimitiveValue*>(val.get()); m_borderAttr = primVal->getDoubleValue(CSSPrimitiveValue::CSS_NUMBER); } } else if (!attr->isNull()) { int border = 0; if (attr->isEmpty()) border = 1; else border = attr->value().toInt(); m_borderAttr = border; addCSSLength(attr, CSSPropertyBorderWidth, String::number(border)); } } else if (attr->name() == bgcolorAttr) addCSSColor(attr, CSSPropertyBackgroundColor, attr->value()); else if (attr->name() == bordercolorAttr) { m_borderColorAttr = attr->decl(); if (!attr->decl() && !attr->isEmpty()) { addCSSColor(attr, CSSPropertyBorderColor, attr->value()); m_borderColorAttr = true; } } else if (attr->name() == backgroundAttr) { String url = parseURL(attr->value()); if (!url.isEmpty()) addCSSImageProperty(attr, CSSPropertyBackgroundImage, document()->completeURL(url).string()); } else if (attr->name() == frameAttr) { // Cache the value of "frame" so that the table can examine it later. m_frameAttr = false; // Whether or not to hide the top/right/bottom/left borders. const int cTop = 0; const int cRight = 1; const int cBottom = 2; const int cLeft = 3; bool borders[4] = { false, false, false, false }; // void, above, below, hsides, vsides, lhs, rhs, box, border if (equalIgnoringCase(attr->value(), "void")) m_frameAttr = true; else if (equalIgnoringCase(attr->value(), "above")) { m_frameAttr = true; borders[cTop] = true; } else if (equalIgnoringCase(attr->value(), "below")) { m_frameAttr = true; borders[cBottom] = true; } else if (equalIgnoringCase(attr->value(), "hsides")) { m_frameAttr = true; borders[cTop] = borders[cBottom] = true; } else if (equalIgnoringCase(attr->value(), "vsides")) { m_frameAttr = true;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -