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_HTMLOptionsCollection_h
7 #define mozilla_dom_HTMLOptionsCollection_h
8 
9 #include "mozilla/Attributes.h"
10 #include "nsIHTMLCollection.h"
11 #include "nsWrapperCache.h"
12 
13 #include "mozilla/dom/HTMLOptionElement.h"
14 #include "mozilla/ErrorResult.h"
15 #include "nsCOMPtr.h"
16 #include "nsError.h"
17 #include "nsGenericHTMLElement.h"
18 #include "nsTArray.h"
19 
20 namespace mozilla {
21 namespace dom {
22 
23 class DocGroup;
24 class HTMLElementOrLong;
25 class HTMLOptionElementOrHTMLOptGroupElement;
26 class HTMLSelectElement;
27 
28 /**
29  * The collection of options in the select (what you get back when you do
30  * select.options in DOM)
31  */
32 class HTMLOptionsCollection final : public nsIHTMLCollection,
33                                     public nsWrapperCache {
34   typedef HTMLOptionElementOrHTMLOptGroupElement HTMLOptionOrOptGroupElement;
35 
36  public:
37   explicit HTMLOptionsCollection(HTMLSelectElement* aSelect);
38 
39   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
40 
41   // nsWrapperCache
42   using nsWrapperCache::GetWrapper;
43   using nsWrapperCache::GetWrapperPreserveColor;
44   using nsWrapperCache::PreserveWrapper;
45   virtual JSObject* WrapObject(JSContext* aCx,
46                                JS::Handle<JSObject*> aGivenProto) override;
47 
48  protected:
49   virtual ~HTMLOptionsCollection() = default;
50 
GetWrapperPreserveColorInternal()51   virtual JSObject* GetWrapperPreserveColorInternal() override {
52     return nsWrapperCache::GetWrapperPreserveColor();
53   }
PreserveWrapperInternal(nsISupports * aScriptObjectHolder)54   virtual void PreserveWrapperInternal(
55       nsISupports* aScriptObjectHolder) override {
56     nsWrapperCache::PreserveWrapper(aScriptObjectHolder);
57   }
58 
59  public:
60   virtual uint32_t Length() override;
61   virtual Element* GetElementAt(uint32_t aIndex) override;
62   virtual nsINode* GetParentObject() override;
63   DocGroup* GetDocGroup() const;
64 
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(HTMLOptionsCollection,nsIHTMLCollection)65   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(HTMLOptionsCollection,
66                                                          nsIHTMLCollection)
67 
68   // Helpers for HTMLSelectElement
69   /**
70    * Insert an option
71    * @param aOption the option to insert
72    * @param aIndex the index to insert at
73    */
74   void InsertOptionAt(mozilla::dom::HTMLOptionElement* aOption,
75                       uint32_t aIndex) {
76     mElements.InsertElementAt(aIndex, aOption);
77   }
78 
79   /**
80    * Remove an option
81    * @param aIndex the index of the option to remove
82    */
RemoveOptionAt(uint32_t aIndex)83   void RemoveOptionAt(uint32_t aIndex) { mElements.RemoveElementAt(aIndex); }
84 
85   /**
86    * Get the option at the index
87    * @param aIndex the index
88    * @param aReturn the option returned [OUT]
89    */
ItemAsOption(uint32_t aIndex)90   mozilla::dom::HTMLOptionElement* ItemAsOption(uint32_t aIndex) {
91     return mElements.SafeElementAt(aIndex, nullptr);
92   }
93 
94   /**
95    * Clears out all options
96    */
Clear()97   void Clear() { mElements.Clear(); }
98 
99   /**
100    * Append an option to end of array
101    */
AppendOption(mozilla::dom::HTMLOptionElement * aOption)102   void AppendOption(mozilla::dom::HTMLOptionElement* aOption) {
103     mElements.AppendElement(aOption);
104   }
105 
106   /**
107    * Finds the index of a given option element.
108    * If the option isn't part of the collection, return NS_ERROR_FAILURE
109    * without setting aIndex.
110    *
111    * @param aOption the option to get the index of
112    * @param aStartIndex the index to start looking at
113    * @param aForward TRUE to look forward, FALSE to look backward
114    * @return the option index
115    */
116   nsresult GetOptionIndex(Element* aOption, int32_t aStartIndex, bool aForward,
117                           int32_t* aIndex);
118 
GetNamedItem(const nsAString & aName)119   HTMLOptionElement* GetNamedItem(const nsAString& aName) {
120     bool dummy;
121     return NamedGetter(aName, dummy);
122   }
123   HTMLOptionElement* NamedGetter(const nsAString& aName, bool& aFound);
GetFirstNamedElement(const nsAString & aName,bool & aFound)124   virtual Element* GetFirstNamedElement(const nsAString& aName,
125                                         bool& aFound) override {
126     return NamedGetter(aName, aFound);
127   }
128   void Add(const HTMLOptionOrOptGroupElement& aElement,
129            const Nullable<HTMLElementOrLong>& aBefore, ErrorResult& aError);
130   void Remove(int32_t aIndex, ErrorResult& aError);
131   int32_t GetSelectedIndex(ErrorResult& aError);
132   void SetSelectedIndex(int32_t aSelectedIndex, ErrorResult& aError);
133   void IndexedSetter(uint32_t aIndex, HTMLOptionElement* aOption,
134                      ErrorResult& aError);
135   virtual void GetSupportedNames(nsTArray<nsString>& aNames) override;
136   void SetLength(uint32_t aLength, ErrorResult& aError);
137 
138  private:
139   /** The list of options (holds strong references).  This is infallible, so
140    * various members such as InsertOptionAt are also infallible. */
141   nsTArray<RefPtr<mozilla::dom::HTMLOptionElement> > mElements;
142   /** The select element that contains this array */
143   RefPtr<HTMLSelectElement> mSelect;
144 };
145 
146 }  // namespace dom
147 }  // namespace mozilla
148 
149 #endif  // mozilla_dom_HTMLOptionsCollection_h
150