1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef mozilla_dom_HTMLTableElement_h
7 #define mozilla_dom_HTMLTableElement_h
8 
9 #include "mozilla/Attributes.h"
10 #include "nsGenericHTMLElement.h"
11 #include "mozilla/dom/HTMLTableCaptionElement.h"
12 #include "mozilla/dom/HTMLTableSectionElement.h"
13 
14 namespace mozilla {
15 namespace dom {
16 
17 class TableRowsCollection;
18 
19 class HTMLTableElement final : public nsGenericHTMLElement {
20  public:
21   explicit HTMLTableElement(
22       already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
23 
NS_IMPL_FROMNODE_HTML_WITH_TAG(HTMLTableElement,table)24   NS_IMPL_FROMNODE_HTML_WITH_TAG(HTMLTableElement, table)
25 
26   // nsISupports
27   NS_DECL_ISUPPORTS_INHERITED
28 
29   HTMLTableCaptionElement* GetCaption() const {
30     return static_cast<HTMLTableCaptionElement*>(GetChild(nsGkAtoms::caption));
31   }
SetCaption(HTMLTableCaptionElement * aCaption,ErrorResult & aError)32   void SetCaption(HTMLTableCaptionElement* aCaption, ErrorResult& aError) {
33     DeleteCaption();
34     if (aCaption) {
35       nsCOMPtr<nsINode> firstChild = nsINode::GetFirstChild();
36       nsINode::InsertBefore(*aCaption, firstChild, aError);
37     }
38   }
39 
40   void DeleteTFoot();
41 
42   already_AddRefed<nsGenericHTMLElement> CreateCaption();
43 
44   void DeleteCaption();
45 
GetTHead()46   HTMLTableSectionElement* GetTHead() const {
47     return static_cast<HTMLTableSectionElement*>(GetChild(nsGkAtoms::thead));
48   }
SetTHead(HTMLTableSectionElement * aTHead,ErrorResult & aError)49   void SetTHead(HTMLTableSectionElement* aTHead, ErrorResult& aError) {
50     if (aTHead && !aTHead->IsHTMLElement(nsGkAtoms::thead)) {
51       aError.ThrowHierarchyRequestError("New value must be a thead element.");
52       return;
53     }
54 
55     DeleteTHead();
56     if (aTHead) {
57       nsCOMPtr<nsIContent> refNode = nullptr;
58       for (refNode = nsINode::GetFirstChild(); refNode;
59            refNode = refNode->GetNextSibling()) {
60         if (refNode->IsHTMLElement() &&
61             !refNode->IsHTMLElement(nsGkAtoms::caption) &&
62             !refNode->IsHTMLElement(nsGkAtoms::colgroup)) {
63           break;
64         }
65       }
66 
67       nsINode::InsertBefore(*aTHead, refNode, aError);
68     }
69   }
70   already_AddRefed<nsGenericHTMLElement> CreateTHead();
71 
72   void DeleteTHead();
73 
GetTFoot()74   HTMLTableSectionElement* GetTFoot() const {
75     return static_cast<HTMLTableSectionElement*>(GetChild(nsGkAtoms::tfoot));
76   }
SetTFoot(HTMLTableSectionElement * aTFoot,ErrorResult & aError)77   void SetTFoot(HTMLTableSectionElement* aTFoot, ErrorResult& aError) {
78     if (aTFoot && !aTFoot->IsHTMLElement(nsGkAtoms::tfoot)) {
79       aError.ThrowHierarchyRequestError("New value must be a tfoot element.");
80       return;
81     }
82 
83     DeleteTFoot();
84     if (aTFoot) {
85       nsINode::AppendChild(*aTFoot, aError);
86     }
87   }
88   already_AddRefed<nsGenericHTMLElement> CreateTFoot();
89 
90   nsIHTMLCollection* TBodies();
91 
92   already_AddRefed<nsGenericHTMLElement> CreateTBody();
93 
94   nsIHTMLCollection* Rows();
95 
96   already_AddRefed<nsGenericHTMLElement> InsertRow(int32_t aIndex,
97                                                    ErrorResult& aError);
98   void DeleteRow(int32_t aIndex, ErrorResult& aError);
99 
GetAlign(DOMString & aAlign)100   void GetAlign(DOMString& aAlign) { GetHTMLAttr(nsGkAtoms::align, aAlign); }
SetAlign(const nsAString & aAlign,ErrorResult & aError)101   void SetAlign(const nsAString& aAlign, ErrorResult& aError) {
102     SetHTMLAttr(nsGkAtoms::align, aAlign, aError);
103   }
GetBorder(DOMString & aBorder)104   void GetBorder(DOMString& aBorder) {
105     GetHTMLAttr(nsGkAtoms::border, aBorder);
106   }
SetBorder(const nsAString & aBorder,ErrorResult & aError)107   void SetBorder(const nsAString& aBorder, ErrorResult& aError) {
108     SetHTMLAttr(nsGkAtoms::border, aBorder, aError);
109   }
GetFrame(DOMString & aFrame)110   void GetFrame(DOMString& aFrame) { GetHTMLAttr(nsGkAtoms::frame, aFrame); }
SetFrame(const nsAString & aFrame,ErrorResult & aError)111   void SetFrame(const nsAString& aFrame, ErrorResult& aError) {
112     SetHTMLAttr(nsGkAtoms::frame, aFrame, aError);
113   }
GetRules(DOMString & aRules)114   void GetRules(DOMString& aRules) { GetHTMLAttr(nsGkAtoms::rules, aRules); }
SetRules(const nsAString & aRules,ErrorResult & aError)115   void SetRules(const nsAString& aRules, ErrorResult& aError) {
116     SetHTMLAttr(nsGkAtoms::rules, aRules, aError);
117   }
GetSummary(nsString & aSummary)118   void GetSummary(nsString& aSummary) {
119     GetHTMLAttr(nsGkAtoms::summary, aSummary);
120   }
GetSummary(DOMString & aSummary)121   void GetSummary(DOMString& aSummary) {
122     GetHTMLAttr(nsGkAtoms::summary, aSummary);
123   }
SetSummary(const nsAString & aSummary,ErrorResult & aError)124   void SetSummary(const nsAString& aSummary, ErrorResult& aError) {
125     SetHTMLAttr(nsGkAtoms::summary, aSummary, aError);
126   }
GetWidth(DOMString & aWidth)127   void GetWidth(DOMString& aWidth) { GetHTMLAttr(nsGkAtoms::width, aWidth); }
SetWidth(const nsAString & aWidth,ErrorResult & aError)128   void SetWidth(const nsAString& aWidth, ErrorResult& aError) {
129     SetHTMLAttr(nsGkAtoms::width, aWidth, aError);
130   }
GetBgColor(DOMString & aBgColor)131   void GetBgColor(DOMString& aBgColor) {
132     GetHTMLAttr(nsGkAtoms::bgcolor, aBgColor);
133   }
SetBgColor(const nsAString & aBgColor,ErrorResult & aError)134   void SetBgColor(const nsAString& aBgColor, ErrorResult& aError) {
135     SetHTMLAttr(nsGkAtoms::bgcolor, aBgColor, aError);
136   }
GetCellPadding(DOMString & aCellPadding)137   void GetCellPadding(DOMString& aCellPadding) {
138     GetHTMLAttr(nsGkAtoms::cellpadding, aCellPadding);
139   }
SetCellPadding(const nsAString & aCellPadding,ErrorResult & aError)140   void SetCellPadding(const nsAString& aCellPadding, ErrorResult& aError) {
141     SetHTMLAttr(nsGkAtoms::cellpadding, aCellPadding, aError);
142   }
GetCellSpacing(DOMString & aCellSpacing)143   void GetCellSpacing(DOMString& aCellSpacing) {
144     GetHTMLAttr(nsGkAtoms::cellspacing, aCellSpacing);
145   }
SetCellSpacing(const nsAString & aCellSpacing,ErrorResult & aError)146   void SetCellSpacing(const nsAString& aCellSpacing, ErrorResult& aError) {
147     SetHTMLAttr(nsGkAtoms::cellspacing, aCellSpacing, aError);
148   }
149 
150   virtual bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
151                               const nsAString& aValue,
152                               nsIPrincipal* aMaybeScriptedPrincipal,
153                               nsAttrValue& aResult) override;
154   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction()
155       const override;
156   NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
157 
158   virtual nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
159 
160   virtual nsresult BindToTree(BindContext&, nsINode& aParent) override;
161   virtual void UnbindFromTree(bool aNullParent = true) override;
162   /**
163    * Called when an attribute is about to be changed
164    */
165   virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsAtom* aName,
166                                  const nsAttrValueOrString* aValue,
167                                  bool aNotify) override;
168   /**
169    * Called when an attribute has just been changed
170    */
171   virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
172                                 const nsAttrValue* aValue,
173                                 const nsAttrValue* aOldValue,
174                                 nsIPrincipal* aSubjectPrincipal,
175                                 bool aNotify) override;
176 
177   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLTableElement,
178                                            nsGenericHTMLElement)
179   nsMappedAttributes* GetAttributesMappedForCell();
180 
181  protected:
182   virtual ~HTMLTableElement();
183 
184   virtual JSObject* WrapNode(JSContext* aCx,
185                              JS::Handle<JSObject*> aGivenProto) override;
186 
GetChild(nsAtom * aTag)187   nsIContent* GetChild(nsAtom* aTag) const {
188     for (nsIContent* cur = nsINode::GetFirstChild(); cur;
189          cur = cur->GetNextSibling()) {
190       if (cur->IsHTMLElement(aTag)) {
191         return cur;
192       }
193     }
194     return nullptr;
195   }
196 
197   RefPtr<nsContentList> mTBodies;
198   RefPtr<TableRowsCollection> mRows;
199   nsMappedAttributes* mTableInheritedAttributes;
200   void BuildInheritedAttributes();
201   void ReleaseInheritedAttributes();
202 
203  private:
204   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
205                                     MappedDeclarations&);
206 };
207 
208 }  // namespace dom
209 }  // namespace mozilla
210 
211 #endif /* mozilla_dom_HTMLTableElement_h */
212