DOM: getting rid of JS_GetContextPrivate wherever possible. Use static parent links where we can. When we do need to find this info about the caller we call a function that knows how to get that info rather than inline calls to JS_GetContextPrivate. This is all required for calling DOM objects on non-DOM JSContexts as we do via xpconnect. XPConnect: basic refactoring work to disassociate wrappers from the JSContext that was active when the wrapper was constructed. This allows for calling into wrapped JS objects on the right JSContext and for proper grouping of wrapped native objects so that they can share proto objects. This also allows for better sharing of objects and lays the foundations for threadsafety and interface flattening. Also, xpconnect tests are reorganized and improved. fixes bugs: 13419, 17736, 17746, 17952, 22086 r=vidur r=mccabe r=norris r=cbegle a=chofmann git-svn-id: svn://10.0.0.236/trunk@56202 18797224-902f-48f8-a5cc-f745e15eee43
1210 lines
33 KiB
C++
1210 lines
33 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape 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/NPL/
|
|
*
|
|
* 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 Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
|
* Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*/
|
|
#include "nsCOMPtr.h"
|
|
#include "nsIDOMHTMLSelectElement.h"
|
|
#include "nsIDOMNSHTMLSelectElement.h"
|
|
#include "nsIDOMHTMLFormElement.h"
|
|
#include "nsIScriptObjectOwner.h"
|
|
#include "nsIDOMEventReceiver.h"
|
|
#include "nsIHTMLContent.h"
|
|
#include "nsGenericHTMLElement.h"
|
|
#include "nsHTMLAtoms.h"
|
|
#include "nsHTMLIIDs.h"
|
|
#include "nsIStyleContext.h"
|
|
#include "nsIMutableStyleContext.h"
|
|
#include "nsStyleConsts.h"
|
|
#include "nsIPresContext.h"
|
|
#include "nsIHTMLAttributes.h"
|
|
#include "nsIFormControl.h"
|
|
#include "nsIForm.h"
|
|
#include "nsIDOMHTMLCollection.h"
|
|
#include "nsIDOMHTMLOptionElement.h"
|
|
#include "nsIFocusableContent.h"
|
|
#include "nsIEventStateManager.h"
|
|
#include "nsGenericDOMHTMLCollection.h"
|
|
#include "nsIJSScriptObject.h"
|
|
#include "nsISelectElement.h"
|
|
#include "nsISelectControlFrame.h"
|
|
#include "nsISizeOfHandler.h"
|
|
|
|
// Notify/query select frame for selectedIndex
|
|
#include "nsIDocument.h"
|
|
#include "nsIPresShell.h"
|
|
#include "nsIFormControlFrame.h"
|
|
#include "nsIFrame.h"
|
|
|
|
static NS_DEFINE_IID(kIDOMHTMLSelectElementIID, NS_IDOMHTMLSELECTELEMENT_IID);
|
|
static NS_DEFINE_IID(kIDOMNSHTMLSelectElementIID, NS_IDOMNSHTMLSELECTELEMENT_IID);
|
|
static NS_DEFINE_IID(kIDOMHTMLOptionElementIID, NS_IDOMHTMLOPTIONELEMENT_IID);
|
|
static NS_DEFINE_IID(kIDOMHTMLFormElementIID, NS_IDOMHTMLFORMELEMENT_IID);
|
|
static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID);
|
|
static NS_DEFINE_IID(kIFormIID, NS_IFORM_IID);
|
|
static NS_DEFINE_IID(kISelectElementIID, NS_ISELECTELEMENT_IID);
|
|
static NS_DEFINE_IID(kIFormControlFrameIID, NS_IFORMCONTROLFRAME_IID);
|
|
static NS_DEFINE_IID(kIFocusableContentIID, NS_IFOCUSABLECONTENT_IID);
|
|
|
|
class nsHTMLSelectElement;
|
|
|
|
// nsOptionList
|
|
class nsOptionList : public nsGenericDOMHTMLCollection,
|
|
public nsIJSScriptObject
|
|
{
|
|
public:
|
|
nsOptionList(nsHTMLSelectElement* aSelect);
|
|
virtual ~nsOptionList();
|
|
|
|
NS_DECL_ISUPPORTS_INHERITED
|
|
|
|
// nsIDOMHTMLCollection interface
|
|
NS_DECL_IDOMHTMLCOLLECTION
|
|
|
|
// nsIJSScriptObject interface
|
|
PRBool AddProperty(JSContext *aContext, JSObject *aObj,
|
|
jsval aID, jsval *aVp);
|
|
PRBool DeleteProperty(JSContext *aContext, JSObject *aObj,
|
|
jsval aID, jsval *aVp);
|
|
PRBool GetProperty(JSContext *aContext, JSObject *aObj,
|
|
jsval aID, jsval *aVp);
|
|
PRBool SetProperty(JSContext *aContext, JSObject *aObj,
|
|
jsval aID, jsval *aVp);
|
|
PRBool EnumerateProperty(JSContext *aContext, JSObject *aObj);
|
|
PRBool Resolve(JSContext *aContext, JSObject *aObj, jsval aID);
|
|
PRBool Convert(JSContext *aContext, JSObject *aObj, jsval aID);
|
|
void Finalize(JSContext *aContext, JSObject *aObj);
|
|
|
|
void AddOption(nsIContent* aOption);
|
|
void RemoveOption(nsIContent* aOption);
|
|
PRInt32 IndexOf(nsIContent* aOption);
|
|
|
|
void Clear();
|
|
void DropReference();
|
|
|
|
void GetOptions();
|
|
|
|
private:
|
|
nsVoidArray mElements;
|
|
PRBool mDirty;
|
|
nsHTMLSelectElement* mSelect;
|
|
};
|
|
|
|
class nsHTMLSelectElement : public nsIDOMHTMLSelectElement,
|
|
public nsIDOMNSHTMLSelectElement,
|
|
public nsIScriptObjectOwner,
|
|
public nsIDOMEventReceiver,
|
|
public nsIHTMLContent,
|
|
public nsIFormControl,
|
|
public nsIFocusableContent,
|
|
public nsISelectElement
|
|
{
|
|
public:
|
|
nsHTMLSelectElement(nsIAtom* aTag);
|
|
virtual ~nsHTMLSelectElement();
|
|
|
|
// nsISupports
|
|
NS_DECL_ISUPPORTS
|
|
|
|
// nsIDOMNode
|
|
NS_IMPL_IDOMNODE_USING_GENERIC(mInner)
|
|
|
|
// nsIDOMElement
|
|
NS_IMPL_IDOMELEMENT_USING_GENERIC(mInner)
|
|
|
|
// nsIDOMHTMLElement
|
|
NS_IMPL_IDOMHTMLELEMENT_USING_GENERIC(mInner)
|
|
|
|
// nsIDOMHTMLSelectElement
|
|
NS_IMETHOD GetType(nsString& aType);
|
|
NS_IMETHOD GetSelectedIndex(PRInt32* aSelectedIndex);
|
|
NS_IMETHOD SetSelectedIndex(PRInt32 aSelectedIndex);
|
|
NS_IMETHOD GetValue(nsString& aValue);
|
|
NS_IMETHOD SetValue(const nsString& aValue);
|
|
NS_IMETHOD GetLength(PRUint32* aLength);
|
|
NS_IMETHOD GetForm(nsIDOMHTMLFormElement** aForm);
|
|
NS_IMETHOD GetOptions(nsIDOMHTMLCollection** aOptions);
|
|
NS_IMETHOD GetDisabled(PRBool* aDisabled);
|
|
NS_IMETHOD SetDisabled(PRBool aDisabled);
|
|
NS_IMETHOD GetMultiple(PRBool* aMultiple);
|
|
NS_IMETHOD SetMultiple(PRBool aMultiple);
|
|
NS_IMETHOD GetName(nsString& aName);
|
|
NS_IMETHOD SetName(const nsString& aName);
|
|
NS_IMETHOD GetSize(PRInt32* aSize);
|
|
NS_IMETHOD SetSize(PRInt32 aSize);
|
|
NS_IMETHOD GetTabIndex(PRInt32* aTabIndex);
|
|
NS_IMETHOD SetTabIndex(PRInt32 aTabIndex);
|
|
NS_IMETHOD Add(nsIDOMHTMLElement* aElement, nsIDOMHTMLElement* aBefore);
|
|
NS_IMETHOD Remove(PRInt32 aIndex);
|
|
NS_IMETHOD Blur();
|
|
NS_IMETHOD Focus();
|
|
|
|
// nsIDOMNSHTMLSelectElement
|
|
NS_IMETHOD Item(PRUint32 aIndex, nsIDOMElement** aReturn);
|
|
|
|
// nsIScriptObjectOwner
|
|
NS_IMPL_ISCRIPTOBJECTOWNER_USING_GENERIC(mInner)
|
|
|
|
// nsIDOMEventReceiver
|
|
NS_IMPL_IDOMEVENTRECEIVER_USING_GENERIC(mInner)
|
|
|
|
// nsIContent
|
|
NS_IMPL_ICONTENT_NO_SETPARENT_NO_SETDOCUMENT_USING_GENERIC(mInner)
|
|
|
|
// nsIHTMLContent
|
|
NS_IMPL_IHTMLCONTENT_USING_GENERIC(mInner)
|
|
|
|
// nsIFormControl
|
|
NS_IMETHOD SetForm(nsIDOMHTMLFormElement* aForm);
|
|
NS_IMETHOD GetType(PRInt32* aType);
|
|
NS_IMETHOD Init();
|
|
|
|
NS_IMETHOD SetFocus(nsIPresContext* aPresContext);
|
|
NS_IMETHOD RemoveFocus(nsIPresContext* aPresContext);
|
|
|
|
// nsISelectElement
|
|
NS_IMETHOD AddOption(nsIContent* aContent);
|
|
NS_IMETHOD RemoveOption(nsIContent* aContent);
|
|
NS_IMETHOD DoneAddingContent(PRBool aIsDone);
|
|
NS_IMETHOD IsDoneAddingContent(PRBool * aIsDone);
|
|
|
|
protected:
|
|
nsGenericHTMLContainerElement mInner;
|
|
nsIForm* mForm;
|
|
nsOptionList* mOptions;
|
|
PRBool mIsDoneAddingContent;
|
|
};
|
|
|
|
|
|
// nsHTMLSelectElement
|
|
|
|
// construction, destruction
|
|
|
|
nsresult
|
|
NS_NewHTMLSelectElement(nsIHTMLContent** aInstancePtrResult, nsIAtom* aTag)
|
|
{
|
|
NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
|
|
if (nsnull == aInstancePtrResult) {
|
|
return NS_ERROR_NULL_POINTER;
|
|
}
|
|
nsIHTMLContent* it = new nsHTMLSelectElement(aTag);
|
|
if (nsnull == it) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
return it->QueryInterface(kIHTMLContentIID, (void**) aInstancePtrResult);
|
|
}
|
|
|
|
|
|
nsHTMLSelectElement::nsHTMLSelectElement(nsIAtom* aTag)
|
|
{
|
|
NS_INIT_REFCNT();
|
|
mInner.Init(this, aTag);
|
|
mOptions = nsnull;
|
|
mForm = nsnull;
|
|
mIsDoneAddingContent = PR_TRUE;
|
|
}
|
|
|
|
nsHTMLSelectElement::~nsHTMLSelectElement()
|
|
{
|
|
if (nsnull != mForm) {
|
|
// prevent mForm from decrementing its ref count on us
|
|
mForm->RemoveElement(this, PR_FALSE);
|
|
NS_RELEASE(mForm);
|
|
}
|
|
if (nsnull != mOptions) {
|
|
mOptions->Clear();
|
|
mOptions->DropReference();
|
|
NS_RELEASE(mOptions);
|
|
}
|
|
}
|
|
|
|
// ISupports
|
|
|
|
NS_IMPL_ADDREF(nsHTMLSelectElement)
|
|
|
|
nsresult
|
|
nsHTMLSelectElement::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
|
{
|
|
NS_IMPL_HTML_CONTENT_QUERY_INTERFACE(aIID, aInstancePtr, this)
|
|
if (aIID.Equals(kIDOMHTMLSelectElementIID)) {
|
|
*aInstancePtr = (void*)(nsIDOMHTMLSelectElement*)this;
|
|
NS_ADDREF_THIS();
|
|
return NS_OK;
|
|
}
|
|
else if (aIID.Equals(kIDOMNSHTMLSelectElementIID)) {
|
|
*aInstancePtr = (void*)(nsIDOMNSHTMLSelectElement*)this;
|
|
NS_ADDREF_THIS();
|
|
return NS_OK;
|
|
}
|
|
else if (aIID.Equals(kIFormControlIID)) {
|
|
*aInstancePtr = (void*)(nsIFormControl*)this;
|
|
NS_ADDREF_THIS();
|
|
return NS_OK;
|
|
}
|
|
else if (aIID.Equals(kIFocusableContentIID)) {
|
|
*aInstancePtr = (void*)(nsIFocusableContent*) this;
|
|
NS_ADDREF_THIS();
|
|
return NS_OK;
|
|
}
|
|
else if (aIID.Equals(kISelectElementIID)) {
|
|
*aInstancePtr = (void*)(nsISelectElement*) this;
|
|
NS_ADDREF_THIS();
|
|
return NS_OK;
|
|
}
|
|
return NS_NOINTERFACE;
|
|
}
|
|
|
|
NS_IMETHODIMP_(nsrefcnt)
|
|
nsHTMLSelectElement::Release()
|
|
{
|
|
--mRefCnt;
|
|
NS_LOG_RELEASE(this, mRefCnt, "nsHTMLSelectElement");
|
|
if (mRefCnt <= 0) {
|
|
delete this;
|
|
return 0;
|
|
} else if ((1 == mRefCnt) && mForm) {
|
|
mRefCnt = 0;
|
|
delete this;
|
|
return 0;
|
|
} else {
|
|
return mRefCnt;
|
|
}
|
|
}
|
|
|
|
// nsIDOMHTMLSelectElement
|
|
|
|
nsresult
|
|
nsHTMLSelectElement::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
|
|
{
|
|
nsHTMLSelectElement* it = new nsHTMLSelectElement(mInner.mTag);
|
|
if (nsnull == it) {
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
mInner.CopyInnerTo(this, &it->mInner, aDeep);
|
|
return it->QueryInterface(kIDOMNodeIID, (void**) aReturn);
|
|
}
|
|
|
|
// nsIContent
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLSelectElement::SetParent(nsIContent* aParent)
|
|
{
|
|
return mInner.SetParentForFormControls(aParent, this, mForm);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLSelectElement::SetDocument(nsIDocument* aDocument, PRBool aDeep)
|
|
{
|
|
return mInner.SetDocumentForFormControls(aDocument, aDeep, this, mForm);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLSelectElement::Add(nsIDOMHTMLElement* aElement, nsIDOMHTMLElement* aBefore)
|
|
{
|
|
nsresult result;
|
|
nsIDOMNode* ret;
|
|
|
|
if (nsnull == aBefore) {
|
|
result = mInner.AppendChild(aElement, &ret);
|
|
NS_IF_RELEASE(ret);
|
|
}
|
|
else {
|
|
// Just in case we're not the parent, get the parent of the reference
|
|
// element
|
|
nsIDOMNode* parent;
|
|
|
|
result = aBefore->GetParentNode(&parent);
|
|
if (NS_SUCCEEDED(result) && (nsnull != parent)) {
|
|
result = parent->InsertBefore(aElement, aBefore, &ret);
|
|
NS_IF_RELEASE(ret);
|
|
NS_RELEASE(parent);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLSelectElement::Remove(PRInt32 aIndex)
|
|
{
|
|
nsresult result = NS_OK;
|
|
nsIDOMNode* option;
|
|
|
|
if (nsnull == mOptions) {
|
|
Init();
|
|
}
|
|
|
|
result = mOptions->Item(aIndex, &option);
|
|
if (NS_SUCCEEDED(result) && (nsnull != option)) {
|
|
nsIDOMNode* parent;
|
|
|
|
result = option->GetParentNode(&parent);
|
|
if (NS_SUCCEEDED(result) && (nsnull != parent)) {
|
|
nsIDOMNode* ret;
|
|
parent->RemoveChild(option, &ret);
|
|
NS_IF_RELEASE(ret);
|
|
NS_RELEASE(parent);
|
|
}
|
|
|
|
NS_RELEASE(option);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLSelectElement::GetForm(nsIDOMHTMLFormElement** aForm)
|
|
{
|
|
nsresult result = NS_OK;
|
|
*aForm = nsnull;
|
|
if (nsnull != mForm) {
|
|
nsIDOMHTMLFormElement* formElem = nsnull;
|
|
result = mForm->QueryInterface(kIDOMHTMLFormElementIID, (void**)&formElem);
|
|
if (NS_OK == result) {
|
|
*aForm = formElem;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLSelectElement::GetOptions(nsIDOMHTMLCollection** aValue)
|
|
{
|
|
if (nsnull == mOptions) {
|
|
Init();
|
|
}
|
|
NS_ADDREF(mOptions);
|
|
*aValue = mOptions;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLSelectElement::GetType(nsString& aType)
|
|
{
|
|
PRBool isMultiple;
|
|
nsresult result = NS_OK;
|
|
|
|
result = GetMultiple(&isMultiple);
|
|
if (NS_OK == result) {
|
|
if (isMultiple) {
|
|
aType.SetString("select-multiple");
|
|
}
|
|
else {
|
|
aType.SetString("select-one");
|
|
}
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLSelectElement::GetLength(PRUint32* aLength)
|
|
{
|
|
if (nsnull != mOptions) {
|
|
Init();
|
|
return mOptions->GetLength(aLength);
|
|
}
|
|
*aLength = 0;
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
//NS_IMPL_INT_ATTR(nsHTMLSelectElement, SelectedIndex, selectedindex)
|
|
NS_IMETHODIMP
|
|
nsHTMLSelectElement::GetSelectedIndex(PRInt32* aValue)
|
|
{
|
|
nsIFormControlFrame* formControlFrame = nsnull;
|
|
nsresult rv = nsGenericHTMLElement::GetPrimaryFrame(this, formControlFrame);
|
|
if (NS_SUCCEEDED(rv)) {
|
|
nsString value;
|
|
rv = formControlFrame->GetProperty(nsHTMLAtoms::selectedindex, value);
|
|
if (NS_SUCCEEDED(rv) && (value.Length() > 0)) {
|
|
PRInt32 retval = 0;
|
|
PRInt32 error = 0;
|
|
retval = value.ToInteger(&error, 10); // Convert to integer, base 10
|
|
if (!error) {
|
|
*aValue = retval;
|
|
} else {
|
|
rv = NS_ERROR_UNEXPECTED;
|
|
}
|
|
}
|
|
} else { // The frame hasn't been created yet. Use the options array
|
|
*aValue = -1;
|
|
// If we are a combo box, our default selectedIndex is 0, not -1;
|
|
// XXX The logic here is duplicated in
|
|
// nsCSSFrameConstructor::ConstructSelectFrame and
|
|
// nsSelectControlFrame::GetDesiredSize
|
|
PRBool isMultiple;
|
|
rv = GetMultiple(&isMultiple); // Must not be multiple
|
|
if (NS_SUCCEEDED(rv) && !isMultiple) {
|
|
PRInt32 size = 1;
|
|
rv = GetSize(&size); // Size 1 or not set
|
|
if (NS_SUCCEEDED(rv) && ((1 >= size) || (NS_CONTENT_ATTR_NOT_THERE == size))) {
|
|
*aValue = 0;
|
|
}
|
|
}
|
|
nsCOMPtr<nsIDOMHTMLCollection> options;
|
|
rv = GetOptions(getter_AddRefs(options));
|
|
if (NS_SUCCEEDED(rv) && options) {
|
|
PRUint32 numOptions;
|
|
rv = options->GetLength(&numOptions);
|
|
if (NS_SUCCEEDED(rv)) {
|
|
for (PRUint32 i = 0; i < numOptions; i++) {
|
|
nsCOMPtr<nsIDOMNode> node;
|
|
rv = options->Item(i, getter_AddRefs(node));
|
|
if (NS_SUCCEEDED(rv) && node) {
|
|
nsCOMPtr<nsIDOMHTMLOptionElement> option = do_QueryInterface(node);
|
|
if (NS_SUCCEEDED(rv) && option) {
|
|
PRBool selected;
|
|
rv = option->GetDefaultSelected(&selected); // DefaultSelected == HTML Selected
|
|
if (NS_SUCCEEDED(rv) && selected) {
|
|
*aValue = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLSelectElement::SetSelectedIndex(PRInt32 aValue)
|
|
{
|
|
nsIFormControlFrame* formControlFrame = nsnull;
|
|
if (NS_OK == nsGenericHTMLElement::GetPrimaryFrame(this, formControlFrame)) {
|
|
nsString value;
|
|
value.Append(aValue, 10);
|
|
nsIPresContext* presContext;
|
|
nsGenericHTMLElement::GetPresContext(this, &presContext);
|
|
formControlFrame->SetProperty(presContext, nsHTMLAtoms::selectedindex, value);
|
|
NS_IF_RELEASE(presContext);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
//NS_IMPL_STRING_ATTR(nsHTMLSelectElement, Value, value)
|
|
NS_IMETHODIMP
|
|
nsHTMLSelectElement::GetValue(nsString& aValue)
|
|
{
|
|
nsresult result = NS_OK;
|
|
PRInt32 selectedIndex;
|
|
|
|
result = GetSelectedIndex(&selectedIndex);
|
|
if (NS_SUCCEEDED(result)) {
|
|
nsCOMPtr<nsIDOMHTMLCollection> options;
|
|
|
|
result = GetOptions(getter_AddRefs(options));
|
|
if (NS_SUCCEEDED(result)) {
|
|
nsCOMPtr<nsIDOMNode> node;
|
|
if (selectedIndex == -1) {
|
|
selectedIndex = 0;
|
|
}
|
|
result = options->Item(selectedIndex, getter_AddRefs(node));
|
|
if (NS_SUCCEEDED(result) && node) {
|
|
nsCOMPtr<nsIDOMHTMLOptionElement> option = do_QueryInterface(node);
|
|
if (option) {
|
|
option->GetValue(aValue);
|
|
if (0 == aValue.Length()) {
|
|
option->GetLabel(aValue);
|
|
if (0 == aValue.Length()) {
|
|
option->GetText(aValue);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLSelectElement::SetValue(const nsString& aValue)
|
|
{
|
|
nsresult result = NS_OK;
|
|
nsCOMPtr<nsIDOMHTMLCollection> options;
|
|
|
|
result = GetOptions(getter_AddRefs(options));
|
|
if (NS_SUCCEEDED(result)) {
|
|
PRUint32 i, length;
|
|
options->GetLength(&length);
|
|
for(i = 0; i < length; i++) {
|
|
nsCOMPtr<nsIDOMNode> node;
|
|
result = options->Item(i, getter_AddRefs(node));
|
|
if (NS_SUCCEEDED(result) && node) {
|
|
nsCOMPtr<nsIDOMHTMLOptionElement> option = do_QueryInterface(node);
|
|
if (option) {
|
|
nsAutoString optionVal;
|
|
option->GetValue(optionVal);
|
|
if (optionVal.Equals(aValue)) {
|
|
SetSelectedIndex((PRInt32)i);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
NS_IMPL_BOOL_ATTR(nsHTMLSelectElement, Disabled, disabled)
|
|
NS_IMPL_BOOL_ATTR(nsHTMLSelectElement, Multiple, multiple)
|
|
NS_IMPL_STRING_ATTR(nsHTMLSelectElement, Name, name)
|
|
NS_IMPL_INT_ATTR(nsHTMLSelectElement, Size, size)
|
|
NS_IMPL_INT_ATTR(nsHTMLSelectElement, TabIndex, tabindex)
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLSelectElement::Blur() // XXX not tested
|
|
{
|
|
nsIFormControlFrame* formControlFrame = nsnull;
|
|
nsresult rv = nsGenericHTMLElement::GetPrimaryFrame(this, formControlFrame);
|
|
if (NS_SUCCEEDED(rv)) {
|
|
// Ask the frame to Deselect focus (i.e Blur).
|
|
formControlFrame->SetFocus(PR_FALSE, PR_TRUE);
|
|
return NS_OK;
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLSelectElement::Focus()
|
|
{
|
|
nsIFormControlFrame* formControlFrame = nsnull;
|
|
nsresult rv = nsGenericHTMLElement::GetPrimaryFrame(this, formControlFrame);
|
|
if (NS_SUCCEEDED(rv)) {
|
|
formControlFrame->SetFocus(PR_TRUE, PR_TRUE);
|
|
return NS_OK;
|
|
}
|
|
return rv;
|
|
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLSelectElement::SetFocus(nsIPresContext* aPresContext)
|
|
{
|
|
nsIEventStateManager* esm;
|
|
if (NS_OK == aPresContext->GetEventStateManager(&esm)) {
|
|
esm->SetContentState(this, NS_EVENT_STATE_FOCUS);
|
|
NS_RELEASE(esm);
|
|
}
|
|
|
|
// XXX Should focus only this presContext
|
|
Focus();
|
|
nsIFormControlFrame* formControlFrame = nsnull;
|
|
nsresult rv = nsGenericHTMLElement::GetPrimaryFrame(this, formControlFrame);
|
|
if (NS_SUCCEEDED(rv)) {
|
|
formControlFrame->ScrollIntoView(aPresContext);
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLSelectElement::RemoveFocus(nsIPresContext* aPresContext)
|
|
{
|
|
// XXX Should focus only this presContext
|
|
Blur();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLSelectElement::Item(PRUint32 aIndex, nsIDOMElement** aReturn)
|
|
{
|
|
if (!mOptions) {
|
|
Init();
|
|
}
|
|
if (mOptions) {
|
|
nsIDOMNode *node;
|
|
nsresult result = mOptions->Item(aIndex, &node);
|
|
if ((NS_OK == result) && (nsnull != node)) {
|
|
result = node->QueryInterface(kIDOMElementIID, (void **)aReturn);
|
|
NS_RELEASE(node);
|
|
}
|
|
else {
|
|
*aReturn = nsnull;
|
|
}
|
|
return result;
|
|
}
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLSelectElement::AddOption(nsIContent* aContent)
|
|
{
|
|
// When first populating the select, this will be null but that's ok
|
|
// as we will manually update the widget at frame construction time.
|
|
if (!mOptions) return NS_OK;
|
|
|
|
// Add the option to the option list.
|
|
mOptions->AddOption(aContent);
|
|
|
|
// Update the widget
|
|
nsIFormControlFrame* fcFrame = nsnull;
|
|
nsresult result = nsGenericHTMLElement::GetPrimaryFrame(this, fcFrame);
|
|
if (NS_SUCCEEDED(result) && (nsnull != fcFrame)) {
|
|
nsISelectControlFrame* selectFrame = nsnull;
|
|
result = fcFrame->QueryInterface(nsISelectControlFrame::GetIID(),(void **) &selectFrame);
|
|
if (NS_SUCCEEDED(result) && (nsnull != selectFrame)) {
|
|
nsIPresContext* presContext;
|
|
nsGenericHTMLElement::GetPresContext(this, &presContext);
|
|
result = selectFrame->AddOption(presContext, mOptions->IndexOf(aContent));
|
|
NS_IF_RELEASE(presContext);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLSelectElement::RemoveOption(nsIContent* aContent)
|
|
{
|
|
// When first populating the select, this will be null but that's ok
|
|
// as we will manually update the widget at frame construction time.
|
|
if (!mOptions) return NS_OK;
|
|
|
|
PRInt32 oldIndex = mOptions->IndexOf(aContent);
|
|
|
|
// Remove the option from the options list
|
|
mOptions->RemoveOption(aContent);
|
|
|
|
// Update the widget
|
|
nsIFormControlFrame* fcFrame = nsnull;
|
|
nsresult result = nsGenericHTMLElement::GetPrimaryFrame(this, fcFrame);
|
|
if (NS_SUCCEEDED(result) && (nsnull != fcFrame)) {
|
|
nsISelectControlFrame* selectFrame = nsnull;
|
|
result = fcFrame->QueryInterface(nsISelectControlFrame::GetIID(),(void **) &selectFrame);
|
|
if (NS_SUCCEEDED(result) && (nsnull != selectFrame)) {
|
|
// We can't get our index if we've already been replaced in the OptionList.
|
|
// If we couldn't get our index, pass -1, remove all options and recreate
|
|
// Coincidentally, IndexOf returns -1 if the option isn't found in the list
|
|
nsIPresContext* presContext;
|
|
nsGenericHTMLElement::GetPresContext(this, &presContext);
|
|
result = selectFrame->RemoveOption(presContext, oldIndex);
|
|
NS_IF_RELEASE(presContext);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLSelectElement::IsDoneAddingContent(PRBool * aIsDone)
|
|
{
|
|
*aIsDone = mIsDoneAddingContent;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLSelectElement::DoneAddingContent(PRBool aIsDone)
|
|
{
|
|
mIsDoneAddingContent = aIsDone;
|
|
nsIFormControlFrame* fcFrame = nsnull;
|
|
nsresult result = nsGenericHTMLElement::GetPrimaryFrame(this, fcFrame);
|
|
if (NS_SUCCEEDED(result) && (nsnull != fcFrame)) {
|
|
nsISelectControlFrame* selectFrame = nsnull;
|
|
result = fcFrame->QueryInterface(nsISelectControlFrame::GetIID(),(void **) &selectFrame);
|
|
if (NS_SUCCEEDED(result) && (nsnull != selectFrame)) {
|
|
result = selectFrame->DoneAddingContent(mIsDoneAddingContent);
|
|
}
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLSelectElement::StringToAttribute(nsIAtom* aAttribute,
|
|
const nsString& aValue,
|
|
nsHTMLValue& aResult)
|
|
{
|
|
if (aAttribute == nsHTMLAtoms::disabled) {
|
|
aResult.SetEmptyValue();
|
|
return NS_CONTENT_ATTR_HAS_VALUE;
|
|
}
|
|
else if (aAttribute == nsHTMLAtoms::multiple) {
|
|
aResult.SetEmptyValue();
|
|
return NS_CONTENT_ATTR_HAS_VALUE;
|
|
}
|
|
else if (aAttribute == nsHTMLAtoms::size) {
|
|
if (nsGenericHTMLElement::ParseValue(aValue, 0, aResult, eHTMLUnit_Integer)) {
|
|
return NS_CONTENT_ATTR_HAS_VALUE;
|
|
}
|
|
}
|
|
else if (aAttribute == nsHTMLAtoms::tabindex) {
|
|
if (nsGenericHTMLElement::ParseValue(aValue, 0, aResult, eHTMLUnit_Integer)) {
|
|
return NS_CONTENT_ATTR_HAS_VALUE;
|
|
}
|
|
}
|
|
return NS_CONTENT_ATTR_NOT_THERE;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLSelectElement::AttributeToString(nsIAtom* aAttribute,
|
|
const nsHTMLValue& aValue,
|
|
nsString& aResult) const
|
|
{
|
|
return mInner.AttributeToString(aAttribute, aValue, aResult);
|
|
}
|
|
|
|
static void
|
|
MapAttributesInto(const nsIHTMLMappedAttributes* aAttributes,
|
|
nsIMutableStyleContext* aContext,
|
|
nsIPresContext* aPresContext)
|
|
{
|
|
nsHTMLValue value;
|
|
|
|
aAttributes->GetAttribute(nsHTMLAtoms::align, value);
|
|
if (eHTMLUnit_Enumerated == value.GetUnit()) {
|
|
nsStyleDisplay* display = (nsStyleDisplay*)
|
|
aContext->GetMutableStyleData(eStyleStruct_Display);
|
|
nsStyleText* text = (nsStyleText*)
|
|
aContext->GetMutableStyleData(eStyleStruct_Text);
|
|
switch (value.GetIntValue()) {
|
|
case NS_STYLE_TEXT_ALIGN_LEFT:
|
|
display->mFloats = NS_STYLE_FLOAT_LEFT;
|
|
break;
|
|
case NS_STYLE_TEXT_ALIGN_RIGHT:
|
|
display->mFloats = NS_STYLE_FLOAT_RIGHT;
|
|
break;
|
|
default:
|
|
text->mVerticalAlign.SetIntValue(value.GetIntValue(), eStyleUnit_Enumerated);
|
|
break;
|
|
}
|
|
}
|
|
|
|
nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aContext, aPresContext);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLSelectElement::GetMappedAttributeImpact(const nsIAtom* aAttribute,
|
|
PRInt32& aHint) const
|
|
{
|
|
if (aAttribute == nsHTMLAtoms::multiple) {
|
|
aHint = NS_STYLE_HINT_FRAMECHANGE;
|
|
}
|
|
else if ((aAttribute == nsHTMLAtoms::align) ||
|
|
(aAttribute == nsHTMLAtoms::size)) {
|
|
aHint = NS_STYLE_HINT_REFLOW;
|
|
}
|
|
else if (! nsGenericHTMLElement::GetCommonMappedAttributesImpact(aAttribute, aHint)) {
|
|
aHint = NS_STYLE_HINT_CONTENT;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLSelectElement::GetAttributeMappingFunctions(nsMapAttributesFunc& aFontMapFunc,
|
|
nsMapAttributesFunc& aMapFunc) const
|
|
{
|
|
aFontMapFunc = nsnull;
|
|
aMapFunc = &MapAttributesInto;
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLSelectElement::HandleDOMEvent(nsIPresContext* aPresContext,
|
|
nsEvent* aEvent,
|
|
nsIDOMEvent** aDOMEvent,
|
|
PRUint32 aFlags,
|
|
nsEventStatus* aEventStatus)
|
|
{
|
|
// Do not process any DOM events if the element is disabled
|
|
PRBool disabled;
|
|
nsresult rv = GetDisabled(&disabled);
|
|
if (NS_FAILED(rv) || disabled) {
|
|
return rv;
|
|
}
|
|
|
|
return mInner.HandleDOMEvent(aPresContext, aEvent, aDOMEvent,
|
|
aFlags, aEventStatus);
|
|
}
|
|
|
|
// nsIFormControl
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLSelectElement::GetType(PRInt32* aType)
|
|
{
|
|
if (aType) {
|
|
*aType = NS_FORM_SELECT;
|
|
return NS_OK;
|
|
} else {
|
|
return NS_FORM_NOTOK;
|
|
}
|
|
}
|
|
|
|
|
|
// An important assumption is that if aForm is null, the previous mForm will not be released
|
|
// This allows nsHTMLFormElement to deal with circular references.
|
|
NS_IMETHODIMP
|
|
nsHTMLSelectElement::SetForm(nsIDOMHTMLFormElement* aForm)
|
|
{
|
|
nsresult result = NS_OK;
|
|
if (nsnull == aForm) {
|
|
mForm = nsnull;
|
|
return NS_OK;
|
|
} else {
|
|
NS_IF_RELEASE(mForm);
|
|
nsIFormControl* formControl = nsnull;
|
|
result = QueryInterface(kIFormControlIID, (void**)&formControl);
|
|
if ((NS_OK == result) && formControl) {
|
|
result = aForm->QueryInterface(kIFormIID, (void**)&mForm); // keep the ref
|
|
if ((NS_OK == result) && mForm) {
|
|
mForm->AddElement(formControl);
|
|
}
|
|
NS_RELEASE(formControl);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLSelectElement::Init()
|
|
{
|
|
if (nsnull == mOptions) {
|
|
mOptions = new nsOptionList(this);
|
|
NS_ADDREF(mOptions);
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// nsOptionList implementation
|
|
// XXX this was modified form nsHTMLFormElement.cpp. We need a base class implementation
|
|
|
|
static
|
|
void GetOptionsRecurse(nsIContent* aContent, nsVoidArray& aOptions)
|
|
{
|
|
PRInt32 numChildren;
|
|
aContent->ChildCount(numChildren);
|
|
nsIContent* child = nsnull;
|
|
nsIDOMHTMLOptionElement* option = nsnull;
|
|
for (int i = 0; i < numChildren; i++) {
|
|
aContent->ChildAt(i, child);
|
|
if (child) {
|
|
nsresult result = child->QueryInterface(kIDOMHTMLOptionElementIID, (void**)&option);
|
|
if ((NS_OK == result) && option) {
|
|
aOptions.AppendElement(option); // keep the ref count
|
|
} else {
|
|
GetOptionsRecurse(child, aOptions);
|
|
}
|
|
NS_RELEASE(child);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
nsOptionList::GetOptions()
|
|
{
|
|
Clear();
|
|
GetOptionsRecurse(mSelect, mElements);
|
|
mDirty = PR_FALSE;
|
|
}
|
|
|
|
|
|
nsOptionList::nsOptionList(nsHTMLSelectElement* aSelect)
|
|
{
|
|
mDirty = PR_TRUE;
|
|
// Do not maintain a reference counted reference. When
|
|
// the select goes away, it will let us know.
|
|
mSelect = aSelect;
|
|
}
|
|
|
|
nsOptionList::~nsOptionList()
|
|
{
|
|
DropReference();
|
|
}
|
|
|
|
void
|
|
nsOptionList::DropReference()
|
|
{
|
|
// Drop our (non ref-counted) reference
|
|
mSelect = nsnull;
|
|
}
|
|
|
|
NS_IMPL_ADDREF_INHERITED(nsOptionList, nsGenericDOMHTMLCollection)
|
|
NS_IMPL_RELEASE_INHERITED(nsOptionList, nsGenericDOMHTMLCollection)
|
|
|
|
nsresult
|
|
nsOptionList::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
|
{
|
|
if (!aInstancePtr) return NS_ERROR_NULL_POINTER;
|
|
if (aIID.Equals(kIJSScriptObjectIID)) {
|
|
*aInstancePtr = (void*)(nsIJSScriptObject*) this;
|
|
NS_ADDREF_THIS();
|
|
return NS_OK;
|
|
}
|
|
else {
|
|
return nsGenericDOMHTMLCollection::QueryInterface(aIID, aInstancePtr);
|
|
}
|
|
}
|
|
|
|
// nsIDOMHTMLCollection interface
|
|
|
|
NS_IMETHODIMP
|
|
nsOptionList::GetLength(PRUint32* aLength)
|
|
{
|
|
if (mDirty && (nsnull != mSelect)) {
|
|
GetOptions();
|
|
}
|
|
*aLength = (PRUint32)mElements.Count();
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsOptionList::Item(PRUint32 aIndex, nsIDOMNode** aReturn)
|
|
{
|
|
if (mDirty && (nsnull != mSelect)) {
|
|
GetOptions();
|
|
}
|
|
PRUint32 length = 0;
|
|
GetLength(&length);
|
|
if (aIndex >= length) {
|
|
*aReturn = nsnull;
|
|
} else {
|
|
*aReturn = (nsIDOMNode*)mElements.ElementAt(aIndex);
|
|
NS_ADDREF(*aReturn);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsOptionList::NamedItem(const nsString& aName, nsIDOMNode** aReturn)
|
|
{
|
|
if (mDirty && (nsnull != mSelect)) {
|
|
GetOptions();
|
|
}
|
|
PRUint32 count = mElements.Count();
|
|
nsresult result = NS_OK;
|
|
|
|
*aReturn = nsnull;
|
|
for (PRUint32 i = 0; i < count && *aReturn == nsnull; i++) {
|
|
nsIDOMHTMLOptionElement *option;
|
|
option = (nsIDOMHTMLOptionElement*)mElements.ElementAt(i);
|
|
if (nsnull != option) {
|
|
nsIContent *content;
|
|
|
|
result = option->QueryInterface(kIContentIID, (void **)&content);
|
|
if (NS_OK == result) {
|
|
nsAutoString name;
|
|
// XXX Should it be an EqualsIgnoreCase?
|
|
if (((content->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::name, name) == NS_CONTENT_ATTR_HAS_VALUE) &&
|
|
(aName.Equals(name))) ||
|
|
((content->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::id, name) == NS_CONTENT_ATTR_HAS_VALUE) &&
|
|
(aName.Equals(name)))) {
|
|
result = option->QueryInterface(kIDOMNodeIID, (void **)aReturn);
|
|
}
|
|
NS_RELEASE(content);
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void
|
|
nsOptionList::AddOption(nsIContent* aOption)
|
|
{
|
|
// Just mark ourselves as dirty. The next time someone
|
|
// makes a call that requires us to look at the elements
|
|
// list, we'll recompute it.
|
|
mDirty = PR_TRUE;
|
|
}
|
|
|
|
void
|
|
nsOptionList::RemoveOption(nsIContent* aOption)
|
|
{
|
|
nsIDOMHTMLOptionElement* option;
|
|
|
|
if ((nsnull != aOption) &&
|
|
NS_SUCCEEDED(aOption->QueryInterface(kIDOMHTMLOptionElementIID, (void**)&option))) {
|
|
if (mElements.RemoveElement(option)) {
|
|
nsresult result;
|
|
NS_RELEASE2(option, result);
|
|
}
|
|
NS_RELEASE(option);
|
|
}
|
|
}
|
|
|
|
PRInt32
|
|
nsOptionList::IndexOf(nsIContent* aOption)
|
|
{
|
|
nsIDOMHTMLOptionElement* option;
|
|
|
|
if (mDirty && (nsnull != mSelect)) {
|
|
GetOptions();
|
|
}
|
|
if ((nsnull != aOption) &&
|
|
NS_SUCCEEDED(aOption->QueryInterface(kIDOMHTMLOptionElementIID, (void**)&option))) {
|
|
return mElements.IndexOf(option);
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
PRBool
|
|
nsOptionList::AddProperty(JSContext *aContext,
|
|
JSObject *aObj,
|
|
jsval aID,
|
|
jsval *aVp)
|
|
{
|
|
return PR_TRUE;
|
|
}
|
|
|
|
PRBool
|
|
nsOptionList::DeleteProperty(JSContext *aContext,
|
|
JSObject *aObj,
|
|
jsval aID,
|
|
jsval *aVp)
|
|
{
|
|
return PR_TRUE;
|
|
}
|
|
|
|
PRBool
|
|
nsOptionList::GetProperty(JSContext *aContext,
|
|
JSObject *aObj,
|
|
jsval aID,
|
|
jsval *aVp)
|
|
{
|
|
return PR_TRUE;
|
|
}
|
|
|
|
PRBool
|
|
nsOptionList::SetProperty(JSContext *aContext,
|
|
JSObject *aObj,
|
|
jsval aID,
|
|
jsval *aVp)
|
|
{
|
|
// XXX How about some error reporting and error
|
|
// propogation in this method???
|
|
|
|
if (JSVAL_IS_INT(aID) && (nsnull != mSelect)) {
|
|
PRInt32 indx = JSVAL_TO_INT(aID);
|
|
nsresult result;
|
|
|
|
// Update the options list
|
|
if (mDirty) {
|
|
GetOptions();
|
|
}
|
|
|
|
PRInt32 length = mElements.Count();
|
|
|
|
// If the indx is within range
|
|
if ((indx >= 0) && (indx <= length)) {
|
|
|
|
// if the value is null, remove this option
|
|
if (JSVAL_IS_NULL(*aVp)) {
|
|
mSelect->Remove(indx);
|
|
}
|
|
else {
|
|
JSObject* jsobj = JSVAL_TO_OBJECT(*aVp);
|
|
JSClass* jsclass = JS_GetClass(aContext, jsobj);
|
|
if ((nsnull != jsclass) && (jsclass->flags & JSCLASS_HAS_PRIVATE)) {
|
|
nsISupports *supports = (nsISupports *)JS_GetPrivate(aContext, jsobj);
|
|
nsIDOMNode* option;
|
|
nsIDOMNode* parent;
|
|
nsIDOMNode* refChild;
|
|
nsIDOMNode* ret;
|
|
|
|
if (NS_OK == supports->QueryInterface(kIDOMNodeIID, (void **)&option)) {
|
|
if (indx == length) {
|
|
result = mSelect->AppendChild(option, &ret);
|
|
NS_IF_RELEASE(ret);
|
|
}
|
|
else {
|
|
refChild = (nsIDOMNode*)mElements.ElementAt(indx);
|
|
if (nsnull != refChild) {
|
|
result = refChild->GetParentNode(&parent);
|
|
if (NS_SUCCEEDED(result) && (nsnull != parent)) {
|
|
|
|
result = parent->ReplaceChild(option, refChild, &ret);
|
|
NS_IF_RELEASE(ret);
|
|
NS_RELEASE(parent);
|
|
}
|
|
}
|
|
}
|
|
NS_RELEASE(option);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return PR_TRUE;
|
|
}
|
|
|
|
PRBool
|
|
nsOptionList::EnumerateProperty(JSContext *aContext, JSObject *aObj)
|
|
{
|
|
return PR_TRUE;
|
|
}
|
|
|
|
PRBool
|
|
nsOptionList::Resolve(JSContext *aContext, JSObject *aObj, jsval aID)
|
|
{
|
|
return PR_TRUE;
|
|
}
|
|
|
|
PRBool
|
|
nsOptionList::Convert(JSContext *aContext, JSObject *aObj, jsval aID)
|
|
{
|
|
return PR_TRUE;
|
|
}
|
|
|
|
void
|
|
nsOptionList::Finalize(JSContext *aContext, JSObject *aObj)
|
|
{
|
|
}
|
|
|
|
void
|
|
nsOptionList::Clear()
|
|
{
|
|
PRUint32 numOptions = mElements.Count();
|
|
for (PRUint32 i = 0; i < numOptions; i++) {
|
|
nsIDOMHTMLOptionElement* option = (nsIDOMHTMLOptionElement*)mElements.ElementAt(i);
|
|
NS_ASSERTION(option,"option already released");
|
|
NS_RELEASE(option);
|
|
}
|
|
mElements.Clear();
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP
|
|
nsHTMLSelectElement::SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const
|
|
{
|
|
if (!aResult) return NS_ERROR_NULL_POINTER;
|
|
#ifdef DEBUG
|
|
mInner.SizeOf(aSizer, aResult, sizeof(*this));
|
|
if (mForm) {
|
|
PRBool recorded;
|
|
aSizer->RecordObject(mForm, &recorded);
|
|
if (!recorded) {
|
|
PRUint32 formSize;
|
|
mForm->SizeOf(aSizer, &formSize);
|
|
aSizer->AddSize(nsHTMLAtoms::iform, formSize);
|
|
}
|
|
}
|
|
#endif
|
|
return NS_OK;
|
|
}
|