Index: Source/core/dom/Element.cpp |
diff --git a/Source/core/dom/Element.cpp b/Source/core/dom/Element.cpp |
index 722b45b513d6876403d5cbad97d915c78e29c4cc..6b05bcca642b155358f9310c3885ae273b713265 100644 |
--- a/Source/core/dom/Element.cpp |
+++ b/Source/core/dom/Element.cpp |
@@ -211,13 +211,20 @@ void Element::clearElementFlag(ElementFlags mask) |
void Element::clearTabIndexExplicitlyIfNeeded() |
{ |
- if (hasRareData()) |
+ if (hasRareData()) { |
elementRareData()->clearTabIndexExplicitly(); |
+ // As tabindex is removed, unless there is an tabstop attribute, |
+ // revert tabstop to default to match tabindex at this point (0). |
+ if (!fastHasAttribute(tabstopAttr)) |
+ setTabStopInternal(true); |
+ } |
} |
void Element::setTabIndexExplicitly(short tabIndex) |
{ |
ensureElementRareData().setTabIndexExplicitly(tabIndex); |
+ if (!fastHasAttribute(tabstopAttr)) |
+ setTabStopInternal(tabIndex >= 0); |
} |
void Element::setTabIndex(int value) |
@@ -2092,6 +2099,26 @@ void Element::parseAttribute(const QualifiedName& name, const AtomicString& valu |
// Clamp tabindex to the range of 'short' to match Firefox's behavior. |
setTabIndexExplicitly(max(static_cast<int>(std::numeric_limits<short>::min()), std::min(tabindex, static_cast<int>(std::numeric_limits<short>::max())))); |
} |
+ } else if (RuntimeEnabledFeatures::tabStopAttributeEnabled() && name == tabstopAttr) { |
+ if (!hasAttribute(tabstopAttr)) { |
+ // tabstop attribute removed. |
+ clearElementFlag(TabStopWasSetExplicitly); |
+ setTabStopInternal(tabIndex() >= 0); |
+ } else { |
+ // Treat empty attribute as true. |
+ if (equalIgnoringCase(value, "true") || equalIgnoringCase(value, "")) { |
+ setTabStopInternal(true); |
+ setElementFlag(TabStopWasSetExplicitly, true); |
+ } else if (equalIgnoringCase(value, "false")) { |
+ setTabStopInternal(false); |
+ setElementFlag(TabStopWasSetExplicitly, true); |
+ } else { |
+ // When value is other than "true", "false", "", the value is ignored and |
+ // falls back the default state. |
+ clearElementFlag(TabStopWasSetExplicitly); |
+ setTabStopInternal(tabIndex() >= 0); |
+ } |
+ } |
} |
} |
@@ -2334,12 +2361,21 @@ bool Element::isMouseFocusable() const |
bool Element::tabStop() const |
{ |
- // Any element which never supports focus will always return false. |
- return supportsFocus() && (hasRareData() ? elementRareData()->tabStop() : true); |
+ if (hasElementFlag(TabStopWasSetExplicitly)) |
+ return elementRareData()->tabStop(); |
+ return tabIndex() >= 0; |
} |
void Element::setTabStop(bool flag) |
{ |
+ // Reflect the value in the HTML attribute. Note that we cannot use setBooleanAttribute() |
+ // because the tabstop attribute is an enumerated attribute. |
+ // After tabstop attribute is set, the property value is modified accordingly. |
+ setAttribute(tabstopAttr, flag ? "true" : "false"); |
+} |
+ |
+void Element::setTabStopInternal(bool flag) |
+{ |
ensureElementRareData().setTabStop(flag); |
focusStateChanged(); |
} |