From 7538a22e42ca05e24599d60cc324157f4027e469 Mon Sep 17 00:00:00 2001 From: "Olli.Pettay%helsinki.fi" Date: Tue, 2 Oct 2007 16:56:11 +0000 Subject: [PATCH] Bug 388558, 'change' event isn't dispatched if user selects input field value from the autocomplete list, r=jst, sr=sicking, a=mconnor git-svn-id: svn://10.0.0.236/trunk@237085 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/content/base/src/nsGkAtomList.h | 1 + .../html/content/src/nsHTMLInputElement.cpp | 39 ++++++++-- .../content/src/nsHTMLTextAreaElement.cpp | 27 +++++-- mozilla/content/html/content/test/Makefile.in | 1 + .../html/content/test/test_bug388558.html | 78 +++++++++++++++++++ .../idl/core/nsIDOMNSEditableElement.idl | 7 +- mozilla/layout/forms/nsTextControlFrame.cpp | 11 ++- .../satchel/src/nsFormFillController.cpp | 6 +- 8 files changed, 152 insertions(+), 18 deletions(-) create mode 100644 mozilla/content/html/content/test/test_bug388558.html diff --git a/mozilla/content/base/src/nsGkAtomList.h b/mozilla/content/base/src/nsGkAtomList.h index bd520c8f31b..6aca1e5c34d 100755 --- a/mozilla/content/base/src/nsGkAtomList.h +++ b/mozilla/content/base/src/nsGkAtomList.h @@ -1159,6 +1159,7 @@ GK_ATOM(tref, "tref") GK_ATOM(tspan, "tspan") GK_ATOM(turbulence, "turbulence") GK_ATOM(unicode_bidi, "unicode-bidi") +GK_ATOM(userInput, "userInput") GK_ATOM(userSpaceOnUse, "userSpaceOnUse") GK_ATOM(view, "view") GK_ATOM(viewBox, "viewBox") diff --git a/mozilla/content/html/content/src/nsHTMLInputElement.cpp b/mozilla/content/html/content/src/nsHTMLInputElement.cpp index 47bd5b06b1b..7478845d923 100644 --- a/mozilla/content/html/content/src/nsHTMLInputElement.cpp +++ b/mozilla/content/html/content/src/nsHTMLInputElement.cpp @@ -179,7 +179,11 @@ public: NS_DECL_NSIPHONETIC // nsIDOMNSEditableElement - NS_FORWARD_NSIDOMNSEDITABLEELEMENT(nsGenericHTMLElement::) + NS_IMETHOD GetEditor(nsIEditor** aEditor) + { + return nsGenericHTMLElement::GetEditor(aEditor); + } + NS_IMETHOD SetUserInput(const nsAString& aInput); // Overriden nsIFormControl methods NS_IMETHOD_(PRInt32) GetType() const { return mType; } @@ -250,7 +254,8 @@ public: protected: // Helper method nsresult SetValueInternal(const nsAString& aValue, - nsITextControlFrame* aFrame); + nsITextControlFrame* aFrame, + PRBool aUserInput); nsresult GetSelectionRange(PRInt32* aSelectionStart, PRInt32* aSelectionEnd); @@ -444,7 +449,7 @@ nsHTMLInputElement::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const nsAutoString value; const_cast(this)->GetValue(value); // SetValueInternal handles setting the VALUE_CHANGED bit for us - it->SetValueInternal(value, nsnull); + it->SetValueInternal(value, nsnull, PR_FALSE); } break; case NS_FORM_INPUT_FILE: @@ -783,12 +788,28 @@ nsHTMLInputElement::SetValue(const nsAString& aValue) SetFileName(aValue); } else { - SetValueInternal(aValue, nsnull); + SetValueInternal(aValue, nsnull, PR_FALSE); } return NS_OK; } +NS_IMETHODIMP +nsHTMLInputElement::SetUserInput(const nsAString& aValue) +{ + if (!nsContentUtils::IsCallerTrustedForWrite()) { + return NS_ERROR_DOM_SECURITY_ERR; + } + + if (mType == NS_FORM_INPUT_FILE) + { + SetFileName(aValue); + } else { + SetValueInternal(aValue, nsnull, PR_TRUE); + } + return NS_OK; +} + NS_IMETHODIMP nsHTMLInputElement::TakeTextFrameValue(const nsAString& aValue) { @@ -883,7 +904,8 @@ nsHTMLInputElement::UpdateFileList() nsresult nsHTMLInputElement::SetValueInternal(const nsAString& aValue, - nsITextControlFrame* aFrame) + nsITextControlFrame* aFrame, + PRBool aUserInput) { NS_PRECONDITION(mType != NS_FORM_INPUT_FILE, "Don't call SetValueInternal for file inputs"); @@ -911,7 +933,8 @@ nsHTMLInputElement::SetValueInternal(const nsAString& aValue, } // If the frame owns the value, set the value in the frame if (frameOwnsValue) { - formControlFrame->SetFormProperty(nsGkAtoms::value, aValue); + formControlFrame->SetFormProperty( + aUserInput ? nsGkAtoms::userInput : nsGkAtoms::value, aValue); return NS_OK; } @@ -1978,7 +2001,7 @@ nsHTMLInputElement::ParseAttribute(PRInt32 aNamespaceID, // confuse values and filenames. However they're there for backwards // compat. SetFileName(EmptyString()); - SetValueInternal(EmptyString(), nsnull); + SetValueInternal(EmptyString(), nsnull, PR_FALSE); } else if (mType == NS_FORM_INPUT_FILE) { SetFileName(EmptyString()); } @@ -2714,7 +2737,7 @@ nsHTMLInputElement::RestoreState(nsPresState* aState) rv = aState->GetStateProperty(NS_LITERAL_STRING("v"), value); NS_ASSERTION(NS_SUCCEEDED(rv), "value restore failed!"); if (rv == NS_STATE_PROPERTY_EXISTS) { - SetValueInternal(value, nsnull); + SetValueInternal(value, nsnull, PR_FALSE); } break; } diff --git a/mozilla/content/html/content/src/nsHTMLTextAreaElement.cpp b/mozilla/content/html/content/src/nsHTMLTextAreaElement.cpp index e153e8840d1..d2a8492899b 100644 --- a/mozilla/content/html/content/src/nsHTMLTextAreaElement.cpp +++ b/mozilla/content/html/content/src/nsHTMLTextAreaElement.cpp @@ -74,6 +74,7 @@ #include "nsLayoutUtils.h" #include "nsLayoutErrors.h" #include "nsStubMutationObserver.h" +#include "nsDOMError.h" static NS_DEFINE_CID(kXULControllersCID, NS_XULCONTROLLERS_CID); @@ -109,7 +110,11 @@ public: NS_DECL_NSIDOMNSHTMLTEXTAREAELEMENT // nsIDOMNSEditableElement - NS_FORWARD_NSIDOMNSEDITABLEELEMENT(nsGenericHTMLElement::) + NS_IMETHOD GetEditor(nsIEditor** aEditor) + { + return nsGenericHTMLElement::GetEditor(aEditor); + } + NS_IMETHOD SetUserInput(const nsAString& aInput); // nsIFormControl NS_IMETHOD_(PRInt32) GetType() const { return NS_FORM_TEXTAREA; } @@ -198,7 +203,8 @@ protected: void GetValueInternal(nsAString& aValue, PRBool aIgnoreWrap); nsresult SetValueInternal(const nsAString& aValue, - nsITextControlFrame* aFrame); + nsITextControlFrame* aFrame, + PRBool aUserInput); nsresult GetSelectionRange(PRInt32* aSelectionStart, PRInt32* aSelectionEnd); /** @@ -479,7 +485,8 @@ nsHTMLTextAreaElement::TakeTextFrameValue(const nsAString& aValue) nsresult nsHTMLTextAreaElement::SetValueInternal(const nsAString& aValue, - nsITextControlFrame* aFrame) + nsITextControlFrame* aFrame, + PRBool aUserInput) { nsITextControlFrame* textControlFrame = aFrame; nsIFormControlFrame* formControlFrame = textControlFrame; @@ -498,7 +505,8 @@ nsHTMLTextAreaElement::SetValueInternal(const nsAString& aValue, textControlFrame->OwnsValue(&frameOwnsValue); } if (frameOwnsValue) { - formControlFrame->SetFormProperty(nsGkAtoms::value, aValue); + formControlFrame->SetFormProperty( + aUserInput ? nsGkAtoms::userInput : nsGkAtoms::value, aValue); } else { if (mValue) { @@ -516,9 +524,18 @@ nsHTMLTextAreaElement::SetValueInternal(const nsAString& aValue, NS_IMETHODIMP nsHTMLTextAreaElement::SetValue(const nsAString& aValue) { - return SetValueInternal(aValue, nsnull); + return SetValueInternal(aValue, nsnull, PR_FALSE); } +NS_IMETHODIMP +nsHTMLTextAreaElement::SetUserInput(const nsAString& aValue) +{ + if (!nsContentUtils::IsCallerTrustedForWrite()) { + return NS_ERROR_DOM_SECURITY_ERR; + } + SetValueInternal(aValue, nsnull, PR_TRUE); + return NS_OK; +} NS_IMETHODIMP nsHTMLTextAreaElement::SetValueChanged(PRBool aValueChanged) diff --git a/mozilla/content/html/content/test/Makefile.in b/mozilla/content/html/content/test/Makefile.in index c98acd1a943..16740b80c3f 100644 --- a/mozilla/content/html/content/test/Makefile.in +++ b/mozilla/content/html/content/test/Makefile.in @@ -79,6 +79,7 @@ _TEST_FILES = test_bug589.html \ test_bug332893-2.html \ test_bug332893-3.html \ test_bug332893-4.html \ + test_bug388558.html \ test_bug332893-5.html \ test_bug332893-6.html \ test_bug353415-1.html \ diff --git a/mozilla/content/html/content/test/test_bug388558.html b/mozilla/content/html/content/test/test_bug388558.html new file mode 100644 index 00000000000..7c48ecb0ed5 --- /dev/null +++ b/mozilla/content/html/content/test/test_bug388558.html @@ -0,0 +1,78 @@ + + + + + Test for Bug 388558 + + + + + +Mozilla Bug 388558 +

