Bug 943047 - Stop <input type=number> from taking focus twice, and enable tabbing backwards through focusable items. r=smaug

This commit is contained in:
Jonathan Watt
2013-12-01 13:49:10 +00:00
parent 4511337a91
commit ca4e493fa4
5 changed files with 58 additions and 7 deletions

View File

@@ -21,7 +21,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=238987
var shouldStop = false;
var modifier = 0;
var expectedResult = "i1,i2,i3,i4,i5,i6,i7,i8,i9,i10,i11,i12";
var expectedResult = "i1,i2,i3,i4,i5,i6,i7,i8,number,i9,i10,i11,i12";
var forwardFocusArray = expectedResult.split(",");
var backwardFocusArray = expectedResult.split(",");
var forwardBlurArray = expectedResult.split(",");
@@ -202,6 +202,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=238987
<tr>
<td>type="file"</td><td><input type="file" id="i8"></td>
</tr>
<tr>
<td>type="number"</td><td><input type="number" id="number"></td>
</tr>
<tr>
<td>button</td><td><button id="i9">button</button></td>
</tr>

View File

@@ -3295,6 +3295,15 @@ HTMLInputElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
// nsIFormControlFrame::SetFocus, we handle focus here.
nsIFrame* frame = GetPrimaryFrame();
if (frame) {
if (aVisitor.mEvent->message == NS_FOCUS_CONTENT) {
// Tell our frame it's getting focus so that it can make sure focus
// is moved to our anonymous text control.
nsNumberControlFrame* numberControlFrame =
do_QueryFrame(GetPrimaryFrame());
if (numberControlFrame) {
numberControlFrame->HandleFocusEvent(aVisitor.mEvent);
}
}
frame->InvalidateFrameSubtree();
}
}
@@ -5758,8 +5767,7 @@ HTMLInputElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, int32_t*
}
if (IsSingleLineTextControl(false) ||
mType == NS_FORM_INPUT_RANGE ||
mType == NS_FORM_INPUT_NUMBER) {
mType == NS_FORM_INPUT_RANGE) {
*aIsFocusable = true;
return false;
}
@@ -5770,11 +5778,17 @@ HTMLInputElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, int32_t*
const bool defaultFocusable = true;
#endif
if (mType == NS_FORM_INPUT_FILE) {
if (mType == NS_FORM_INPUT_FILE ||
mType == NS_FORM_INPUT_NUMBER) {
if (aTabIndex) {
// We only want our native anonymous child to be tabable to, not ourself.
*aTabIndex = -1;
}
*aIsFocusable = defaultFocusable;
if (mType == NS_FORM_INPUT_NUMBER) {
*aIsFocusable = true;
} else {
*aIsFocusable = defaultFocusable;
}
return true;
}

View File

@@ -149,6 +149,12 @@ var focusableElements = [
"<input type=\"text\" tabindex=\"1\">",
"<input type=\"text\" contenteditable=\"true\">",
"<input type=\"number\">",
"<input type=\"number\" tabindex=\"-1\">",
"<input type=\"number\" tabindex=\"0\">",
"<input type=\"number\" tabindex=\"1\">",
"<input type=\"number\" contenteditable=\"true\">",
"<object tabindex=\"-1\"></object>",
"<object tabindex=\"0\"></object>",
"<object tabindex=\"1\"></object>",
@@ -371,6 +377,12 @@ var focusableInContentEditable = [
"<input type=\"text\" tabindex=\"1\">",
"<input type=\"text\" contenteditable=\"true\">",
"<input type=\"number\">",
"<input type=\"number\" tabindex=\"-1\">",
"<input type=\"number\" tabindex=\"0\">",
"<input type=\"number\" tabindex=\"1\">",
"<input type=\"number\" contenteditable=\"true\">",
"<object tabindex=\"-1\"></object>",
"<object tabindex=\"0\"></object>",
"<object tabindex=\"1\"></object>",

View File

@@ -156,7 +156,8 @@ nsNumberControlFrame::AttributeChanged(int32_t aNameSpaceID,
{
if (aNameSpaceID == kNameSpaceID_None) {
if (aAttribute == nsGkAtoms::placeholder ||
aAttribute == nsGkAtoms::readonly) {
aAttribute == nsGkAtoms::readonly ||
aAttribute == nsGkAtoms::tabindex) {
if (aModType == nsIDOMMutationEvent::REMOVAL) {
mTextField->UnsetAttr(aNameSpaceID, aAttribute, true);
} else {
@@ -252,9 +253,12 @@ nsNumberControlFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
mTextField->SetAttr(kNameSpaceID_None, nsGkAtoms::type,
NS_LITERAL_STRING("text"), PR_FALSE);
HTMLInputElement* content = HTMLInputElement::FromContent(mContent);
HTMLInputElement* textField = HTMLInputElement::FromContent(mTextField);
// Initialize the text field value:
nsAutoString value;
HTMLInputElement::FromContent(mContent)->GetValue(value);
content->GetValue(value);
mTextField->SetAttr(kNameSpaceID_None, nsGkAtoms::value, value, false);
// If we're readonly, make sure our anonymous text control is too:
@@ -263,6 +267,11 @@ nsNumberControlFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
mTextField->SetAttr(kNameSpaceID_None, nsGkAtoms::readonly, readonly, false);
}
// Propogate our tabindex:
int32_t tabIndex;
content->GetTabIndex(&tabIndex);
textField->SetTabIndex(tabIndex);
// Initialize the text field's placeholder, if ours is set:
nsAutoString placeholder;
if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::placeholder, placeholder)) {
@@ -331,6 +340,15 @@ nsNumberControlFrame::GetSpinButtonForPointerEvent(WidgetGUIEvent* aEvent) const
return eSpinButtonNone;
}
void
nsNumberControlFrame::HandleFocusEvent(WidgetEvent* aEvent)
{
if (aEvent->originalTarget != mTextField) {
// Move focus to our text field
HTMLInputElement::FromContent(mTextField)->Focus();
}
}
void
nsNumberControlFrame::AppendAnonymousContentTo(nsBaseContentList& aElements,
uint32_t aFilter)

View File

@@ -14,6 +14,7 @@
class nsPresContext;
namespace mozilla {
class WidgetEvent;
class WidgetGUIEvent;
namespace dom {
class HTMLInputElement;
@@ -30,6 +31,7 @@ class nsNumberControlFrame MOZ_FINAL : public nsContainerFrame
NS_NewNumberControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
typedef mozilla::dom::HTMLInputElement HTMLInputElement;
typedef mozilla::WidgetEvent WidgetEvent;
typedef mozilla::WidgetGUIEvent WidgetGUIEvent;
nsNumberControlFrame(nsStyleContext* aContext);
@@ -101,6 +103,8 @@ public:
*/
int32_t GetSpinButtonForPointerEvent(WidgetGUIEvent* aEvent) const;
void HandleFocusEvent(WidgetEvent* aEvent);
private:
nsresult MakeAnonymousElement(nsIContent** aResult,