nsIFormControl.h (9456B)
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 nsIFormControl_h___ 7 #define nsIFormControl_h___ 8 9 #include "mozilla/EventForwards.h" 10 #include "mozilla/StaticPrefs_dom.h" 11 #include "nsISupports.h" 12 13 class nsINode; 14 namespace mozilla { 15 class PresState; 16 namespace dom { 17 class Element; 18 class EventTarget; 19 class FormData; 20 class HTMLFieldSetElement; 21 class HTMLFormElement; 22 } // namespace dom 23 } // namespace mozilla 24 25 // Elements with different types, the value is used as a mask. 26 // When changing the order, adding or removing elements, be sure to update 27 // the static_assert checks accordingly. 28 constexpr uint8_t kFormControlButtonElementMask = 0x40; // 0b01000000 29 constexpr uint8_t kFormControlInputElementMask = 0x80; // 0b10000000 30 31 enum class FormControlType : uint8_t { 32 Fieldset = 1, 33 Output, 34 Select, 35 Textarea, 36 Object, 37 FormAssociatedCustomElement, 38 39 LastWithoutSubtypes = FormAssociatedCustomElement, 40 41 ButtonButton = kFormControlButtonElementMask + 1, 42 ButtonReset, 43 ButtonSubmit, 44 LastButtonElement = ButtonSubmit, 45 46 InputButton = kFormControlInputElementMask + 1, 47 InputCheckbox, 48 InputColor, 49 InputDate, 50 InputEmail, 51 InputFile, 52 InputHidden, 53 InputReset, 54 InputImage, 55 InputMonth, 56 InputNumber, 57 InputPassword, 58 InputRadio, 59 InputSearch, 60 InputSubmit, 61 InputTel, 62 InputText, 63 InputTime, 64 InputUrl, 65 InputRange, 66 InputWeek, 67 InputDatetimeLocal, 68 LastInputElement = InputDatetimeLocal, 69 }; 70 71 static_assert(uint8_t(FormControlType::LastWithoutSubtypes) < 72 kFormControlButtonElementMask, 73 "Too many FormControlsTypes without sub-types"); 74 static_assert(uint8_t(FormControlType::LastButtonElement) < 75 kFormControlInputElementMask, 76 "Too many ButtonElementTypes"); 77 static_assert(uint32_t(FormControlType::LastInputElement) < (1 << 8), 78 "Too many form control types"); 79 80 #define NS_IFORMCONTROL_IID \ 81 {0x4b89980c, 0x4dcd, 0x428f, {0xb7, 0xad, 0x43, 0x5b, 0x93, 0x29, 0x79, 0xec}} 82 83 /** 84 * Interface which all form controls (e.g. buttons, checkboxes, text, 85 * radio buttons, select, etc) implement in addition to their dom specific 86 * interface. 87 */ 88 class nsIFormControl : public nsISupports { 89 public: 90 nsIFormControl(FormControlType aType) : mType(aType) {} 91 92 NS_INLINE_DECL_STATIC_IID(NS_IFORMCONTROL_IID) 93 94 static nsIFormControl* FromEventTarget(mozilla::dom::EventTarget* aTarget); 95 static nsIFormControl* FromEventTargetOrNull( 96 mozilla::dom::EventTarget* aTarget); 97 static const nsIFormControl* FromEventTarget( 98 const mozilla::dom::EventTarget* aTarget); 99 static const nsIFormControl* FromEventTargetOrNull( 100 const mozilla::dom::EventTarget* aTarget); 101 102 static nsIFormControl* FromNode(nsINode* aNode); 103 static nsIFormControl* FromNodeOrNull(nsINode* aNode); 104 static const nsIFormControl* FromNode(const nsINode* aNode); 105 static const nsIFormControl* FromNodeOrNull(const nsINode* aNode); 106 107 /** 108 * Get the fieldset for this form control. 109 * @return the fieldset 110 */ 111 virtual mozilla::dom::HTMLFieldSetElement* GetFieldSet() = 0; 112 113 /** 114 * Get the form for this form control. 115 * @return the form 116 */ 117 virtual mozilla::dom::HTMLFormElement* GetForm() const = 0; 118 119 /** 120 * Set the form for this form control. 121 * @param aForm the form. This must not be null. 122 * 123 * @note that when setting the form the control is not added to the 124 * form. It adds itself when it gets bound to the tree thereafter, 125 * so that it can be properly sorted with the other controls in the 126 * form. 127 */ 128 virtual void SetForm(mozilla::dom::HTMLFormElement* aForm) = 0; 129 130 /** 131 * Tell the control to forget about its form. 132 * 133 * @param aRemoveFromForm set false if you do not want this element removed 134 * from the form. (Used by nsFormControlList::Clear()) 135 * @param aUnbindOrDelete set true if the element is being deleted or unbound 136 * from tree. 137 */ 138 virtual void ClearForm(bool aRemoveFromForm, bool aUnbindOrDelete) = 0; 139 140 /** 141 * Get the type of this control as an int (see NS_FORM_* above) 142 * @return the type of this control 143 */ 144 FormControlType ControlType() const { return mType; } 145 146 /** 147 * Reset this form control (as it should be when the user clicks the Reset 148 * button) 149 */ 150 NS_IMETHOD Reset() = 0; 151 152 /** 153 * Tells the form control to submit its names and values to the form data 154 * object 155 * 156 * @param aFormData the form data to notify of names/values/files to submit 157 */ 158 NS_IMETHOD 159 SubmitNamesValues(mozilla::dom::FormData* aFormData) = 0; 160 161 /** 162 * Returns whether this is a control which submits the form when activated by 163 * the user. 164 * @return whether this is a submit control. 165 */ 166 inline bool IsSubmitControl() const; 167 168 /** 169 * Returns whether this is a text control. 170 * @param aExcludePassword to have NS_FORM_INPUT_PASSWORD returning false. 171 * @return whether this is a text control. 172 */ 173 inline bool IsTextControl(bool aExcludePassword) const; 174 175 /** 176 * Returns whether this is a single line text control. 177 * @param aExcludePassword to have NS_FORM_INPUT_PASSWORD returning false. 178 * @return whether this is a single line text control. 179 */ 180 inline bool IsSingleLineTextControl(bool aExcludePassword) const; 181 182 /** 183 * Returns whether this is a submittable form control. 184 * @return whether this is a submittable form control. 185 */ 186 inline bool IsSubmittableControl() const; 187 188 /** 189 * https://html.spec.whatwg.org/multipage/forms.html#concept-button 190 */ 191 inline bool IsConceptButton() const; 192 193 /** 194 * Returns whether this is an ordinal button or a concept button that has no 195 * form associated. 196 */ 197 inline bool IsButtonControl() const; 198 199 /** 200 * Returns whether this form control can have draggable children. 201 * @return whether this form control can have draggable children. 202 */ 203 inline bool AllowDraggableChildren() const; 204 205 // Returns a number for this form control that is unique within its 206 // owner document. This is used by nsContentUtils::GenerateStateKey 207 // to identify form controls that are inserted into the document by 208 // the parser. -1 is returned for form controls with no state or 209 // which were inserted into the document by some other means than 210 // the parser from the network. 211 virtual int32_t GetParserInsertedControlNumberForStateKey() const { 212 return -1; 213 }; 214 215 protected: 216 /** 217 * Returns whether mType corresponds to a single line text control type. 218 * @param aExcludePassword to have NS_FORM_INPUT_PASSWORD ignored. 219 * @param aType the type to be tested. 220 * @return whether mType corresponds to a single line text control type. 221 */ 222 inline static bool IsSingleLineTextControl(bool aExcludePassword, 223 FormControlType); 224 225 inline static bool IsButtonElement(FormControlType aType) { 226 return uint8_t(aType) & kFormControlButtonElementMask; 227 } 228 229 inline static bool IsInputElement(FormControlType aType) { 230 return uint8_t(aType) & kFormControlInputElementMask; 231 } 232 233 FormControlType mType; 234 }; 235 236 bool nsIFormControl::IsSubmitControl() const { 237 FormControlType type = ControlType(); 238 return type == FormControlType::InputSubmit || 239 type == FormControlType::InputImage || 240 type == FormControlType::ButtonSubmit; 241 } 242 243 bool nsIFormControl::IsTextControl(bool aExcludePassword) const { 244 FormControlType type = ControlType(); 245 return type == FormControlType::Textarea || 246 IsSingleLineTextControl(aExcludePassword, type); 247 } 248 249 bool nsIFormControl::IsSingleLineTextControl(bool aExcludePassword) const { 250 return IsSingleLineTextControl(aExcludePassword, ControlType()); 251 } 252 253 /*static*/ 254 bool nsIFormControl::IsSingleLineTextControl(bool aExcludePassword, 255 FormControlType aType) { 256 switch (aType) { 257 case FormControlType::InputText: 258 case FormControlType::InputEmail: 259 case FormControlType::InputSearch: 260 case FormControlType::InputTel: 261 case FormControlType::InputUrl: 262 case FormControlType::InputNumber: 263 // TODO: those are temporary until bug 773205 is fixed. 264 case FormControlType::InputMonth: 265 case FormControlType::InputWeek: 266 return true; 267 case FormControlType::InputPassword: 268 return !aExcludePassword; 269 default: 270 return false; 271 } 272 } 273 274 bool nsIFormControl::IsSubmittableControl() const { 275 auto type = ControlType(); 276 return type == FormControlType::Object || type == FormControlType::Textarea || 277 type == FormControlType::Select || IsButtonElement(type) || 278 IsInputElement(type); 279 } 280 281 bool nsIFormControl::IsConceptButton() const { 282 auto type = ControlType(); 283 return IsSubmitControl() || type == FormControlType::InputReset || 284 type == FormControlType::InputButton || IsButtonElement(type); 285 } 286 287 bool nsIFormControl::IsButtonControl() const { 288 return IsConceptButton() && (!GetForm() || !IsSubmitControl()); 289 } 290 291 bool nsIFormControl::AllowDraggableChildren() const { 292 auto type = ControlType(); 293 return type == FormControlType::Object || type == FormControlType::Fieldset || 294 type == FormControlType::Output; 295 } 296 297 #endif /* nsIFormControl_h___ */