+
+ + +
+
+
+
+ + + diff --git a/mozilla/dom/public/idl/core/nsIDOMNSEditableElement.idl b/mozilla/dom/public/idl/core/nsIDOMNSEditableElement.idl index 20cc2918da6..56898907ce8 100644 --- a/mozilla/dom/public/idl/core/nsIDOMNSEditableElement.idl +++ b/mozilla/dom/public/idl/core/nsIDOMNSEditableElement.idl @@ -45,8 +45,13 @@ interface nsIEditor; * such as HTML input and textarea. */ -[scriptable, uuid(c4a71f8e-82ba-49d7-94f9-beb359361072)] +[scriptable, uuid(b33eb56c-3120-418c-892b-774b00c7dde8)] interface nsIDOMNSEditableElement : nsISupports { readonly attribute nsIEditor editor; + // This is similar to set .value on nsIDOMInput/TextAreaElements, but + // handling of the value change is closer to the normal user input, so + // 'change' event for example will be dispatched when focusing out the + // element. + void setUserInput(in DOMString input); }; diff --git a/mozilla/layout/forms/nsTextControlFrame.cpp b/mozilla/layout/forms/nsTextControlFrame.cpp index 94669bf8ab0..097a95d2945 100644 --- a/mozilla/layout/forms/nsTextControlFrame.cpp +++ b/mozilla/layout/forms/nsTextControlFrame.cpp @@ -1942,15 +1942,22 @@ nsresult nsTextControlFrame::SetFormProperty(nsIAtom* aName, const nsAString& aV if (!mIsProcessing)//some kind of lock. { mIsProcessing = PR_TRUE; - - if (nsGkAtoms::value == aName) + PRBool isUserInput = (nsGkAtoms::userInput == aName); + if (nsGkAtoms::value == aName || isUserInput) { + PRBool fireChangeEvent = GetFireChangeEventState(); + if (isUserInput) { + SetFireChangeEventState(PR_TRUE); + } if (mEditor && mUseEditor) { // If the editor exists, the control needs to be informed that the value // has changed. SetValueChanged(PR_TRUE); } nsresult rv = SetValue(aValue); // set new text value + if (isUserInput) { + SetFireChangeEventState(fireChangeEvent); + } NS_ENSURE_SUCCESS(rv, rv); } else if (nsGkAtoms::select == aName) diff --git a/mozilla/toolkit/components/satchel/src/nsFormFillController.cpp b/mozilla/toolkit/components/satchel/src/nsFormFillController.cpp index 71781ad3d80..142d2a904e6 100644 --- a/mozilla/toolkit/components/satchel/src/nsFormFillController.cpp +++ b/mozilla/toolkit/components/satchel/src/nsFormFillController.cpp @@ -74,6 +74,7 @@ #include "nsIGenericFactory.h" #include "nsToolkitCompsCID.h" #include "nsEmbedCID.h" +#include "nsIDOMNSEditableElement.h" NS_INTERFACE_MAP_BEGIN(nsFormFillController) NS_INTERFACE_MAP_ENTRY(nsIFormFillController) @@ -397,9 +398,10 @@ nsFormFillController::GetTextValue(nsAString & aTextValue) NS_IMETHODIMP nsFormFillController::SetTextValue(const nsAString & aTextValue) { - if (mFocusedInput) { + nsCOMPtr editable = do_QueryInterface(mFocusedInput); + if (editable) { mSuppressOnInput = PR_TRUE; - mFocusedInput->SetValue(aTextValue); + editable->SetUserInput(aTextValue); mSuppressOnInput = PR_FALSE; } return NS_OK;