1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is Mozilla Communicator client code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 1998
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Pierre Phaneuf <pp@ludusdesign.com>
24 : * Mats Palmgren <mats.palmgren@bredband.net>
25 : * Olli Pettay <Olli.Pettay@helsinki.fi>
26 : *
27 : * Alternatively, the contents of this file may be used under the terms of
28 : * either of the GNU General Public License Version 2 or later (the "GPL"),
29 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 : * in which case the provisions of the GPL or the LGPL are applicable instead
31 : * of those above. If you wish to allow use of your version of this file only
32 : * under the terms of either the GPL or the LGPL, and not to allow others to
33 : * use your version of this file under the terms of the MPL, indicate your
34 : * decision by deleting the provisions above and replace them with the notice
35 : * and other provisions required by the GPL or the LGPL. If you do not delete
36 : * the provisions above, a recipient may use your version of this file under
37 : * the terms of any one of the MPL, the GPL or the LGPL.
38 : *
39 : * ***** END LICENSE BLOCK ***** */
40 : #ifndef nsHTMLSelectElement_h___
41 : #define nsHTMLSelectElement_h___
42 :
43 : #include "nsCOMPtr.h"
44 : #include "nsCOMArray.h"
45 : #include "nsGenericHTMLElement.h"
46 : #include "nsIDOMHTMLSelectElement.h"
47 : #include "nsIDOMHTMLFormElement.h"
48 : #include "nsIDOMHTMLOptionElement.h"
49 : #include "nsIDOMHTMLOptionsCollection.h"
50 : #include "nsISelectControlFrame.h"
51 : #include "nsIHTMLCollection.h"
52 : #include "nsIConstraintValidation.h"
53 :
54 : // PresState
55 : #include "nsXPCOM.h"
56 : #include "nsPresState.h"
57 : #include "nsIComponentManager.h"
58 : #include "nsCheapSets.h"
59 : #include "nsLayoutErrors.h"
60 : #include "nsHTMLOptionElement.h"
61 : #include "nsHTMLFormElement.h"
62 :
63 : class nsHTMLSelectElement;
64 :
65 : /**
66 : * The collection of options in the select (what you get back when you do
67 : * select.options in DOM)
68 : */
69 : class nsHTMLOptionCollection: public nsIDOMHTMLOptionsCollection,
70 : public nsIHTMLCollection,
71 : public nsWrapperCache
72 : {
73 : public:
74 : nsHTMLOptionCollection(nsHTMLSelectElement* aSelect);
75 : virtual ~nsHTMLOptionCollection();
76 :
77 0 : NS_DECL_CYCLE_COLLECTING_ISUPPORTS
78 :
79 : virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope,
80 : bool *triedToWrap);
81 :
82 : // nsIDOMHTMLOptionsCollection interface
83 : NS_DECL_NSIDOMHTMLOPTIONSCOLLECTION
84 :
85 : // nsIDOMHTMLCollection interface, all its methods are defined in
86 : // nsIDOMHTMLOptionsCollection
87 :
88 : virtual nsIContent* GetNodeAt(PRUint32 aIndex);
89 : virtual nsINode* GetParentObject();
90 :
91 1464 : NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsHTMLOptionCollection,
92 : nsIHTMLCollection)
93 :
94 : // Helpers for nsHTMLSelectElement
95 : /**
96 : * Insert an option
97 : * @param aOption the option to insert
98 : * @param aIndex the index to insert at
99 : */
100 0 : bool InsertOptionAt(nsHTMLOptionElement* aOption, PRUint32 aIndex)
101 : {
102 0 : return !!mElements.InsertElementAt(aIndex, aOption);
103 : }
104 :
105 : /**
106 : * Remove an option
107 : * @param aIndex the index of the option to remove
108 : */
109 0 : void RemoveOptionAt(PRUint32 aIndex)
110 : {
111 0 : mElements.RemoveElementAt(aIndex);
112 0 : }
113 :
114 : /**
115 : * Get the option at the index
116 : * @param aIndex the index
117 : * @param aReturn the option returned [OUT]
118 : */
119 0 : nsHTMLOptionElement *ItemAsOption(PRUint32 aIndex)
120 : {
121 0 : return mElements.SafeElementAt(aIndex, nsnull);
122 : }
123 :
124 : /**
125 : * Clears out all options
126 : */
127 0 : void Clear()
128 : {
129 0 : mElements.Clear();
130 0 : }
131 :
132 : /**
133 : * Append an option to end of array
134 : */
135 0 : bool AppendOption(nsHTMLOptionElement* aOption)
136 : {
137 0 : return !!mElements.AppendElement(aOption);
138 : }
139 :
140 : /**
141 : * Drop the reference to the select. Called during select destruction.
142 : */
143 : void DropReference();
144 :
145 : /**
146 : * Finds the index of a given option element.
147 : * If the option isn't part of the collection, return NS_ERROR_FAILURE
148 : * without setting aIndex.
149 : *
150 : * @param aOption the option to get the index of
151 : * @param aStartIndex the index to start looking at
152 : * @param aForward TRUE to look forward, FALSE to look backward
153 : * @return the option index
154 : */
155 : nsresult GetOptionIndex(mozilla::dom::Element* aOption,
156 : PRInt32 aStartIndex, bool aForward,
157 : PRInt32* aIndex);
158 :
159 : private:
160 : /** The list of options (holds strong references) */
161 : nsTArray<nsRefPtr<nsHTMLOptionElement> > mElements;
162 : /** The select element that contains this array */
163 : nsHTMLSelectElement* mSelect;
164 : };
165 :
166 : #define NS_SELECT_STATE_IID \
167 : { /* 4db54c7c-d159-455f-9d8e-f60ee466dbf3 */ \
168 : 0x4db54c7c, \
169 : 0xd159, \
170 : 0x455f, \
171 : {0x9d, 0x8e, 0xf6, 0x0e, 0xe4, 0x66, 0xdb, 0xf3} \
172 : }
173 :
174 : /**
175 : * The restore state used by select
176 : */
177 : class nsSelectState : public nsISupports {
178 : public:
179 0 : nsSelectState()
180 0 : {
181 0 : }
182 0 : virtual ~nsSelectState()
183 0 : {
184 0 : }
185 :
186 : NS_DECLARE_STATIC_IID_ACCESSOR(NS_SELECT_STATE_IID)
187 : NS_DECL_ISUPPORTS
188 :
189 0 : void PutOption(PRInt32 aIndex, const nsAString& aValue)
190 : {
191 : // If the option is empty, store the index. If not, store the value.
192 0 : if (aValue.IsEmpty()) {
193 0 : mIndices.Put(aIndex);
194 : } else {
195 0 : mValues.Put(aValue);
196 : }
197 0 : }
198 :
199 0 : bool ContainsOption(PRInt32 aIndex, const nsAString& aValue)
200 : {
201 0 : return mValues.Contains(aValue) || mIndices.Contains(aIndex);
202 : }
203 :
204 : private:
205 : nsCheapSet<nsStringHashKey> mValues;
206 : nsCheapSet<nsUint32HashKey> mIndices;
207 : };
208 :
209 : class NS_STACK_CLASS nsSafeOptionListMutation
210 : {
211 : public:
212 : /**
213 : * @param aSelect The select element which option list is being mutated.
214 : * Can be null.
215 : * @param aParent The content object which is being mutated.
216 : * @param aKid If not null, a new child element is being inserted to
217 : * aParent. Otherwise a child element will be removed.
218 : * @param aIndex The index of the content object in the parent.
219 : */
220 : nsSafeOptionListMutation(nsIContent* aSelect, nsIContent* aParent,
221 : nsIContent* aKid, PRUint32 aIndex, bool aNotify);
222 : ~nsSafeOptionListMutation();
223 0 : void MutationFailed() { mNeedsRebuild = true; }
224 : private:
225 : static void* operator new(size_t) CPP_THROW_NEW { return 0; }
226 : static void operator delete(void*, size_t) {}
227 : /** The select element which option list is being mutated. */
228 : nsRefPtr<nsHTMLSelectElement> mSelect;
229 : /** true if the current mutation is the first one in the stack. */
230 : bool mTopLevelMutation;
231 : /** true if it is known that the option list must be recreated. */
232 : bool mNeedsRebuild;
233 : /** Option list must be recreated if more than one mutation is detected. */
234 : nsMutationGuard mGuard;
235 : };
236 :
237 :
238 : /**
239 : * Implementation of <select>
240 : */
241 : class nsHTMLSelectElement : public nsGenericHTMLFormElement,
242 : public nsIDOMHTMLSelectElement,
243 : public nsIConstraintValidation
244 : {
245 : public:
246 : using nsIConstraintValidation::GetValidationMessage;
247 :
248 : nsHTMLSelectElement(already_AddRefed<nsINodeInfo> aNodeInfo,
249 : mozilla::dom::FromParser aFromParser = mozilla::dom::NOT_FROM_PARSER);
250 : virtual ~nsHTMLSelectElement();
251 :
252 : /** Typesafe, non-refcounting cast from nsIContent. Cheaper than QI. **/
253 0 : static nsHTMLSelectElement* FromContent(nsIContent* aContent)
254 : {
255 0 : if (aContent && aContent->IsHTML(nsGkAtoms::select))
256 0 : return static_cast<nsHTMLSelectElement*>(aContent);
257 0 : return nsnull;
258 : }
259 :
260 : // nsISupports
261 : NS_DECL_ISUPPORTS_INHERITED
262 :
263 : // nsIDOMNode
264 0 : NS_FORWARD_NSIDOMNODE(nsGenericHTMLFormElement::)
265 :
266 : // nsIDOMElement
267 0 : NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLFormElement::)
268 :
269 : // nsIDOMHTMLElement
270 0 : NS_FORWARD_NSIDOMHTMLELEMENT_BASIC(nsGenericHTMLFormElement::)
271 0 : NS_SCRIPTABLE NS_IMETHOD Click() {
272 0 : return nsGenericHTMLFormElement::Click();
273 : }
274 : NS_SCRIPTABLE NS_IMETHOD GetTabIndex(PRInt32* aTabIndex);
275 : NS_SCRIPTABLE NS_IMETHOD SetTabIndex(PRInt32 aTabIndex);
276 0 : NS_SCRIPTABLE NS_IMETHOD Focus() {
277 0 : return nsGenericHTMLFormElement::Focus();
278 : }
279 0 : NS_SCRIPTABLE NS_IMETHOD GetDraggable(bool* aDraggable) {
280 0 : return nsGenericHTMLFormElement::GetDraggable(aDraggable);
281 : }
282 0 : NS_SCRIPTABLE NS_IMETHOD GetInnerHTML(nsAString& aInnerHTML) {
283 0 : return nsGenericHTMLFormElement::GetInnerHTML(aInnerHTML);
284 : }
285 0 : NS_SCRIPTABLE NS_IMETHOD SetInnerHTML(const nsAString& aInnerHTML) {
286 0 : return nsGenericHTMLFormElement::SetInnerHTML(aInnerHTML);
287 : }
288 :
289 : // nsIDOMHTMLSelectElement
290 : NS_DECL_NSIDOMHTMLSELECTELEMENT
291 :
292 : // nsIContent
293 : virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
294 : virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
295 :
296 : virtual bool IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable, PRInt32 *aTabIndex);
297 : virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
298 : bool aNotify);
299 : virtual nsresult RemoveChildAt(PRUint32 aIndex, bool aNotify);
300 :
301 : // Overriden nsIFormControl methods
302 0 : NS_IMETHOD_(PRUint32) GetType() const { return NS_FORM_SELECT; }
303 : NS_IMETHOD Reset();
304 : NS_IMETHOD SubmitNamesValues(nsFormSubmission* aFormSubmission);
305 : NS_IMETHOD SaveState();
306 : virtual bool RestoreState(nsPresState* aState);
307 :
308 : virtual void FieldSetDisabledChanged(bool aNotify);
309 :
310 : nsEventStates IntrinsicState() const;
311 :
312 : /**
313 : * To be called when stuff is added under a child of the select--but *before*
314 : * they are actually added.
315 : *
316 : * @param aOptions the content that was added (usually just an option, but
317 : * could be an optgroup node with many child options)
318 : * @param aParent the parent the options were added to (could be an optgroup)
319 : * @param aContentIndex the index where the options are being added within the
320 : * parent (if the parent is an optgroup, the index within the optgroup)
321 : */
322 : NS_IMETHOD WillAddOptions(nsIContent* aOptions,
323 : nsIContent* aParent,
324 : PRInt32 aContentIndex,
325 : bool aNotify);
326 :
327 : /**
328 : * To be called when stuff is removed under a child of the select--but
329 : * *before* they are actually removed.
330 : *
331 : * @param aParent the parent the option(s) are being removed from
332 : * @param aContentIndex the index of the option(s) within the parent (if the
333 : * parent is an optgroup, the index within the optgroup)
334 : */
335 : NS_IMETHOD WillRemoveOptions(nsIContent* aParent,
336 : PRInt32 aContentIndex,
337 : bool aNotify);
338 :
339 : /**
340 : * Checks whether an option is disabled (even if it's part of an optgroup)
341 : *
342 : * @param aIndex the index of the option to check
343 : * @return whether the option is disabled
344 : */
345 : NS_IMETHOD IsOptionDisabled(PRInt32 aIndex,
346 : bool *aIsDisabled NS_OUTPARAM);
347 :
348 : /**
349 : * Sets multiple options (or just sets startIndex if select is single)
350 : * and handles notifications and cleanup and everything under the sun.
351 : * When this method exits, the select will be in a consistent state. i.e.
352 : * if you set the last option to false, it will select an option anyway.
353 : *
354 : * @param aStartIndex the first index to set
355 : * @param aEndIndex the last index to set (set same as first index for one
356 : * option)
357 : * @param aIsSelected whether to set the option(s) to true or false
358 : * @param aClearAll whether to clear all other options (for example, if you
359 : * are normal-clicking on the current option)
360 : * @param aSetDisabled whether it is permissible to set disabled options
361 : * (for JavaScript)
362 : * @param aNotify whether to notify frames and such
363 : * @return whether any options were actually changed
364 : */
365 : NS_IMETHOD SetOptionsSelectedByIndex(PRInt32 aStartIndex,
366 : PRInt32 aEndIndex,
367 : bool aIsSelected,
368 : bool aClearAll,
369 : bool aSetDisabled,
370 : bool aNotify,
371 : bool* aChangedSomething NS_OUTPARAM);
372 :
373 : /**
374 : * Finds the index of a given option element
375 : *
376 : * @param aOption the option to get the index of
377 : * @param aStartIndex the index to start looking at
378 : * @param aForward TRUE to look forward, FALSE to look backward
379 : * @return the option index
380 : */
381 : NS_IMETHOD GetOptionIndex(nsIDOMHTMLOptionElement* aOption,
382 : PRInt32 aStartIndex,
383 : bool aForward,
384 : PRInt32* aIndex NS_OUTPARAM);
385 :
386 : /** Whether or not there are optgroups in this select */
387 : NS_IMETHOD GetHasOptGroups(bool* aHasGroups);
388 :
389 : /**
390 : * Called when an attribute is about to be changed
391 : */
392 : virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
393 : nsIContent* aBindingParent,
394 : bool aCompileEventHandlers);
395 : virtual void UnbindFromTree(bool aDeep, bool aNullParent);
396 : virtual nsresult BeforeSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
397 : const nsAttrValueOrString* aValue,
398 : bool aNotify);
399 : virtual nsresult AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
400 : const nsAttrValue* aValue, bool aNotify);
401 : virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
402 : bool aNotify);
403 :
404 : virtual void DoneAddingChildren(bool aHaveNotified);
405 0 : virtual bool IsDoneAddingChildren() {
406 0 : return mIsDoneAddingChildren;
407 : }
408 :
409 : virtual bool ParseAttribute(PRInt32 aNamespaceID,
410 : nsIAtom* aAttribute,
411 : const nsAString& aValue,
412 : nsAttrValue& aResult);
413 : virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
414 : virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
415 : PRInt32 aModType) const;
416 : NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
417 :
418 : virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
419 :
420 1464 : NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsHTMLSelectElement,
421 : nsGenericHTMLFormElement)
422 :
423 0 : nsHTMLOptionCollection *GetOptions()
424 : {
425 0 : return mOptions;
426 : }
427 :
428 0 : static nsHTMLSelectElement *FromSupports(nsISupports *aSupports)
429 : {
430 0 : return static_cast<nsHTMLSelectElement*>(static_cast<nsINode*>(aSupports));
431 : }
432 :
433 : virtual nsXPCClassInfo* GetClassInfo();
434 :
435 : // nsIConstraintValidation
436 : nsresult GetValidationMessage(nsAString& aValidationMessage,
437 : ValidityStateType aType);
438 :
439 : protected:
440 : friend class nsSafeOptionListMutation;
441 :
442 : // Helper Methods
443 : /**
444 : * Check whether the option specified by the index is selected
445 : * @param aIndex the index
446 : * @return whether the option at the index is selected
447 : */
448 : bool IsOptionSelectedByIndex(PRInt32 aIndex);
449 : /**
450 : * Starting with (and including) aStartIndex, find the first selected index
451 : * and set mSelectedIndex to it.
452 : * @param aStartIndex the index to start with
453 : */
454 : void FindSelectedIndex(PRInt32 aStartIndex, bool aNotify);
455 : /**
456 : * Select some option if possible (generally the first non-disabled option).
457 : * @return true if something was selected, false otherwise
458 : */
459 : bool SelectSomething(bool aNotify);
460 : /**
461 : * Call SelectSomething(), but only if nothing is selected
462 : * @see SelectSomething()
463 : * @return true if something was selected, false otherwise
464 : */
465 : bool CheckSelectSomething(bool aNotify);
466 : /**
467 : * Called to trigger notifications of frames and fixing selected index
468 : *
469 : * @param aSelectFrame the frame for this content (could be null)
470 : * @param aIndex the index that was selected or deselected
471 : * @param aSelected whether the index was selected or deselected
472 : * @param aChangeOptionState if false, don't do anything to the
473 : * nsHTMLOptionElement at aIndex. If true, change
474 : * its selected state to aSelected.
475 : * @param aNotify whether to notify the style system and such
476 : */
477 : void OnOptionSelected(nsISelectControlFrame* aSelectFrame,
478 : PRInt32 aIndex,
479 : bool aSelected,
480 : bool aChangeOptionState,
481 : bool aNotify);
482 : /**
483 : * Restore state to a particular state string (representing the options)
484 : * @param aNewSelected the state string to restore to
485 : */
486 : void RestoreStateTo(nsSelectState* aNewSelected);
487 :
488 : // Adding options
489 : /**
490 : * Insert option(s) into the options[] array and perform notifications
491 : * @param aOptions the option or optgroup being added
492 : * @param aListIndex the index to start adding options into the list at
493 : * @param aDepth the depth of aOptions (1=direct child of select ...)
494 : */
495 : nsresult InsertOptionsIntoList(nsIContent* aOptions,
496 : PRInt32 aListIndex,
497 : PRInt32 aDepth,
498 : bool aNotify);
499 : /**
500 : * Remove option(s) from the options[] array
501 : * @param aOptions the option or optgroup being added
502 : * @param aListIndex the index to start removing options from the list at
503 : * @param aDepth the depth of aOptions (1=direct child of select ...)
504 : */
505 : nsresult RemoveOptionsFromList(nsIContent* aOptions,
506 : PRInt32 aListIndex,
507 : PRInt32 aDepth,
508 : bool aNotify);
509 : /**
510 : * Insert option(s) into the options[] array (called by InsertOptionsIntoList)
511 : * @param aOptions the option or optgroup being added
512 : * @param aInsertIndex the index to start adding options into the list at
513 : * @param aDepth the depth of aOptions (1=direct child of select ...)
514 : */
515 : nsresult InsertOptionsIntoListRecurse(nsIContent* aOptions,
516 : PRInt32* aInsertIndex,
517 : PRInt32 aDepth);
518 : /**
519 : * Remove option(s) from the options[] array (called by RemoveOptionsFromList)
520 : * @param aOptions the option or optgroup being added
521 : * @param aListIndex the index to start removing options from the list at
522 : * @param aNumRemoved the number removed so far [OUT]
523 : * @param aDepth the depth of aOptions (1=direct child of select ...)
524 : */
525 : nsresult RemoveOptionsFromListRecurse(nsIContent* aOptions,
526 : PRInt32 aRemoveIndex,
527 : PRInt32* aNumRemoved,
528 : PRInt32 aDepth);
529 :
530 : // nsIConstraintValidation
531 : void UpdateBarredFromConstraintValidation();
532 : bool IsValueMissing();
533 : void UpdateValueMissingValidityState();
534 :
535 : /**
536 : * Find out how deep this content is from the select (1=direct child)
537 : * @param aContent the content to check
538 : * @return the depth
539 : */
540 : PRInt32 GetContentDepth(nsIContent* aContent);
541 : /**
542 : * Get the index of the first option at, under or following the content in
543 : * the select, or length of options[] if none are found
544 : * @param aOptions the content
545 : * @return the index of the first option
546 : */
547 : PRInt32 GetOptionIndexAt(nsIContent* aOptions);
548 : /**
549 : * Get the next option following the content in question (not at or under)
550 : * (this could include siblings of the current content or siblings of the
551 : * parent or children of siblings of the parent).
552 : * @param aOptions the content
553 : * @return the index of the next option after the content
554 : */
555 : PRInt32 GetOptionIndexAfter(nsIContent* aOptions);
556 : /**
557 : * Get the first option index at or under the content in question.
558 : * @param aOptions the content
559 : * @return the index of the first option at or under the content
560 : */
561 : PRInt32 GetFirstOptionIndex(nsIContent* aOptions);
562 : /**
563 : * Get the first option index under the content in question, within the
564 : * range specified.
565 : * @param aOptions the content
566 : * @param aStartIndex the first child to look at
567 : * @param aEndIndex the child *after* the last child to look at
568 : * @return the index of the first option at or under the content
569 : */
570 : PRInt32 GetFirstChildOptionIndex(nsIContent* aOptions,
571 : PRInt32 aStartIndex,
572 : PRInt32 aEndIndex);
573 :
574 : /**
575 : * Get the frame as an nsISelectControlFrame (MAY RETURN NULL)
576 : * @return the select frame, or null
577 : */
578 : nsISelectControlFrame *GetSelectFrame();
579 :
580 : /**
581 : * Is this a combobox?
582 : */
583 0 : bool IsCombobox() {
584 0 : if (HasAttr(kNameSpaceID_None, nsGkAtoms::multiple)) {
585 0 : return false;
586 : }
587 :
588 0 : PRInt32 size = 1;
589 0 : GetSize(&size);
590 0 : return size <= 1;
591 : }
592 :
593 : /**
594 : * Helper method for dispatching ContentReset notifications to list
595 : * and combo box frames.
596 : */
597 : void DispatchContentReset();
598 :
599 : /**
600 : * Rebuilds the options array from scratch as a fallback in error cases.
601 : */
602 : void RebuildOptionsArray(bool aNotify);
603 :
604 : #ifdef DEBUG
605 : void VerifyOptionsArray();
606 : #endif
607 :
608 : nsresult SetSelectedIndexInternal(PRInt32 aIndex, bool aNotify);
609 :
610 : void SetSelectionChanged(bool aValue, bool aNotify);
611 :
612 : /**
613 : * Return whether an element should have a validity UI.
614 : * (with :-moz-ui-invalid and :-moz-ui-valid pseudo-classes).
615 : *
616 : * @return Whether the element should have a validity UI.
617 : */
618 0 : bool ShouldShowValidityUI() const {
619 : /**
620 : * Always show the validity UI if the form has already tried to be submitted
621 : * but was invalid.
622 : *
623 : * Otherwise, show the validity UI if the selection has been changed.
624 : */
625 0 : if (mForm && mForm->HasEverTriedInvalidSubmit()) {
626 0 : return true;
627 : }
628 :
629 0 : return mSelectionHasChanged;
630 : }
631 :
632 : /**
633 : * Insert aElement before the node given by aBefore
634 : */
635 : nsresult Add(nsIDOMHTMLElement* aElement, nsIDOMHTMLElement* aBefore = nsnull);
636 :
637 : /** The options[] array */
638 : nsRefPtr<nsHTMLOptionCollection> mOptions;
639 : /** false if the parser is in the middle of adding children. */
640 : bool mIsDoneAddingChildren;
641 : /** true if our disabled state has changed from the default **/
642 : bool mDisabledChanged;
643 : /** true if child nodes are being added or removed.
644 : * Used by nsSafeOptionListMutation.
645 : */
646 : bool mMutating;
647 : /**
648 : * True if DoneAddingChildren will get called but shouldn't restore state.
649 : */
650 : bool mInhibitStateRestoration;
651 : /**
652 : * True if the selection has changed since the element's creation.
653 : */
654 : bool mSelectionHasChanged;
655 : /**
656 : * True if the default selected option has been set.
657 : */
658 : bool mDefaultSelectionSet;
659 : /**
660 : * True if :-moz-ui-invalid can be shown.
661 : */
662 : bool mCanShowInvalidUI;
663 : /**
664 : * True if :-moz-ui-valid can be shown.
665 : */
666 : bool mCanShowValidUI;
667 :
668 : /** The number of non-options as children of the select */
669 : PRUint32 mNonOptionChildren;
670 : /** The number of optgroups anywhere under the select */
671 : PRUint32 mOptGroupCount;
672 : /**
673 : * The current selected index for selectedIndex (will be the first selected
674 : * index if multiple are selected)
675 : */
676 : PRInt32 mSelectedIndex;
677 : /**
678 : * The temporary restore state in case we try to restore before parser is
679 : * done adding options
680 : */
681 : nsCOMPtr<nsSelectState> mRestoreState;
682 : };
683 :
684 : #endif
|