diff --git a/content/html/content/src/HTMLInputElement.h b/content/html/content/src/HTMLInputElement.h index 73d1bd077af7..cd2713de73fd 100644 --- a/content/html/content/src/HTMLInputElement.h +++ b/content/html/content/src/HTMLInputElement.h @@ -1321,7 +1321,7 @@ private: bool SupportsSetRangeText() const { return mType == NS_FORM_INPUT_TEXT || mType == NS_FORM_INPUT_SEARCH || mType == NS_FORM_INPUT_URL || mType == NS_FORM_INPUT_TEL || - mType == NS_FORM_INPUT_PASSWORD; + mType == NS_FORM_INPUT_PASSWORD || mType == NS_FORM_INPUT_NUMBER; } static bool MayFireChangeOnBlur(uint8_t aType) { diff --git a/content/html/content/test/forms/test_set_range_text.html b/content/html/content/test/forms/test_set_range_text.html index e505eefb5a42..af58c3c8decf 100644 --- a/content/html/content/test/forms/test_set_range_text.html +++ b/content/html/content/test/forms/test_set_range_text.html @@ -20,6 +20,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=850364 + @@ -39,7 +40,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=850364 /** Tests for Bug 850364 && Bug 918940**/ - var SupportedTypes = ["text", "search", "url", "tel", "password", "textarea"]; + var SupportedTypes = ["text", "search", "url", "tel", "password", "textarea", "number"]; var NonSupportedTypes = ["button", "submit", "image", "reset", "radio", "checkbox", "range", "file", "email"]; @@ -92,58 +93,58 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=850364 }, false); var test = " setRange(replacement), shrink"; - elem.value = "0123456789ABCDEF"; + elem.value = "0123456789123456"; elem.setSelectionRange(1, 6); - elem.setRangeText("xyz"); - is(elem.value, "0xyz6789ABCDEF", msg + test); + elem.setRangeText("999"); + is(elem.value, "09996789123456", msg + test); is(elem.selectionStart, 1, msg + test); is(elem.selectionEnd, 4, msg + test); - elem.setRangeText("mnk"); - is(elem.value, "0mnk6789ABCDEF", msg + test); + elem.setRangeText("222"); + is(elem.value, "02226789123456", msg + test); expectedNumOfSelectCalls += 3; test = " setRange(replacement), expand"; - elem.value = "0123456789ABCDEF"; + elem.value = "0123456789123456"; elem.setSelectionRange(1, 2); - elem.setRangeText("xyz"); - is(elem.value, "0xyz23456789ABCDEF", msg + test); + elem.setRangeText("999"); + is(elem.value, "099923456789123456", msg + test); is(elem.selectionStart, 1, msg + test); is(elem.selectionEnd, 4, msg + test); - elem.setRangeText("mnk"); - is(elem.value, "0mnk23456789ABCDEF", msg + test); + elem.setRangeText("222"); + is(elem.value, "022223456789123456", msg + test); expectedNumOfSelectCalls += 3; test = " setRange(replacement) pure insertion at start"; - elem.value = "0123456789ABCDEF"; + elem.value = "0123456789123456"; elem.setSelectionRange(0, 0); - elem.setRangeText("xyz"); - is(elem.value, "xyz0123456789ABCDEF", msg + test); + elem.setRangeText("999"); + is(elem.value, "9990123456789123456", msg + test); is(elem.selectionStart, 0, msg + test); is(elem.selectionEnd, 0, msg + test); - elem.setRangeText("mnk"); - is(elem.value, "mnkxyz0123456789ABCDEF", msg + test); + elem.setRangeText("222"); + is(elem.value, "2229990123456789123456", msg + test); expectedNumOfSelectCalls += 3; test = " setRange(replacement) pure insertion in the middle"; - elem.value = "0123456789ABCDEF"; + elem.value = "0123456789123456"; elem.setSelectionRange(4, 4); - elem.setRangeText("xyz"); - is(elem.value, "0123xyz456789ABCDEF", msg + test); + elem.setRangeText("999"); + is(elem.value, "0123999456789123456", msg + test); is(elem.selectionStart, 4, msg + test); is(elem.selectionEnd, 4, msg + test); - elem.setRangeText("mnk"); - is(elem.value, "0123mnkxyz456789ABCDEF", msg + test); + elem.setRangeText("222"); + is(elem.value, "0123222999456789123456", msg + test); expectedNumOfSelectCalls += 3; test = " setRange(replacement) pure insertion at the end"; - elem.value = "0123456789ABCDEF"; + elem.value = "1123456789123456"; elem.setSelectionRange(16, 16); - elem.setRangeText("xyz"); - is(elem.value, "0123456789ABCDEFxyz", msg + test); + elem.setRangeText("999"); + is(elem.value, "1123456789123456999", msg + test); is(elem.selectionStart, 16, msg + test); is(elem.selectionEnd, 16, msg + test); - elem.setRangeText("mnk"); - is(elem.value, "0123456789ABCDEFmnkxyz", msg + test); + elem.setRangeText("222"); + is(elem.value, "1123456789123456222999", msg + test); expectedNumOfSelectCalls += 3; //test SetRange(replacement, start, end, mode) with start > end @@ -155,43 +156,43 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=850364 is(opThrows, true, msg + " should throw IndexSizeError"); //test SelectionMode 'select' - elem.value = "0123456789ABCDEF"; - elem.setRangeText("xyz", 4, 9, "select"); - is(elem.value, "0123xyz9ABCDEF", msg + ".value == \"0123xyz9ABCDEF\""); + elem.value = "1023456789123456"; + elem.setRangeText("999", 4, 9, "select"); + is(elem.value, "10239999123456", msg + ".value == \"10239999123456\""); is(elem.selectionStart, 4, msg + ".selectionStart == 4, with \"select\""); is(elem.selectionEnd, 7, msg + ".selectionEnd == 7, with \"select\""); expectedNumOfSelectCalls += 1; - elem.setRangeText("pqm", 6, 25, "select"); - is(elem.value, "0123xypqm", msg + ".value == \"0123xypqm\""); + elem.setRangeText("888", 6, 25, "select"); + is(elem.value, "102399888", msg + ".value == \"102399888\""); is(elem.selectionStart, 6, msg + ".selectionStart == 6, with \"select\""); is(elem.selectionEnd, 9, msg + ".selectionEnd == 9, with \"select\""); expectedNumOfSelectCalls += 1; //test SelectionMode 'start' - elem.value = "0123456789ABCDEF"; - elem.setRangeText("xyz", 4, 9, "start"); - is(elem.value, "0123xyz9ABCDEF", msg + ".value == \"0123xyz9ABCDEF\""); + elem.value = "0123456789123456"; + elem.setRangeText("999", 4, 9, "start"); + is(elem.value, "01239999123456", msg + ".value == \"01239999123456\""); is(elem.selectionStart, 4, msg + ".selectionStart == 4, with \"start\""); is(elem.selectionEnd, 4, msg + ".selectionEnd == 4, with \"start\""); expectedNumOfSelectCalls += 1; - elem.setRangeText("pqm", 6, 25, "start"); - is(elem.value, "0123xypqm", msg + ".value == \"0123xypqm\""); + elem.setRangeText("888", 6, 25, "start"); + is(elem.value, "012399888", msg + ".value == \"012399888\""); is(elem.selectionStart, 6, msg + ".selectionStart == 6, with \"start\""); is(elem.selectionEnd, 6, msg + ".selectionEnd == 6, with \"start\""); expectedNumOfSelectCalls += 1; //test SelectionMode 'end' - elem.value = "0123456789ABCDEF"; - elem.setRangeText("xyz", 4, 9, "end"); - is(elem.value, "0123xyz9ABCDEF", msg + ".value == \"0123xyz9ABCDEF\""); + elem.value = "1023456789123456"; + elem.setRangeText("999", 4, 9, "end"); + is(elem.value, "10239999123456", msg + ".value == \"10239999123456\""); is(elem.selectionStart, 7, msg + ".selectionStart == 7, with \"end\""); is(elem.selectionEnd, 7, msg + ".selectionEnd == 7, with \"end\""); expectedNumOfSelectCalls += 1; - elem.setRangeText("pqm", 6, 25, "end"); - is(elem.value, "0123xypqm", msg + ".value == \"0123xypqm\""); + elem.setRangeText("888", 6, 25, "end"); + is(elem.value, "102399888", msg + ".value == \"102399888\""); is(elem.selectionStart, 9, msg + ".selectionStart == 9, with \"end\""); is(elem.selectionEnd, 9, msg + ".selectionEnd == 9, with \"end\""); expectedNumOfSelectCalls += 1; @@ -201,8 +202,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=850364 //subcase: selection{Start|End} > end elem.value = "0123456789"; elem.setSelectionRange(6, 9); - elem.setRangeText("Z", 1, 2, "preserve"); - is(elem.value, "0Z23456789", msg + ".value == \"0Z23456789\""); + elem.setRangeText("7", 1, 2, "preserve"); + is(elem.value, "0723456789", msg + ".value == \"0723456789\""); is(elem.selectionStart, 6, msg + ".selectionStart == 6, with \"preserve\""); is(elem.selectionEnd, 9, msg + ".selectionEnd == 9, with \"preserve\""); expectedNumOfSelectCalls += 2; @@ -210,8 +211,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=850364 //subcase: selection{Start|End} < end elem.value = "0123456789"; elem.setSelectionRange(4, 5); - elem.setRangeText("QRST", 2, 9, "preserve"); - is(elem.value, "01QRST9", msg + ".value == \"01QRST9\""); + elem.setRangeText("3456", 2, 9, "preserve"); + is(elem.value, "0134569", msg + ".value == \"0134569\""); is(elem.selectionStart, 2, msg + ".selectionStart == 2, with \"preserve\""); is(elem.selectionEnd, 6, msg + ".selectionEnd == 6, with \"preserve\""); expectedNumOfSelectCalls += 2; @@ -219,8 +220,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=850364 //subcase: selectionStart > end, selectionEnd < end elem.value = "0123456789"; elem.setSelectionRange(8, 4); - elem.setRangeText("QRST", 1, 5); - is(elem.value, "0QRST56789", msg + ".value == \"0QRST56789\""); + elem.setRangeText("3456", 1, 5); + is(elem.value, "0345656789", msg + ".value == \"0345656789\""); is(elem.selectionStart, 1, msg + ".selectionStart == 1, with \"default\""); is(elem.selectionEnd, 5, msg + ".selectionEnd == 5, with \"default\""); expectedNumOfSelectCalls += 2; @@ -228,8 +229,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=850364 //subcase: selectionStart < end, selectionEnd > end elem.value = "0123456789"; elem.setSelectionRange(4, 9); - elem.setRangeText("QRST", 2, 6); - is(elem.value, "01QRST6789", msg + ".value == \"01QRST6789\""); + elem.setRangeText("3456", 2, 6); + is(elem.value, "0134566789", msg + ".value == \"0134566789\""); is(elem.selectionStart, 2, msg + ".selectionStart == 2, with \"default\""); is(elem.selectionEnd, 9, msg + ".selectionEnd == 9, with \"default\""); expectedNumOfSelectCalls += 2; diff --git a/layout/forms/nsNumberControlFrame.cpp b/layout/forms/nsNumberControlFrame.cpp index 0caed05e1368..309fdc715f6a 100644 --- a/layout/forms/nsNumberControlFrame.cpp +++ b/layout/forms/nsNumberControlFrame.cpp @@ -42,6 +42,8 @@ NS_IMPL_FRAMEARENA_HELPERS(nsNumberControlFrame) NS_QUERYFRAME_HEAD(nsNumberControlFrame) NS_QUERYFRAME_ENTRY(nsNumberControlFrame) NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator) + NS_QUERYFRAME_ENTRY(nsITextControlFrame) + NS_QUERYFRAME_ENTRY(nsIFormControlFrame) NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame) nsNumberControlFrame::nsNumberControlFrame(nsStyleContext* aContext) @@ -254,6 +256,12 @@ nsNumberControlFrame::ContentStatesChanged(EventStates aStates) } } +nsITextControlFrame* +nsNumberControlFrame::GetTextFieldFrame() +{ + return do_QueryFrame(GetAnonTextControl()->GetPrimaryFrame()); +} + nsresult nsNumberControlFrame::MakeAnonymousElement(Element** aResult, nsTArray& aElements, @@ -407,6 +415,84 @@ nsNumberControlFrame::GetType() const return nsGkAtoms::numberControlFrame; } +NS_IMETHODIMP +nsNumberControlFrame::GetEditor(nsIEditor **aEditor) +{ + return GetTextFieldFrame()->GetEditor(aEditor); +} + +NS_IMETHODIMP +nsNumberControlFrame::SetSelectionStart(int32_t aSelectionStart) +{ + return GetTextFieldFrame()->SetSelectionStart(aSelectionStart); +} + +NS_IMETHODIMP +nsNumberControlFrame::SetSelectionEnd(int32_t aSelectionEnd) +{ + return GetTextFieldFrame()->SetSelectionEnd(aSelectionEnd); +} + +NS_IMETHODIMP +nsNumberControlFrame::SetSelectionRange(int32_t aSelectionStart, + int32_t aSelectionEnd, + SelectionDirection aDirection) +{ + return GetTextFieldFrame()->SetSelectionRange(aSelectionStart, aSelectionEnd, + aDirection); +} + +NS_IMETHODIMP +nsNumberControlFrame::GetSelectionRange(int32_t* aSelectionStart, + int32_t* aSelectionEnd, + SelectionDirection* aDirection) +{ + return GetTextFieldFrame()->GetSelectionRange(aSelectionStart, aSelectionEnd, + aDirection); +} + +NS_IMETHODIMP +nsNumberControlFrame::GetOwnedSelectionController(nsISelectionController** aSelCon) +{ + return GetTextFieldFrame()->GetOwnedSelectionController(aSelCon); +} + +nsFrameSelection* +nsNumberControlFrame::GetOwnedFrameSelection() +{ + return GetTextFieldFrame()->GetOwnedFrameSelection(); +} + +nsresult +nsNumberControlFrame::GetPhonetic(nsAString& aPhonetic) +{ + return GetTextFieldFrame()->GetPhonetic(aPhonetic); +} + +nsresult +nsNumberControlFrame::EnsureEditorInitialized() +{ + return GetTextFieldFrame()->EnsureEditorInitialized(); +} + +nsresult +nsNumberControlFrame::ScrollSelectionIntoView() +{ + return GetTextFieldFrame()->ScrollSelectionIntoView(); +} + +void +nsNumberControlFrame::SetFocus(bool aOn, bool aRepaint) +{ + GetTextFieldFrame()->SetFocus(aOn, aRepaint); +} + +nsresult +nsNumberControlFrame::SetFormProperty(nsIAtom* aName, const nsAString& aValue) +{ + return GetTextFieldFrame()->SetFormProperty(aName, aValue); +} + HTMLInputElement* nsNumberControlFrame::GetAnonTextControl() { diff --git a/layout/forms/nsNumberControlFrame.h b/layout/forms/nsNumberControlFrame.h index a29c0ce15065..c2c555bb03e4 100644 --- a/layout/forms/nsNumberControlFrame.h +++ b/layout/forms/nsNumberControlFrame.h @@ -9,6 +9,7 @@ #include "mozilla/Attributes.h" #include "nsContainerFrame.h" #include "nsIFormControlFrame.h" +#include "nsITextControlFrame.h" #include "nsIAnonymousContentCreator.h" #include "nsCOMPtr.h" @@ -27,6 +28,7 @@ class HTMLInputElement; */ class nsNumberControlFrame MOZ_FINAL : public nsContainerFrame , public nsIAnonymousContentCreator + , public nsITextControlFrame { friend nsIFrame* NS_NewNumberControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); @@ -83,6 +85,38 @@ public: ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock)); } + // nsITextControlFrame + NS_IMETHOD GetEditor(nsIEditor **aEditor) MOZ_OVERRIDE; + + NS_IMETHOD SetSelectionStart(int32_t aSelectionStart) MOZ_OVERRIDE; + NS_IMETHOD SetSelectionEnd(int32_t aSelectionEnd) MOZ_OVERRIDE; + + NS_IMETHOD SetSelectionRange(int32_t aSelectionStart, + int32_t aSelectionEnd, + SelectionDirection aDirection = eNone) MOZ_OVERRIDE; + + NS_IMETHOD GetSelectionRange(int32_t* aSelectionStart, + int32_t* aSelectionEnd, + SelectionDirection* aDirection = nullptr) MOZ_OVERRIDE; + + NS_IMETHOD GetOwnedSelectionController(nsISelectionController** aSelCon) MOZ_OVERRIDE; + virtual nsFrameSelection* GetOwnedFrameSelection() MOZ_OVERRIDE; + + virtual nsresult GetPhonetic(nsAString& aPhonetic) MOZ_OVERRIDE; + + /** + * Ensure mEditor is initialized with the proper flags and the default value. + * @throws NS_ERROR_NOT_INITIALIZED if mEditor has not been created + * @throws various and sundry other things + */ + virtual nsresult EnsureEditorInitialized() MOZ_OVERRIDE; + + virtual nsresult ScrollSelectionIntoView() MOZ_OVERRIDE; + + // nsIFormControlFrame + virtual void SetFocus(bool aOn, bool aRepaint) MOZ_OVERRIDE; + virtual nsresult SetFormProperty(nsIAtom* aName, const nsAString& aValue) MOZ_OVERRIDE; + /** * This method attempts to localizes aValue and then sets the result as the * value of our anonymous text control. It's called when our @@ -158,6 +192,7 @@ public: private: + nsITextControlFrame* GetTextFieldFrame(); nsresult MakeAnonymousElement(Element** aResult, nsTArray& aElements, nsIAtom* aTagName,