зеркало из https://github.com/mozilla/pjs.git
Bug 339501, r=bz, sr=sicking, a=1.9+
This commit is contained in:
Родитель
44d62b28b7
Коммит
93dbdbf87f
|
@ -48,6 +48,7 @@
|
||||||
#include "nsISelectElement.h"
|
#include "nsISelectElement.h"
|
||||||
#include "nsIDOMHTMLSelectElement.h"
|
#include "nsIDOMHTMLSelectElement.h"
|
||||||
#include "nsEventDispatcher.h"
|
#include "nsEventDispatcher.h"
|
||||||
|
#include "nsHTMLSelectElement.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The implementation of <optgroup>
|
* The implementation of <optgroup>
|
||||||
|
@ -174,23 +175,23 @@ nsHTMLOptGroupElement::InsertChildAt(nsIContent* aKid,
|
||||||
PRUint32 aIndex,
|
PRUint32 aIndex,
|
||||||
PRBool aNotify)
|
PRBool aNotify)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsISelectElement> sel = do_QueryInterface(GetSelect());
|
nsSafeOptionListMutation safeMutation(GetSelect(), this, aKid, aIndex);
|
||||||
if (sel) {
|
nsresult rv = nsGenericHTMLElement::InsertChildAt(aKid, aIndex, aNotify);
|
||||||
sel->WillAddOptions(aKid, this, aIndex);
|
if (NS_FAILED(rv)) {
|
||||||
|
safeMutation.MutationFailed();
|
||||||
}
|
}
|
||||||
|
return rv;
|
||||||
return nsGenericHTMLElement::InsertChildAt(aKid, aIndex, aNotify);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsHTMLOptGroupElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify)
|
nsHTMLOptGroupElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsISelectElement> sel = do_QueryInterface(GetSelect());
|
nsSafeOptionListMutation safeMutation(GetSelect(), this, nsnull, aIndex);
|
||||||
if (sel) {
|
nsresult rv = nsGenericHTMLElement::RemoveChildAt(aIndex, aNotify);
|
||||||
sel->WillRemoveOptions(this, aIndex);
|
if (NS_FAILED(rv)) {
|
||||||
|
safeMutation.MutationFailed();
|
||||||
}
|
}
|
||||||
|
return rv;
|
||||||
return nsGenericHTMLElement::RemoveChildAt(aIndex, aNotify);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PRInt32
|
PRInt32
|
||||||
|
|
|
@ -36,15 +36,10 @@
|
||||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
*
|
*
|
||||||
* ***** END LICENSE BLOCK ***** */
|
* ***** END LICENSE BLOCK ***** */
|
||||||
#include "nsCOMPtr.h"
|
|
||||||
#include "nsCOMArray.h"
|
#include "nsHTMLSelectElement.h"
|
||||||
#include "nsIDOMHTMLSelectElement.h"
|
|
||||||
#include "nsIDOMNSHTMLSelectElement.h"
|
|
||||||
#include "nsIDOMNSXBLFormControl.h"
|
|
||||||
#include "nsIDOMHTMLFormElement.h"
|
|
||||||
#include "nsIDOMEventTarget.h"
|
#include "nsIDOMEventTarget.h"
|
||||||
#include "nsContentCreatorFunctions.h"
|
#include "nsContentCreatorFunctions.h"
|
||||||
#include "nsGenericHTMLElement.h"
|
|
||||||
#include "nsGkAtoms.h"
|
#include "nsGkAtoms.h"
|
||||||
#include "nsStyleConsts.h"
|
#include "nsStyleConsts.h"
|
||||||
#include "nsPresContext.h"
|
#include "nsPresContext.h"
|
||||||
|
@ -52,28 +47,16 @@
|
||||||
#include "nsMappedAttributes.h"
|
#include "nsMappedAttributes.h"
|
||||||
#include "nsIForm.h"
|
#include "nsIForm.h"
|
||||||
#include "nsIFormSubmission.h"
|
#include "nsIFormSubmission.h"
|
||||||
#include "nsIDOMHTMLCollection.h"
|
|
||||||
#include "nsIDOMHTMLOptionElement.h"
|
|
||||||
#include "nsIDOMHTMLOptGroupElement.h"
|
#include "nsIDOMHTMLOptGroupElement.h"
|
||||||
#include "nsIOptionElement.h"
|
#include "nsIOptionElement.h"
|
||||||
#include "nsIEventStateManager.h"
|
#include "nsIEventStateManager.h"
|
||||||
#include "nsISelectElement.h"
|
|
||||||
#include "nsISelectControlFrame.h"
|
|
||||||
#include "nsIDOMHTMLOptionsCollection.h"
|
|
||||||
#include "nsIDOMNSHTMLOptionCollectn.h"
|
|
||||||
#include "nsGUIEvent.h"
|
#include "nsGUIEvent.h"
|
||||||
#include "nsIPrivateDOMEvent.h"
|
#include "nsIPrivateDOMEvent.h"
|
||||||
#include "nsIBoxObject.h"
|
#include "nsIBoxObject.h"
|
||||||
#include "nsIDOMNSDocument.h"
|
#include "nsIDOMNSDocument.h"
|
||||||
#include "nsIDOMDocumentEvent.h"
|
#include "nsIDOMDocumentEvent.h"
|
||||||
|
|
||||||
// PresState
|
|
||||||
#include "nsXPCOM.h"
|
|
||||||
#include "nsPresState.h"
|
|
||||||
#include "nsIComponentManager.h"
|
|
||||||
#include "nsCheapSets.h"
|
|
||||||
#include "nsLayoutErrors.h"
|
|
||||||
|
|
||||||
// Notify/query select frame for selectedIndex
|
// Notify/query select frame for selectedIndex
|
||||||
#include "nsIDocument.h"
|
#include "nsIDocument.h"
|
||||||
#include "nsIPresShell.h"
|
#include "nsIPresShell.h"
|
||||||
|
@ -86,405 +69,58 @@
|
||||||
#include "nsRuleData.h"
|
#include "nsRuleData.h"
|
||||||
#include "nsEventDispatcher.h"
|
#include "nsEventDispatcher.h"
|
||||||
|
|
||||||
class nsHTMLSelectElement;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The collection of options in the select (what you get back when you do
|
|
||||||
* select.options in DOM)
|
|
||||||
*/
|
|
||||||
class nsHTMLOptionCollection: public nsIDOMHTMLOptionsCollection,
|
|
||||||
public nsIDOMNSHTMLOptionCollection,
|
|
||||||
public nsIDOMHTMLCollection
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
nsHTMLOptionCollection(nsHTMLSelectElement* aSelect);
|
|
||||||
virtual ~nsHTMLOptionCollection();
|
|
||||||
|
|
||||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
|
||||||
|
|
||||||
// nsIDOMHTMLOptionsCollection interface
|
|
||||||
NS_DECL_NSIDOMHTMLOPTIONSCOLLECTION
|
|
||||||
|
|
||||||
// nsIDOMNSHTMLOptionCollection interface
|
|
||||||
NS_DECL_NSIDOMNSHTMLOPTIONCOLLECTION
|
|
||||||
|
|
||||||
// nsIDOMHTMLCollection interface, all its methods are defined in
|
|
||||||
// nsIDOMHTMLOptionsCollection
|
|
||||||
|
|
||||||
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsHTMLOptionCollection,
|
|
||||||
nsIDOMNSHTMLOptionCollection)
|
|
||||||
|
|
||||||
// Helpers for nsHTMLSelectElement
|
|
||||||
/**
|
|
||||||
* Insert an option
|
|
||||||
* @param aOption the option to insert
|
|
||||||
* @param aIndex the index to insert at
|
|
||||||
*/
|
|
||||||
PRBool InsertOptionAt(nsIDOMHTMLOptionElement* aOption, PRInt32 aIndex)
|
|
||||||
{
|
|
||||||
return mElements.InsertObjectAt(aOption, aIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove an option
|
|
||||||
* @param aIndex the index of the option to remove
|
|
||||||
*/
|
|
||||||
void RemoveOptionAt(PRInt32 aIndex)
|
|
||||||
{
|
|
||||||
mElements.RemoveObjectAt(aIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the option at the index
|
|
||||||
* @param aIndex the index
|
|
||||||
* @param aReturn the option returned [OUT]
|
|
||||||
*/
|
|
||||||
nsIDOMHTMLOptionElement *ItemAsOption(PRInt32 aIndex)
|
|
||||||
{
|
|
||||||
return mElements.SafeObjectAt(aIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clears out all options
|
|
||||||
*/
|
|
||||||
void Clear()
|
|
||||||
{
|
|
||||||
mElements.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Append an option to end of array
|
|
||||||
*/
|
|
||||||
PRBool AppendOption(nsIDOMHTMLOptionElement* aOption)
|
|
||||||
{
|
|
||||||
return mElements.AppendObject(aOption);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Drop the reference to the select. Called during select destruction.
|
|
||||||
*/
|
|
||||||
void DropReference();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* See nsISelectElement.idl for documentation on this method
|
|
||||||
*/
|
|
||||||
nsresult GetOptionIndex(nsIDOMHTMLOptionElement* aOption,
|
|
||||||
PRInt32 aStartIndex, PRBool aForward,
|
|
||||||
PRInt32* aIndex);
|
|
||||||
|
|
||||||
private:
|
|
||||||
/** The list of options (holds strong references) */
|
|
||||||
nsCOMArray<nsIDOMHTMLOptionElement> mElements;
|
|
||||||
/** The select element that contains this array */
|
|
||||||
nsHTMLSelectElement* mSelect;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The restore state used by select
|
|
||||||
*/
|
|
||||||
class nsSelectState : public nsISupports {
|
|
||||||
public:
|
|
||||||
nsSelectState()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
virtual ~nsSelectState()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_DECL_ISUPPORTS
|
|
||||||
|
|
||||||
void PutOption(PRInt32 aIndex, const nsAString& aValue)
|
|
||||||
{
|
|
||||||
// If the option is empty, store the index. If not, store the value.
|
|
||||||
if (aValue.IsEmpty()) {
|
|
||||||
mIndices.Put(aIndex);
|
|
||||||
} else {
|
|
||||||
mValues.Put(aValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PRBool ContainsOption(PRInt32 aIndex, const nsAString& aValue)
|
|
||||||
{
|
|
||||||
return mValues.Contains(aValue) || mIndices.Contains(aIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
nsCheapStringSet mValues;
|
|
||||||
nsCheapInt32Set mIndices;
|
|
||||||
};
|
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS0(nsSelectState)
|
NS_IMPL_ISUPPORTS0(nsSelectState)
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// nsSafeOptionListMutation
|
||||||
|
//
|
||||||
|
|
||||||
/**
|
nsSafeOptionListMutation::nsSafeOptionListMutation(nsIContent* aSelect,
|
||||||
* Implementation of <select>
|
nsIContent* aParent,
|
||||||
*/
|
nsIContent* aKid,
|
||||||
class nsHTMLSelectElement : public nsGenericHTMLFormElement,
|
PRUint32 aIndex)
|
||||||
public nsIDOMHTMLSelectElement,
|
: mSelect(do_QueryInterface(aSelect)), mTopLevelMutation(PR_FALSE),
|
||||||
public nsIDOMNSHTMLSelectElement,
|
mNeedsRebuild(PR_FALSE)
|
||||||
public nsIDOMNSXBLFormControl,
|
|
||||||
public nsISelectElement
|
|
||||||
{
|
{
|
||||||
public:
|
nsHTMLSelectElement* select = static_cast<nsHTMLSelectElement*>(mSelect.get());
|
||||||
nsHTMLSelectElement(nsINodeInfo *aNodeInfo, PRBool aFromParser = PR_FALSE);
|
if (select) {
|
||||||
virtual ~nsHTMLSelectElement();
|
mTopLevelMutation = !select->mMutating;
|
||||||
|
if (mTopLevelMutation) {
|
||||||
// nsISupports
|
select->mMutating = PR_TRUE;
|
||||||
NS_DECL_ISUPPORTS_INHERITED
|
} else {
|
||||||
|
// This is very unfortunate, but to handle mutation events properly,
|
||||||
// nsIDOMNode
|
// option list must be up-to-date before inserting or removing options.
|
||||||
NS_FORWARD_NSIDOMNODE(nsGenericHTMLFormElement::)
|
// Fortunately this is called only if mutation event listener
|
||||||
|
// adds or removes options.
|
||||||
// nsIDOMElement
|
select->RebuildOptionsArray();
|
||||||
NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLFormElement::)
|
}
|
||||||
|
nsresult rv;
|
||||||
// nsIDOMHTMLElement
|
if (aKid) {
|
||||||
NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLFormElement::)
|
rv = mSelect->WillAddOptions(aKid, aParent, aIndex);
|
||||||
|
} else {
|
||||||
// nsIDOMHTMLSelectElement
|
rv = mSelect->WillRemoveOptions(aParent, aIndex);
|
||||||
NS_DECL_NSIDOMHTMLSELECTELEMENT
|
}
|
||||||
|
mNeedsRebuild = NS_FAILED(rv);
|
||||||
// nsIDOMNSHTMLSelectElement
|
|
||||||
NS_DECL_NSIDOMNSHTMLSELECTELEMENT
|
|
||||||
|
|
||||||
// nsIDOMNSXBLFormControl
|
|
||||||
NS_DECL_NSIDOMNSXBLFORMCONTROL
|
|
||||||
|
|
||||||
// nsIContent
|
|
||||||
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
|
|
||||||
|
|
||||||
virtual void SetFocus(nsPresContext* aPresContext);
|
|
||||||
virtual PRBool IsFocusable(PRInt32 *aTabIndex = nsnull);
|
|
||||||
virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
|
|
||||||
PRBool aNotify);
|
|
||||||
virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify);
|
|
||||||
|
|
||||||
// Overriden nsIFormControl methods
|
|
||||||
NS_IMETHOD_(PRInt32) GetType() const { return NS_FORM_SELECT; }
|
|
||||||
NS_IMETHOD Reset();
|
|
||||||
NS_IMETHOD SubmitNamesValues(nsIFormSubmission* aFormSubmission,
|
|
||||||
nsIContent* aSubmitElement);
|
|
||||||
NS_IMETHOD SaveState();
|
|
||||||
virtual PRBool RestoreState(nsPresState* aState);
|
|
||||||
|
|
||||||
// nsISelectElement
|
|
||||||
NS_DECL_NSISELECTELEMENT
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when an attribute is about to be changed
|
|
||||||
*/
|
|
||||||
virtual nsresult BeforeSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
|
||||||
const nsAString* aValue, PRBool aNotify);
|
|
||||||
virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
|
|
||||||
PRBool aNotify);
|
|
||||||
|
|
||||||
virtual nsresult DoneAddingChildren(PRBool aHaveNotified);
|
|
||||||
virtual PRBool IsDoneAddingChildren();
|
|
||||||
|
|
||||||
virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
|
|
||||||
nsIAtom* aAttribute,
|
|
||||||
const nsAString& aValue,
|
|
||||||
nsAttrValue& aResult);
|
|
||||||
virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
|
|
||||||
virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
|
|
||||||
PRInt32 aModType) const;
|
|
||||||
NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
|
|
||||||
|
|
||||||
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
|
|
||||||
|
|
||||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsHTMLSelectElement,
|
|
||||||
nsGenericHTMLFormElement)
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// Helper Methods
|
|
||||||
/**
|
|
||||||
* Check whether the option specified by the index is selected
|
|
||||||
* @param aIndex the index
|
|
||||||
* @return whether the option at the index is selected
|
|
||||||
*/
|
|
||||||
PRBool IsOptionSelectedByIndex(PRInt32 aIndex);
|
|
||||||
/**
|
|
||||||
* Starting with (and including) aStartIndex, find the first selected index
|
|
||||||
* and set mSelectedIndex to it.
|
|
||||||
* @param aStartIndex the index to start with
|
|
||||||
*/
|
|
||||||
void FindSelectedIndex(PRInt32 aStartIndex);
|
|
||||||
/**
|
|
||||||
* Select some option if possible (generally the first non-disabled option).
|
|
||||||
* @return true if something was selected, false otherwise
|
|
||||||
*/
|
|
||||||
PRBool SelectSomething();
|
|
||||||
/**
|
|
||||||
* Call SelectSomething(), but only if nothing is selected
|
|
||||||
* @see SelectSomething()
|
|
||||||
* @return true if something was selected, false otherwise
|
|
||||||
*/
|
|
||||||
PRBool CheckSelectSomething();
|
|
||||||
/**
|
|
||||||
* Called to trigger notifications of frames and fixing selected index
|
|
||||||
*
|
|
||||||
* @param aSelectFrame the frame for this content (could be null)
|
|
||||||
* @param aPresContext the current pres context
|
|
||||||
* @param aIndex the index that was selected or deselected
|
|
||||||
* @param aSelected whether the index was selected or deselected
|
|
||||||
* @param aNotify whether to notify the style system and such
|
|
||||||
*/
|
|
||||||
void OnOptionSelected(nsISelectControlFrame* aSelectFrame,
|
|
||||||
nsPresContext* aPresContext,
|
|
||||||
PRInt32 aIndex,
|
|
||||||
PRBool aSelected,
|
|
||||||
PRBool aNotify);
|
|
||||||
/**
|
|
||||||
* Restore state to a particular state string (representing the options)
|
|
||||||
* @param aNewSelected the state string to restore to
|
|
||||||
*/
|
|
||||||
void RestoreStateTo(nsSelectState* aNewSelected);
|
|
||||||
|
|
||||||
#ifdef DEBUG_john
|
|
||||||
// Don't remove these, por favor. They're very useful in debugging
|
|
||||||
nsresult PrintOptions(nsIContent* aOptions, PRInt32 tabs);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Adding options
|
|
||||||
/**
|
|
||||||
* Insert option(s) into the options[] array and perform notifications
|
|
||||||
* @param aOptions the option or optgroup being added
|
|
||||||
* @param aListIndex the index to start adding options into the list at
|
|
||||||
* @param aDepth the depth of aOptions (1=direct child of select ...)
|
|
||||||
*/
|
|
||||||
nsresult InsertOptionsIntoList(nsIContent* aOptions,
|
|
||||||
PRInt32 aListIndex,
|
|
||||||
PRInt32 aDepth);
|
|
||||||
/**
|
|
||||||
* Remove option(s) from the options[] array
|
|
||||||
* @param aOptions the option or optgroup being added
|
|
||||||
* @param aListIndex the index to start removing options from the list at
|
|
||||||
* @param aDepth the depth of aOptions (1=direct child of select ...)
|
|
||||||
*/
|
|
||||||
nsresult RemoveOptionsFromList(nsIContent* aOptions,
|
|
||||||
PRInt32 aListIndex,
|
|
||||||
PRInt32 aDepth);
|
|
||||||
/**
|
|
||||||
* Insert option(s) into the options[] array (called by InsertOptionsIntoList)
|
|
||||||
* @param aOptions the option or optgroup being added
|
|
||||||
* @param aInsertIndex the index to start adding options into the list at
|
|
||||||
* @param aDepth the depth of aOptions (1=direct child of select ...)
|
|
||||||
*/
|
|
||||||
nsresult InsertOptionsIntoListRecurse(nsIContent* aOptions,
|
|
||||||
PRInt32* aInsertIndex,
|
|
||||||
PRInt32 aDepth);
|
|
||||||
/**
|
|
||||||
* Remove option(s) from the options[] array (called by RemoveOptionsFromList)
|
|
||||||
* @param aOptions the option or optgroup being added
|
|
||||||
* @param aListIndex the index to start removing options from the list at
|
|
||||||
* @param aNumRemoved the number removed so far [OUT]
|
|
||||||
* @param aDepth the depth of aOptions (1=direct child of select ...)
|
|
||||||
*/
|
|
||||||
nsresult RemoveOptionsFromListRecurse(nsIContent* aOptions,
|
|
||||||
PRInt32 aRemoveIndex,
|
|
||||||
PRInt32* aNumRemoved,
|
|
||||||
PRInt32 aDepth);
|
|
||||||
/**
|
|
||||||
* Find out how deep this content is from the select (1=direct child)
|
|
||||||
* @param aContent the content to check
|
|
||||||
* @return the depth
|
|
||||||
*/
|
|
||||||
PRInt32 GetContentDepth(nsIContent* aContent);
|
|
||||||
/**
|
|
||||||
* Get the index of the first option at, under or following the content in
|
|
||||||
* the select, or length of options[] if none are found
|
|
||||||
* @param aOptions the content
|
|
||||||
* @return the index of the first option
|
|
||||||
*/
|
|
||||||
PRInt32 GetOptionIndexAt(nsIContent* aOptions);
|
|
||||||
/**
|
|
||||||
* Get the next option following the content in question (not at or under)
|
|
||||||
* (this could include siblings of the current content or siblings of the
|
|
||||||
* parent or children of siblings of the parent).
|
|
||||||
* @param aOptions the content
|
|
||||||
* @return the index of the next option after the content
|
|
||||||
*/
|
|
||||||
PRInt32 GetOptionIndexAfter(nsIContent* aOptions);
|
|
||||||
/**
|
|
||||||
* Get the first option index at or under the content in question.
|
|
||||||
* @param aOptions the content
|
|
||||||
* @return the index of the first option at or under the content
|
|
||||||
*/
|
|
||||||
PRInt32 GetFirstOptionIndex(nsIContent* aOptions);
|
|
||||||
/**
|
|
||||||
* Get the first option index under the content in question, within the
|
|
||||||
* range specified.
|
|
||||||
* @param aOptions the content
|
|
||||||
* @param aStartIndex the first child to look at
|
|
||||||
* @param aEndIndex the child *after* the last child to look at
|
|
||||||
* @return the index of the first option at or under the content
|
|
||||||
*/
|
|
||||||
PRInt32 GetFirstChildOptionIndex(nsIContent* aOptions,
|
|
||||||
PRInt32 aStartIndex,
|
|
||||||
PRInt32 aEndIndex);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the frame as an nsISelectControlFrame (MAY RETURN NULL)
|
|
||||||
* @return the select frame, or null
|
|
||||||
*/
|
|
||||||
nsISelectControlFrame *GetSelectFrame();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper method for dispatching custom DOM events to our anonymous subcontent
|
|
||||||
* (for XBL form controls)
|
|
||||||
* @param aName the name of the event to dispatch
|
|
||||||
*/
|
|
||||||
void DispatchDOMEvent(const nsAString& aName);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is this a combobox?
|
|
||||||
*/
|
|
||||||
PRBool IsCombobox() {
|
|
||||||
PRBool isMultiple = PR_TRUE;
|
|
||||||
PRInt32 size = 1;
|
|
||||||
GetSize(&size);
|
|
||||||
GetMultiple(&isMultiple);
|
|
||||||
return !isMultiple && size <= 1;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
nsSafeOptionListMutation::~nsSafeOptionListMutation()
|
||||||
* Helper method for dispatching ContentReset notifications to list
|
{
|
||||||
* and combo box frames.
|
if (mSelect) {
|
||||||
*/
|
nsHTMLSelectElement* select =
|
||||||
void DispatchContentReset();
|
static_cast<nsHTMLSelectElement*>(mSelect.get());
|
||||||
|
if (mNeedsRebuild || (mTopLevelMutation && mGuard.Mutated(1))) {
|
||||||
/**
|
select->RebuildOptionsArray();
|
||||||
* Rebuilds the options array from scratch as a fallback in error cases.
|
}
|
||||||
*/
|
if (mTopLevelMutation) {
|
||||||
void RebuildOptionsArray();
|
select->mMutating = PR_FALSE;
|
||||||
|
}
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
void VerifyOptionsArray();
|
select->VerifyOptionsArray();
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
/** The options[] array */
|
}
|
||||||
nsRefPtr<nsHTMLOptionCollection> mOptions;
|
|
||||||
/** false if the parser is in the middle of adding children. */
|
|
||||||
PRPackedBool mIsDoneAddingChildren;
|
|
||||||
/** true if our disabled state has changed from the default **/
|
|
||||||
PRPackedBool mDisabledChanged;
|
|
||||||
/** The number of non-options as children of the select */
|
|
||||||
PRUint32 mNonOptionChildren;
|
|
||||||
/** The number of optgroups anywhere under the select */
|
|
||||||
PRUint32 mOptGroupCount;
|
|
||||||
/**
|
|
||||||
* The current selected index for selectedIndex (will be the first selected
|
|
||||||
* index if multiple are selected)
|
|
||||||
*/
|
|
||||||
PRInt32 mSelectedIndex;
|
|
||||||
/**
|
|
||||||
* The temporary restore state in case we try to restore before parser is
|
|
||||||
* done adding options
|
|
||||||
*/
|
|
||||||
nsRefPtr<nsSelectState> mRestoreState;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
|
@ -502,6 +138,7 @@ nsHTMLSelectElement::nsHTMLSelectElement(nsINodeInfo *aNodeInfo,
|
||||||
mOptions(new nsHTMLOptionCollection(this)),
|
mOptions(new nsHTMLOptionCollection(this)),
|
||||||
mIsDoneAddingChildren(!aFromParser),
|
mIsDoneAddingChildren(!aFromParser),
|
||||||
mDisabledChanged(PR_FALSE),
|
mDisabledChanged(PR_FALSE),
|
||||||
|
mMutating(PR_FALSE),
|
||||||
mNonOptionChildren(0),
|
mNonOptionChildren(0),
|
||||||
mOptGroupCount(0),
|
mOptGroupCount(0),
|
||||||
mSelectedIndex(-1)
|
mSelectedIndex(-1)
|
||||||
|
@ -561,39 +198,23 @@ nsHTMLSelectElement::InsertChildAt(nsIContent* aKid,
|
||||||
PRUint32 aIndex,
|
PRUint32 aIndex,
|
||||||
PRBool aNotify)
|
PRBool aNotify)
|
||||||
{
|
{
|
||||||
nsresult rv = WillAddOptions(aKid, this, aIndex);
|
nsSafeOptionListMutation safeMutation(this, this, aKid, aIndex);
|
||||||
PRBool rebuild = NS_FAILED(rv);
|
nsresult rv = nsGenericHTMLFormElement::InsertChildAt(aKid, aIndex, aNotify);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
rv = nsGenericHTMLFormElement::InsertChildAt(aKid, aIndex, aNotify);
|
safeMutation.MutationFailed();
|
||||||
if (rebuild || NS_FAILED(rv)) {
|
|
||||||
RebuildOptionsArray();
|
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
|
return rv;
|
||||||
#ifdef DEBUG
|
|
||||||
VerifyOptionsArray();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsHTMLSelectElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify)
|
nsHTMLSelectElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify)
|
||||||
{
|
{
|
||||||
nsresult rv = WillRemoveOptions(this, aIndex);
|
nsSafeOptionListMutation safeMutation(this, this, nsnull, aIndex);
|
||||||
PRBool rebuild = NS_FAILED(rv);
|
nsresult rv = nsGenericHTMLFormElement::RemoveChildAt(aIndex, aNotify);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
rv = nsGenericHTMLFormElement::RemoveChildAt(aIndex, aNotify);
|
safeMutation.MutationFailed();
|
||||||
if (rebuild || NS_FAILED(rv)) {
|
|
||||||
RebuildOptionsArray();
|
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
|
return rv;
|
||||||
#ifdef DEBUG
|
|
||||||
VerifyOptionsArray();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,496 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is Mozilla Communicator client code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* Netscape Communications Corporation.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Pierre Phaneuf <pp@ludusdesign.com>
|
||||||
|
* Mats Palmgren <mats.palmgren@bredband.net>
|
||||||
|
* Olli Pettay <Olli.Pettay@helsinki.fi>
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||||
|
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
#ifndef nsHTMLSelectElement_h___
|
||||||
|
#define nsHTMLSelectElement_h___
|
||||||
|
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
#include "nsCOMArray.h"
|
||||||
|
#include "nsGenericHTMLElement.h"
|
||||||
|
#include "nsISelectElement.h"
|
||||||
|
#include "nsIDOMHTMLSelectElement.h"
|
||||||
|
#include "nsIDOMNSHTMLSelectElement.h"
|
||||||
|
#include "nsIDOMNSXBLFormControl.h"
|
||||||
|
#include "nsIDOMHTMLFormElement.h"
|
||||||
|
#include "nsIDOMHTMLOptionElement.h"
|
||||||
|
#include "nsIDOMHTMLCollection.h"
|
||||||
|
#include "nsIDOMHTMLOptionsCollection.h"
|
||||||
|
#include "nsIDOMNSHTMLOptionCollectn.h"
|
||||||
|
#include "nsISelectControlFrame.h"
|
||||||
|
|
||||||
|
// PresState
|
||||||
|
#include "nsXPCOM.h"
|
||||||
|
#include "nsPresState.h"
|
||||||
|
#include "nsIComponentManager.h"
|
||||||
|
#include "nsCheapSets.h"
|
||||||
|
#include "nsLayoutErrors.h"
|
||||||
|
|
||||||
|
|
||||||
|
class nsHTMLSelectElement;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The collection of options in the select (what you get back when you do
|
||||||
|
* select.options in DOM)
|
||||||
|
*/
|
||||||
|
class nsHTMLOptionCollection: public nsIDOMHTMLOptionsCollection,
|
||||||
|
public nsIDOMNSHTMLOptionCollection,
|
||||||
|
public nsIDOMHTMLCollection
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
nsHTMLOptionCollection(nsHTMLSelectElement* aSelect);
|
||||||
|
virtual ~nsHTMLOptionCollection();
|
||||||
|
|
||||||
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||||
|
|
||||||
|
// nsIDOMHTMLOptionsCollection interface
|
||||||
|
NS_DECL_NSIDOMHTMLOPTIONSCOLLECTION
|
||||||
|
|
||||||
|
// nsIDOMNSHTMLOptionCollection interface
|
||||||
|
NS_DECL_NSIDOMNSHTMLOPTIONCOLLECTION
|
||||||
|
|
||||||
|
// nsIDOMHTMLCollection interface, all its methods are defined in
|
||||||
|
// nsIDOMHTMLOptionsCollection
|
||||||
|
|
||||||
|
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsHTMLOptionCollection,
|
||||||
|
nsIDOMNSHTMLOptionCollection)
|
||||||
|
|
||||||
|
// Helpers for nsHTMLSelectElement
|
||||||
|
/**
|
||||||
|
* Insert an option
|
||||||
|
* @param aOption the option to insert
|
||||||
|
* @param aIndex the index to insert at
|
||||||
|
*/
|
||||||
|
PRBool InsertOptionAt(nsIDOMHTMLOptionElement* aOption, PRInt32 aIndex)
|
||||||
|
{
|
||||||
|
return mElements.InsertObjectAt(aOption, aIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove an option
|
||||||
|
* @param aIndex the index of the option to remove
|
||||||
|
*/
|
||||||
|
void RemoveOptionAt(PRInt32 aIndex)
|
||||||
|
{
|
||||||
|
mElements.RemoveObjectAt(aIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the option at the index
|
||||||
|
* @param aIndex the index
|
||||||
|
* @param aReturn the option returned [OUT]
|
||||||
|
*/
|
||||||
|
nsIDOMHTMLOptionElement *ItemAsOption(PRInt32 aIndex)
|
||||||
|
{
|
||||||
|
return mElements.SafeObjectAt(aIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears out all options
|
||||||
|
*/
|
||||||
|
void Clear()
|
||||||
|
{
|
||||||
|
mElements.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append an option to end of array
|
||||||
|
*/
|
||||||
|
PRBool AppendOption(nsIDOMHTMLOptionElement* aOption)
|
||||||
|
{
|
||||||
|
return mElements.AppendObject(aOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Drop the reference to the select. Called during select destruction.
|
||||||
|
*/
|
||||||
|
void DropReference();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See nsISelectElement.idl for documentation on this method
|
||||||
|
*/
|
||||||
|
nsresult GetOptionIndex(nsIDOMHTMLOptionElement* aOption,
|
||||||
|
PRInt32 aStartIndex, PRBool aForward,
|
||||||
|
PRInt32* aIndex);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/** The list of options (holds strong references) */
|
||||||
|
nsCOMArray<nsIDOMHTMLOptionElement> mElements;
|
||||||
|
/** The select element that contains this array */
|
||||||
|
nsHTMLSelectElement* mSelect;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The restore state used by select
|
||||||
|
*/
|
||||||
|
class nsSelectState : public nsISupports {
|
||||||
|
public:
|
||||||
|
nsSelectState()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
virtual ~nsSelectState()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
|
||||||
|
void PutOption(PRInt32 aIndex, const nsAString& aValue)
|
||||||
|
{
|
||||||
|
// If the option is empty, store the index. If not, store the value.
|
||||||
|
if (aValue.IsEmpty()) {
|
||||||
|
mIndices.Put(aIndex);
|
||||||
|
} else {
|
||||||
|
mValues.Put(aValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PRBool ContainsOption(PRInt32 aIndex, const nsAString& aValue)
|
||||||
|
{
|
||||||
|
return mValues.Contains(aValue) || mIndices.Contains(aIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
nsCheapStringSet mValues;
|
||||||
|
nsCheapInt32Set mIndices;
|
||||||
|
};
|
||||||
|
|
||||||
|
class nsSafeOptionListMutation
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @param aSelect The select element which option list is being mutated.
|
||||||
|
* Can be null.
|
||||||
|
* @param aParent The content object which is being mutated.
|
||||||
|
* @param aKid If not null, a new child element is being inserted to
|
||||||
|
* aParent. Otherwise a child element will be removed.
|
||||||
|
* @param aIndex The index of the content object in the parent.
|
||||||
|
*/
|
||||||
|
nsSafeOptionListMutation(nsIContent* aSelect, nsIContent* aParent,
|
||||||
|
nsIContent* aKid, PRUint32 aIndex);
|
||||||
|
~nsSafeOptionListMutation();
|
||||||
|
void MutationFailed() { mNeedsRebuild = PR_TRUE; }
|
||||||
|
private:
|
||||||
|
static void* operator new(size_t) CPP_THROW_NEW { return 0; }
|
||||||
|
static void operator delete(void*, size_t) {}
|
||||||
|
/** The select element which option list is being mutated. */
|
||||||
|
nsCOMPtr<nsISelectElement> mSelect;
|
||||||
|
/** PR_TRUE if the current mutation is the first one in the stack. */
|
||||||
|
PRBool mTopLevelMutation;
|
||||||
|
/** PR_TRUE if it is known that the option list must be recreated. */
|
||||||
|
PRBool mNeedsRebuild;
|
||||||
|
/** Option list must be recreated if more than one mutation is detected. */
|
||||||
|
nsMutationGuard mGuard;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of <select>
|
||||||
|
*/
|
||||||
|
class nsHTMLSelectElement : public nsGenericHTMLFormElement,
|
||||||
|
public nsIDOMHTMLSelectElement,
|
||||||
|
public nsIDOMNSHTMLSelectElement,
|
||||||
|
public nsIDOMNSXBLFormControl,
|
||||||
|
public nsISelectElement
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
nsHTMLSelectElement(nsINodeInfo *aNodeInfo, PRBool aFromParser = PR_FALSE);
|
||||||
|
virtual ~nsHTMLSelectElement();
|
||||||
|
|
||||||
|
// nsISupports
|
||||||
|
NS_DECL_ISUPPORTS_INHERITED
|
||||||
|
|
||||||
|
// nsIDOMNode
|
||||||
|
NS_FORWARD_NSIDOMNODE(nsGenericHTMLFormElement::)
|
||||||
|
|
||||||
|
// nsIDOMElement
|
||||||
|
NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLFormElement::)
|
||||||
|
|
||||||
|
// nsIDOMHTMLElement
|
||||||
|
NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLFormElement::)
|
||||||
|
|
||||||
|
// nsIDOMHTMLSelectElement
|
||||||
|
NS_DECL_NSIDOMHTMLSELECTELEMENT
|
||||||
|
|
||||||
|
// nsIDOMNSHTMLSelectElement
|
||||||
|
NS_DECL_NSIDOMNSHTMLSELECTELEMENT
|
||||||
|
|
||||||
|
// nsIDOMNSXBLFormControl
|
||||||
|
NS_DECL_NSIDOMNSXBLFORMCONTROL
|
||||||
|
|
||||||
|
// nsIContent
|
||||||
|
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
|
||||||
|
|
||||||
|
virtual void SetFocus(nsPresContext* aPresContext);
|
||||||
|
virtual PRBool IsFocusable(PRInt32 *aTabIndex = nsnull);
|
||||||
|
virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
|
||||||
|
PRBool aNotify);
|
||||||
|
virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify);
|
||||||
|
|
||||||
|
// Overriden nsIFormControl methods
|
||||||
|
NS_IMETHOD_(PRInt32) GetType() const { return NS_FORM_SELECT; }
|
||||||
|
NS_IMETHOD Reset();
|
||||||
|
NS_IMETHOD SubmitNamesValues(nsIFormSubmission* aFormSubmission,
|
||||||
|
nsIContent* aSubmitElement);
|
||||||
|
NS_IMETHOD SaveState();
|
||||||
|
virtual PRBool RestoreState(nsPresState* aState);
|
||||||
|
|
||||||
|
// nsISelectElement
|
||||||
|
NS_DECL_NSISELECTELEMENT
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when an attribute is about to be changed
|
||||||
|
*/
|
||||||
|
virtual nsresult BeforeSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||||
|
const nsAString* aValue, PRBool aNotify);
|
||||||
|
virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
|
||||||
|
PRBool aNotify);
|
||||||
|
|
||||||
|
virtual nsresult DoneAddingChildren(PRBool aHaveNotified);
|
||||||
|
virtual PRBool IsDoneAddingChildren();
|
||||||
|
|
||||||
|
virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
|
||||||
|
nsIAtom* aAttribute,
|
||||||
|
const nsAString& aValue,
|
||||||
|
nsAttrValue& aResult);
|
||||||
|
virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
|
||||||
|
virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
|
||||||
|
PRInt32 aModType) const;
|
||||||
|
NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
|
||||||
|
|
||||||
|
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
|
||||||
|
|
||||||
|
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsHTMLSelectElement,
|
||||||
|
nsGenericHTMLFormElement)
|
||||||
|
|
||||||
|
protected:
|
||||||
|
friend class nsSafeOptionListMutation;
|
||||||
|
|
||||||
|
// Helper Methods
|
||||||
|
/**
|
||||||
|
* Check whether the option specified by the index is selected
|
||||||
|
* @param aIndex the index
|
||||||
|
* @return whether the option at the index is selected
|
||||||
|
*/
|
||||||
|
PRBool IsOptionSelectedByIndex(PRInt32 aIndex);
|
||||||
|
/**
|
||||||
|
* Starting with (and including) aStartIndex, find the first selected index
|
||||||
|
* and set mSelectedIndex to it.
|
||||||
|
* @param aStartIndex the index to start with
|
||||||
|
*/
|
||||||
|
void FindSelectedIndex(PRInt32 aStartIndex);
|
||||||
|
/**
|
||||||
|
* Select some option if possible (generally the first non-disabled option).
|
||||||
|
* @return true if something was selected, false otherwise
|
||||||
|
*/
|
||||||
|
PRBool SelectSomething();
|
||||||
|
/**
|
||||||
|
* Call SelectSomething(), but only if nothing is selected
|
||||||
|
* @see SelectSomething()
|
||||||
|
* @return true if something was selected, false otherwise
|
||||||
|
*/
|
||||||
|
PRBool CheckSelectSomething();
|
||||||
|
/**
|
||||||
|
* Called to trigger notifications of frames and fixing selected index
|
||||||
|
*
|
||||||
|
* @param aSelectFrame the frame for this content (could be null)
|
||||||
|
* @param aPresContext the current pres context
|
||||||
|
* @param aIndex the index that was selected or deselected
|
||||||
|
* @param aSelected whether the index was selected or deselected
|
||||||
|
* @param aNotify whether to notify the style system and such
|
||||||
|
*/
|
||||||
|
void OnOptionSelected(nsISelectControlFrame* aSelectFrame,
|
||||||
|
nsPresContext* aPresContext,
|
||||||
|
PRInt32 aIndex,
|
||||||
|
PRBool aSelected,
|
||||||
|
PRBool aNotify);
|
||||||
|
/**
|
||||||
|
* Restore state to a particular state string (representing the options)
|
||||||
|
* @param aNewSelected the state string to restore to
|
||||||
|
*/
|
||||||
|
void RestoreStateTo(nsSelectState* aNewSelected);
|
||||||
|
|
||||||
|
#ifdef DEBUG_john
|
||||||
|
// Don't remove these, por favor. They're very useful in debugging
|
||||||
|
nsresult PrintOptions(nsIContent* aOptions, PRInt32 tabs);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Adding options
|
||||||
|
/**
|
||||||
|
* Insert option(s) into the options[] array and perform notifications
|
||||||
|
* @param aOptions the option or optgroup being added
|
||||||
|
* @param aListIndex the index to start adding options into the list at
|
||||||
|
* @param aDepth the depth of aOptions (1=direct child of select ...)
|
||||||
|
*/
|
||||||
|
nsresult InsertOptionsIntoList(nsIContent* aOptions,
|
||||||
|
PRInt32 aListIndex,
|
||||||
|
PRInt32 aDepth);
|
||||||
|
/**
|
||||||
|
* Remove option(s) from the options[] array
|
||||||
|
* @param aOptions the option or optgroup being added
|
||||||
|
* @param aListIndex the index to start removing options from the list at
|
||||||
|
* @param aDepth the depth of aOptions (1=direct child of select ...)
|
||||||
|
*/
|
||||||
|
nsresult RemoveOptionsFromList(nsIContent* aOptions,
|
||||||
|
PRInt32 aListIndex,
|
||||||
|
PRInt32 aDepth);
|
||||||
|
/**
|
||||||
|
* Insert option(s) into the options[] array (called by InsertOptionsIntoList)
|
||||||
|
* @param aOptions the option or optgroup being added
|
||||||
|
* @param aInsertIndex the index to start adding options into the list at
|
||||||
|
* @param aDepth the depth of aOptions (1=direct child of select ...)
|
||||||
|
*/
|
||||||
|
nsresult InsertOptionsIntoListRecurse(nsIContent* aOptions,
|
||||||
|
PRInt32* aInsertIndex,
|
||||||
|
PRInt32 aDepth);
|
||||||
|
/**
|
||||||
|
* Remove option(s) from the options[] array (called by RemoveOptionsFromList)
|
||||||
|
* @param aOptions the option or optgroup being added
|
||||||
|
* @param aListIndex the index to start removing options from the list at
|
||||||
|
* @param aNumRemoved the number removed so far [OUT]
|
||||||
|
* @param aDepth the depth of aOptions (1=direct child of select ...)
|
||||||
|
*/
|
||||||
|
nsresult RemoveOptionsFromListRecurse(nsIContent* aOptions,
|
||||||
|
PRInt32 aRemoveIndex,
|
||||||
|
PRInt32* aNumRemoved,
|
||||||
|
PRInt32 aDepth);
|
||||||
|
/**
|
||||||
|
* Find out how deep this content is from the select (1=direct child)
|
||||||
|
* @param aContent the content to check
|
||||||
|
* @return the depth
|
||||||
|
*/
|
||||||
|
PRInt32 GetContentDepth(nsIContent* aContent);
|
||||||
|
/**
|
||||||
|
* Get the index of the first option at, under or following the content in
|
||||||
|
* the select, or length of options[] if none are found
|
||||||
|
* @param aOptions the content
|
||||||
|
* @return the index of the first option
|
||||||
|
*/
|
||||||
|
PRInt32 GetOptionIndexAt(nsIContent* aOptions);
|
||||||
|
/**
|
||||||
|
* Get the next option following the content in question (not at or under)
|
||||||
|
* (this could include siblings of the current content or siblings of the
|
||||||
|
* parent or children of siblings of the parent).
|
||||||
|
* @param aOptions the content
|
||||||
|
* @return the index of the next option after the content
|
||||||
|
*/
|
||||||
|
PRInt32 GetOptionIndexAfter(nsIContent* aOptions);
|
||||||
|
/**
|
||||||
|
* Get the first option index at or under the content in question.
|
||||||
|
* @param aOptions the content
|
||||||
|
* @return the index of the first option at or under the content
|
||||||
|
*/
|
||||||
|
PRInt32 GetFirstOptionIndex(nsIContent* aOptions);
|
||||||
|
/**
|
||||||
|
* Get the first option index under the content in question, within the
|
||||||
|
* range specified.
|
||||||
|
* @param aOptions the content
|
||||||
|
* @param aStartIndex the first child to look at
|
||||||
|
* @param aEndIndex the child *after* the last child to look at
|
||||||
|
* @return the index of the first option at or under the content
|
||||||
|
*/
|
||||||
|
PRInt32 GetFirstChildOptionIndex(nsIContent* aOptions,
|
||||||
|
PRInt32 aStartIndex,
|
||||||
|
PRInt32 aEndIndex);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the frame as an nsISelectControlFrame (MAY RETURN NULL)
|
||||||
|
* @return the select frame, or null
|
||||||
|
*/
|
||||||
|
nsISelectControlFrame *GetSelectFrame();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method for dispatching custom DOM events to our anonymous subcontent
|
||||||
|
* (for XBL form controls)
|
||||||
|
* @param aName the name of the event to dispatch
|
||||||
|
*/
|
||||||
|
void DispatchDOMEvent(const nsAString& aName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is this a combobox?
|
||||||
|
*/
|
||||||
|
PRBool IsCombobox() {
|
||||||
|
PRBool isMultiple = PR_TRUE;
|
||||||
|
PRInt32 size = 1;
|
||||||
|
GetSize(&size);
|
||||||
|
GetMultiple(&isMultiple);
|
||||||
|
return !isMultiple && size <= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method for dispatching ContentReset notifications to list
|
||||||
|
* and combo box frames.
|
||||||
|
*/
|
||||||
|
void DispatchContentReset();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rebuilds the options array from scratch as a fallback in error cases.
|
||||||
|
*/
|
||||||
|
void RebuildOptionsArray();
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
void VerifyOptionsArray();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** The options[] array */
|
||||||
|
nsRefPtr<nsHTMLOptionCollection> mOptions;
|
||||||
|
/** false if the parser is in the middle of adding children. */
|
||||||
|
PRPackedBool mIsDoneAddingChildren;
|
||||||
|
/** true if our disabled state has changed from the default **/
|
||||||
|
PRPackedBool mDisabledChanged;
|
||||||
|
/** true if child nodes are being added or removed.
|
||||||
|
* Used by nsSafeOptionListMutation.
|
||||||
|
*/
|
||||||
|
PRPackedBool mMutating;
|
||||||
|
/** The number of non-options as children of the select */
|
||||||
|
PRUint32 mNonOptionChildren;
|
||||||
|
/** The number of optgroups anywhere under the select */
|
||||||
|
PRUint32 mOptGroupCount;
|
||||||
|
/**
|
||||||
|
* The current selected index for selectedIndex (will be the first selected
|
||||||
|
* index if multiple are selected)
|
||||||
|
*/
|
||||||
|
PRInt32 mSelectedIndex;
|
||||||
|
/**
|
||||||
|
* The temporary restore state in case we try to restore before parser is
|
||||||
|
* done adding options
|
||||||
|
*/
|
||||||
|
nsRefPtr<nsSelectState> mRestoreState;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
Загрузка…
Ссылка в новой задаче