summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/html/HTMLElement.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/html/HTMLElement.cpp')
-rw-r--r--Source/WebCore/html/HTMLElement.cpp155
1 files changed, 150 insertions, 5 deletions
diff --git a/Source/WebCore/html/HTMLElement.cpp b/Source/WebCore/html/HTMLElement.cpp
index 22fc2f2..b3981c8 100644
--- a/Source/WebCore/html/HTMLElement.cpp
+++ b/Source/WebCore/html/HTMLElement.cpp
@@ -124,7 +124,7 @@ bool HTMLElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry
}
if (attrName == dirAttr) {
result = hasLocalName(bdoTag) ? eBDO : eUniversal;
- return false;
+ return true;
}
return StyledElement::mapToEntry(attrName, result);
@@ -148,14 +148,18 @@ void HTMLElement::parseMappedAttribute(Attribute* attr)
} else if (attr->name() == tabindexAttr) {
indexstring = getAttribute(tabindexAttr);
int tabindex = 0;
- if (parseHTMLInteger(indexstring, tabindex)) {
+ if (!indexstring.length()) {
+ clearTabIndexExplicitly();
+ } else if (parseHTMLInteger(indexstring, tabindex)) {
// Clamp tabindex to the range of 'short' to match Firefox's behavior.
setTabIndexExplicitly(max(static_cast<int>(std::numeric_limits<short>::min()), min(tabindex, static_cast<int>(std::numeric_limits<short>::max()))));
}
} else if (attr->name() == langAttr) {
// FIXME: Implement
} else if (attr->name() == dirAttr) {
- addCSSProperty(attr, CSSPropertyDirection, attr->value());
+ if (!equalIgnoringCase(attr->value(), "auto"))
+ addCSSProperty(attr, CSSPropertyDirection, attr->value());
+ dirAttributeChanged(attr);
addCSSProperty(attr, CSSPropertyUnicodeBidi, hasLocalName(bdoTag) ? CSSValueBidiOverride : CSSValueEmbed);
} else if (attr->name() == draggableAttr) {
const AtomicString& value = attr->value();
@@ -655,7 +659,7 @@ bool HTMLElement::supportsFocus() const
bool HTMLElement::isContentEditable() const
{
- if (document()->frame() && document()->frame()->isContentEditable())
+ if (document()->inDesignMode())
return true;
// Ideally we'd call ASSERT!needsStyleRecalc()) here, but
@@ -674,7 +678,7 @@ bool HTMLElement::isContentEditable() const
bool HTMLElement::isContentRichlyEditable() const
{
- if (document()->frame() && document()->frame()->isContentEditable())
+ if (document()->inDesignMode())
return true;
if (!renderer()) {
@@ -878,6 +882,147 @@ void HTMLElement::dispatchInputEvents()
ownerForm->dispatchFormInput();
}
+static void setHasDirAutoFlagRecursively(Node* firstNode, bool flag, Node* lastNode = 0)
+{
+ firstNode->setSelfOrAncestorHasDirAutoAttribute(flag);
+
+ Node* node = firstNode->firstChild();
+
+ while (node) {
+ if (node->selfOrAncestorHasDirAutoAttribute() == flag)
+ return;
+
+ if (node->isHTMLElement() && toElement(node)->hasAttribute(dirAttr)) {
+ if (node == lastNode)
+ return;
+ node = node->traverseNextSibling(firstNode);
+ continue;
+ }
+ node->setSelfOrAncestorHasDirAutoAttribute(flag);
+ if (node == lastNode)
+ return;
+ node = node->traverseNextNode(firstNode);
+ }
+}
+
+void HTMLElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
+{
+ StyledElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
+ adjustDirectionalityIfNeededAfterChildrenChanged(beforeChange, childCountDelta);
+}
+
+TextDirection HTMLElement::directionalityIfhasDirAutoAttribute(bool& isAuto) const
+{
+ if (!(selfOrAncestorHasDirAutoAttribute() && equalIgnoringCase(getAttribute(dirAttr), "auto"))) {
+ isAuto = false;
+ return LTR;
+ }
+
+ isAuto = true;
+ return directionality();
+}
+
+TextDirection HTMLElement::directionality(Node** strongDirectionalityTextNode) const
+{
+ Node* node = firstChild();
+ while (node) {
+ // Skip bdi, script and style elements
+ if (equalIgnoringCase(node->nodeName(), "bdi") || node->hasTagName(scriptTag) || node->hasTagName(styleTag)) {
+ node = node->traverseNextSibling(this);
+ continue;
+ }
+
+ // Skip elements with valid dir attribute
+ if (node->isElementNode()) {
+ AtomicString dirAttributeValue = toElement(node)->fastGetAttribute(dirAttr);
+ if (equalIgnoringCase(dirAttributeValue, "rtl") || equalIgnoringCase(dirAttributeValue, "ltr") || equalIgnoringCase(dirAttributeValue, "auto")) {
+ node = node->traverseNextSibling(this);
+ continue;
+ }
+ }
+
+ if (node->isTextNode()) {
+ bool hasStrongDirectionality;
+ WTF::Unicode::Direction textDirection = node->textContent(true).defaultWritingDirection(&hasStrongDirectionality);
+ if (hasStrongDirectionality) {
+ if (strongDirectionalityTextNode)
+ *strongDirectionalityTextNode = node;
+ return (textDirection == WTF::Unicode::LeftToRight) ? LTR : RTL;
+ }
+ }
+ node = node->traverseNextNode(this);
+ }
+ if (strongDirectionalityTextNode)
+ *strongDirectionalityTextNode = 0;
+ return LTR;
+}
+
+void HTMLElement::dirAttributeChanged(Attribute* attribute)
+{
+ Element* parent = parentElement();
+
+ if (parent && parent->isHTMLElement() && parent->selfOrAncestorHasDirAutoAttribute())
+ toHTMLElement(parent)->adjustDirectionalityIfNeededAfterChildAttributeChanged(this);
+
+ if (equalIgnoringCase(attribute->value(), "auto"))
+ calculateAndAdjustDirectionality();
+}
+
+void HTMLElement::adjustDirectionalityIfNeededAfterChildAttributeChanged(Element* child)
+{
+ ASSERT(selfOrAncestorHasDirAutoAttribute());
+ Node* strongDirectionalityTextNode;
+ TextDirection textDirection = directionality(&strongDirectionalityTextNode);
+ setHasDirAutoFlagRecursively(child, false);
+ if (renderer() && renderer()->style() && renderer()->style()->direction() != textDirection) {
+ Element* elementToAdjust = this;
+ for (; elementToAdjust; elementToAdjust = elementToAdjust->parentElement()) {
+ if (elementToAdjust->hasAttribute(dirAttr)) {
+ elementToAdjust->setNeedsStyleRecalc();
+ return;
+ }
+ }
+ }
+}
+
+void HTMLElement::calculateAndAdjustDirectionality()
+{
+ Node* strongDirectionalityTextNode;
+ TextDirection textDirection = directionality(&strongDirectionalityTextNode);
+ setHasDirAutoFlagRecursively(this, true, strongDirectionalityTextNode);
+ if (renderer() && renderer()->style() && renderer()->style()->direction() != textDirection)
+ setNeedsStyleRecalc();
+}
+
+void HTMLElement::adjustDirectionalityIfNeededAfterChildrenChanged(Node* beforeChange, int childCountDelta)
+{
+ if ((!document() || document()->renderer()) && childCountDelta < 0) {
+ Node* node = beforeChange ? beforeChange->traverseNextSibling() : 0;
+ for (int counter = 0; node && counter < childCountDelta; counter++, node = node->traverseNextSibling()) {
+ if (node->isElementNode() && toElement(node)->hasAttribute(dirAttr))
+ continue;
+
+ setHasDirAutoFlagRecursively(node, false);
+ }
+ }
+
+ if (!selfOrAncestorHasDirAutoAttribute())
+ return;
+
+ Node* oldMarkedNode = beforeChange ? beforeChange->traverseNextSibling() : 0;
+ while (oldMarkedNode && oldMarkedNode->isHTMLElement() && toHTMLElement(oldMarkedNode)->hasAttribute(dirAttr))
+ oldMarkedNode = oldMarkedNode->traverseNextSibling(this);
+ if (oldMarkedNode)
+ setHasDirAutoFlagRecursively(oldMarkedNode, false);
+
+ for (Element* elementToAdjust = this; elementToAdjust; elementToAdjust = elementToAdjust->parentElement()) {
+ if (elementToAdjust->isHTMLElement() && elementToAdjust->hasAttribute(dirAttr)) {
+ toHTMLElement(elementToAdjust)->calculateAndAdjustDirectionality();
+ return;
+ }
+ }
+}
+
} // namespace WebCore
#ifndef NDEBUG