зеркало из https://github.com/mozilla/pjs.git
Bug 388558, 'change' event isn't dispatched if user selects input field value from the autocomplete list, r=jst, sr=sicking, a=mconnor
This commit is contained in:
Родитель
743fea8d4a
Коммит
4bee858f92
|
@ -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")
|
||||
|
|
|
@ -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<nsHTMLInputElement*>(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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=388558
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 388558</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=388558">Mozilla Bug 388558</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<input type="text" id="input" onchange="++inputChange;">
|
||||
<textarea id="textarea" onchange="++textareaChange;"></textarea>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/** Test for Bug 388558 **/
|
||||
var inputChange = 0;
|
||||
var textareaChange = 0;
|
||||
|
||||
function testUserInput() {
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserWrite');
|
||||
var input = document.getElementById("input");
|
||||
var textarea = document.getElementById("textarea");
|
||||
|
||||
input.focus();
|
||||
input.QueryInterface(Components.interfaces.nsIDOMNSEditableElement).setUserInput("foo");
|
||||
input.blur();
|
||||
is(inputChange, 1, "Input element should have got one change event.");
|
||||
|
||||
input.focus();
|
||||
input.value = "bar";
|
||||
input.blur();
|
||||
is(inputChange, 1,
|
||||
"Change event dispatched when setting the value of the input element");
|
||||
|
||||
input.value = "";
|
||||
is(inputChange, 1,
|
||||
"Change event dispatched when setting the value of the input element (2).");
|
||||
|
||||
input.QueryInterface(Components.interfaces.nsIDOMNSEditableElement).setUserInput("foo");
|
||||
is(inputChange, 1,
|
||||
"Change event dispatched when input element doesn't have focus.");
|
||||
|
||||
textarea.focus();
|
||||
textarea.QueryInterface(Components.interfaces.nsIDOMNSEditableElement).setUserInput("foo");
|
||||
textarea.blur();
|
||||
is(textareaChange, 1, "Textarea element should have got one change event.");
|
||||
|
||||
textarea.focus();
|
||||
textarea.value = "bar";
|
||||
textarea.blur();
|
||||
is(textareaChange, 1,
|
||||
"Change event dispatched when setting the value of the textarea element.");
|
||||
|
||||
textarea.value = "";
|
||||
is(textareaChange, 1,
|
||||
"Change event dispatched when setting the value of the textarea element (2).");
|
||||
|
||||
textarea.QueryInterface(Components.interfaces.nsIDOMNSEditableElement).setUserInput("foo");
|
||||
is(textareaChange, 1,
|
||||
"Change event dispatched when textarea element doesn't have focus.");
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addLoadEvent(testUserInput);
|
||||
addLoadEvent(SimpleTest.finish);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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<nsIDOMNSEditableElement> editable = do_QueryInterface(mFocusedInput);
|
||||
if (editable) {
|
||||
mSuppressOnInput = PR_TRUE;
|
||||
mFocusedInput->SetValue(aTextValue);
|
||||
editable->SetUserInput(aTextValue);
|
||||
mSuppressOnInput = PR_FALSE;
|
||||
}
|
||||
return NS_OK;
|
||||
|
|
Загрузка…
Ссылка в новой задаче