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 #define TABLE_ATTRS_DIRTY ((nsMappedAttributes*)0x1)
18 
19 class TableRowsCollection;
20 
21 class HTMLTableElement final : public nsGenericHTMLElement
22 {
23 public:
24   explicit HTMLTableElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
25 
NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLTableElement,table)26   NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLTableElement, table)
27 
28   // nsISupports
29   NS_DECL_ISUPPORTS_INHERITED
30 
31   HTMLTableCaptionElement* GetCaption() const
32   {
33     return static_cast<HTMLTableCaptionElement*>(GetChild(nsGkAtoms::caption));
34   }
SetCaption(HTMLTableCaptionElement * aCaption,ErrorResult & aError)35   void SetCaption(HTMLTableCaptionElement* aCaption, ErrorResult& aError)
36   {
37     DeleteCaption();
38     if (aCaption) {
39       nsINode::AppendChild(*aCaption, aError);
40     }
41   }
42 
43   void DeleteTFoot();
44 
45   already_AddRefed<nsGenericHTMLElement> CreateCaption();
46 
47   void DeleteCaption();
48 
GetTHead()49   HTMLTableSectionElement* GetTHead() const
50   {
51     return static_cast<HTMLTableSectionElement*>(GetChild(nsGkAtoms::thead));
52   }
SetTHead(HTMLTableSectionElement * aTHead,ErrorResult & aError)53   void SetTHead(HTMLTableSectionElement* aTHead, ErrorResult& aError)
54   {
55     if (aTHead && !aTHead->IsHTMLElement(nsGkAtoms::thead)) {
56       aError.Throw(NS_ERROR_DOM_HIERARCHY_REQUEST_ERR);
57       return;
58     }
59 
60     DeleteTHead();
61     if (aTHead) {
62       nsCOMPtr<nsINode> refNode = nsINode::GetFirstChild();
63       nsINode::InsertBefore(*aTHead, refNode, aError);
64     }
65   }
66   already_AddRefed<nsGenericHTMLElement> CreateTHead();
67 
68   void DeleteTHead();
69 
GetTFoot()70   HTMLTableSectionElement* GetTFoot() const
71   {
72     return static_cast<HTMLTableSectionElement*>(GetChild(nsGkAtoms::tfoot));
73   }
SetTFoot(HTMLTableSectionElement * aTFoot,ErrorResult & aError)74   void SetTFoot(HTMLTableSectionElement* aTFoot, ErrorResult& aError)
75   {
76     if (aTFoot && !aTFoot->IsHTMLElement(nsGkAtoms::tfoot)) {
77       aError.Throw(NS_ERROR_DOM_HIERARCHY_REQUEST_ERR);
78       return;
79     }
80 
81     DeleteTFoot();
82     if (aTFoot) {
83       nsINode::AppendChild(*aTFoot, aError);
84     }
85   }
86   already_AddRefed<nsGenericHTMLElement> CreateTFoot();
87 
88   nsIHTMLCollection* TBodies();
89 
90   already_AddRefed<nsGenericHTMLElement> CreateTBody();
91 
92   nsIHTMLCollection* Rows();
93 
94   already_AddRefed<nsGenericHTMLElement> InsertRow(int32_t aIndex,
95                                                    ErrorResult& aError);
96   void DeleteRow(int32_t aIndex, ErrorResult& aError);
97 
GetAlign(DOMString & aAlign)98   void GetAlign(DOMString& aAlign)
99   {
100     GetHTMLAttr(nsGkAtoms::align, aAlign);
101   }
SetAlign(const nsAString & aAlign,ErrorResult & aError)102   void SetAlign(const nsAString& aAlign, ErrorResult& aError)
103   {
104     SetHTMLAttr(nsGkAtoms::align, aAlign, aError);
105   }
GetBorder(DOMString & aBorder)106   void GetBorder(DOMString& aBorder)
107   {
108     GetHTMLAttr(nsGkAtoms::border, aBorder);
109   }
SetBorder(const nsAString & aBorder,ErrorResult & aError)110   void SetBorder(const nsAString& aBorder, ErrorResult& aError)
111   {
112     SetHTMLAttr(nsGkAtoms::border, aBorder, aError);
113   }
GetFrame(DOMString & aFrame)114   void GetFrame(DOMString& aFrame)
115   {
116     GetHTMLAttr(nsGkAtoms::frame, aFrame);
117   }
SetFrame(const nsAString & aFrame,ErrorResult & aError)118   void SetFrame(const nsAString& aFrame, ErrorResult& aError)
119   {
120     SetHTMLAttr(nsGkAtoms::frame, aFrame, aError);
121   }
GetRules(DOMString & aRules)122   void GetRules(DOMString& aRules)
123   {
124     GetHTMLAttr(nsGkAtoms::rules, aRules);
125   }
SetRules(const nsAString & aRules,ErrorResult & aError)126   void SetRules(const nsAString& aRules, ErrorResult& aError)
127   {
128     SetHTMLAttr(nsGkAtoms::rules, aRules, aError);
129   }
GetSummary(nsString & aSummary)130   void GetSummary(nsString& aSummary)
131   {
132     GetHTMLAttr(nsGkAtoms::summary, aSummary);
133   }
GetSummary(DOMString & aSummary)134   void GetSummary(DOMString& aSummary)
135   {
136     GetHTMLAttr(nsGkAtoms::summary, aSummary);
137   }
SetSummary(const nsAString & aSummary,ErrorResult & aError)138   void SetSummary(const nsAString& aSummary, ErrorResult& aError)
139   {
140     SetHTMLAttr(nsGkAtoms::summary, aSummary, aError);
141   }
GetWidth(DOMString & aWidth)142   void GetWidth(DOMString& aWidth)
143   {
144     GetHTMLAttr(nsGkAtoms::width, aWidth);
145   }
SetWidth(const nsAString & aWidth,ErrorResult & aError)146   void SetWidth(const nsAString& aWidth, ErrorResult& aError)
147   {
148     SetHTMLAttr(nsGkAtoms::width, aWidth, aError);
149   }
GetBgColor(DOMString & aBgColor)150   void GetBgColor(DOMString& aBgColor)
151   {
152     GetHTMLAttr(nsGkAtoms::bgcolor, aBgColor);
153   }
SetBgColor(const nsAString & aBgColor,ErrorResult & aError)154   void SetBgColor(const nsAString& aBgColor, ErrorResult& aError)
155   {
156     SetHTMLAttr(nsGkAtoms::bgcolor, aBgColor, aError);
157   }
GetCellPadding(DOMString & aCellPadding)158   void GetCellPadding(DOMString& aCellPadding)
159   {
160     GetHTMLAttr(nsGkAtoms::cellpadding, aCellPadding);
161   }
SetCellPadding(const nsAString & aCellPadding,ErrorResult & aError)162   void SetCellPadding(const nsAString& aCellPadding, ErrorResult& aError)
163   {
164     SetHTMLAttr(nsGkAtoms::cellpadding, aCellPadding, aError);
165   }
GetCellSpacing(DOMString & aCellSpacing)166   void GetCellSpacing(DOMString& aCellSpacing)
167   {
168     GetHTMLAttr(nsGkAtoms::cellspacing, aCellSpacing);
169   }
SetCellSpacing(const nsAString & aCellSpacing,ErrorResult & aError)170   void SetCellSpacing(const nsAString& aCellSpacing, ErrorResult& aError)
171   {
172     SetHTMLAttr(nsGkAtoms::cellspacing, aCellSpacing, aError);
173   }
174 
175   virtual bool ParseAttribute(int32_t aNamespaceID,
176                                 nsIAtom* aAttribute,
177                                 const nsAString& aValue,
178                                 nsAttrValue& aResult) override;
179   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
180   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
181 
182   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
183 
184   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
185                               nsIContent* aBindingParent,
186                               bool aCompileEventHandlers) override;
187   virtual void UnbindFromTree(bool aDeep = true,
188                               bool aNullParent = true) override;
189   /**
190    * Called when an attribute is about to be changed
191    */
192   virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
193                                  nsAttrValueOrString* aValue,
194                                  bool aNotify) override;
195   /**
196    * Called when an attribute has just been changed
197    */
198   virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
199                                 const nsAttrValue* aValue, bool aNotify) override;
200 
201   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLTableElement,
202                                            nsGenericHTMLElement)
203   nsMappedAttributes* GetAttributesMappedForCell();
204 
205 protected:
206   virtual ~HTMLTableElement();
207 
208   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
209 
GetChild(nsIAtom * aTag)210   nsIContent* GetChild(nsIAtom *aTag) const
211   {
212     for (nsIContent* cur = nsINode::GetFirstChild(); cur;
213          cur = cur->GetNextSibling()) {
214       if (cur->IsHTMLElement(aTag)) {
215         return cur;
216       }
217     }
218     return nullptr;
219   }
220 
221   RefPtr<nsContentList> mTBodies;
222   RefPtr<TableRowsCollection> mRows;
223   // Sentinel value of TABLE_ATTRS_DIRTY indicates that this is dirty and needs
224   // to be recalculated.
225   nsMappedAttributes *mTableInheritedAttributes;
226   void BuildInheritedAttributes();
227   void ReleaseInheritedAttributes();
228 
229 private:
230   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
231                                     nsRuleData* aData);
232 };
233 
234 } // namespace dom
235 } // namespace mozilla
236 
237 #endif /* mozilla_dom_HTMLTableElement_h */
238