| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
| 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
| 4 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. | 4 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. |
| 5 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmo
bile.com/) | 5 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmo
bile.com/) |
| 6 * Copyright (C) 2011 Motorola Mobility. All rights reserved. | 6 * Copyright (C) 2011 Motorola Mobility. All rights reserved. |
| 7 * | 7 * |
| 8 * This library is free software; you can redistribute it and/or | 8 * This library is free software; you can redistribute it and/or |
| 9 * modify it under the terms of the GNU Library General Public | 9 * modify it under the terms of the GNU Library General Public |
| 10 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 67 PassRefPtr<HTMLElement> HTMLElement::create(const QualifiedName& tagName, Docume
nt* document) | 67 PassRefPtr<HTMLElement> HTMLElement::create(const QualifiedName& tagName, Docume
nt* document) |
| 68 { | 68 { |
| 69 return adoptRef(new HTMLElement(tagName, document)); | 69 return adoptRef(new HTMLElement(tagName, document)); |
| 70 } | 70 } |
| 71 | 71 |
| 72 String HTMLElement::nodeName() const | 72 String HTMLElement::nodeName() const |
| 73 { | 73 { |
| 74 // FIXME: Would be nice to have an atomicstring lookup based off uppercase | 74 // FIXME: Would be nice to have an atomicstring lookup based off uppercase |
| 75 // chars that does not have to copy the string on a hit in the hash. | 75 // chars that does not have to copy the string on a hit in the hash. |
| 76 // FIXME: We should have a way to detect XHTML elements and replace the hasP
refix() check with it. | 76 // FIXME: We should have a way to detect XHTML elements and replace the hasP
refix() check with it. |
| 77 if (document()->isHTMLDocument() && !tagQName().hasPrefix()) | 77 if (document().isHTMLDocument() && !tagQName().hasPrefix()) |
| 78 return tagQName().localNameUpper(); | 78 return tagQName().localNameUpper(); |
| 79 return Element::nodeName(); | 79 return Element::nodeName(); |
| 80 } | 80 } |
| 81 | 81 |
| 82 bool HTMLElement::ieForbidsInsertHTML() const | 82 bool HTMLElement::ieForbidsInsertHTML() const |
| 83 { | 83 { |
| 84 // FIXME: Supposedly IE disallows settting innerHTML, outerHTML | 84 // FIXME: Supposedly IE disallows settting innerHTML, outerHTML |
| 85 // and createContextualFragment on these tags. We have no tests to | 85 // and createContextualFragment on these tags. We have no tests to |
| 86 // verify this however, so this list could be totally wrong. | 86 // verify this however, so this list could be totally wrong. |
| 87 // This list was moved from the previous endTagRequirement() implementation. | 87 // This list was moved from the previous endTagRequirement() implementation. |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 288 | 288 |
| 289 if (name == dirAttr) | 289 if (name == dirAttr) |
| 290 dirAttributeChanged(value); | 290 dirAttributeChanged(value); |
| 291 else if (name == tabindexAttr) { | 291 else if (name == tabindexAttr) { |
| 292 int tabindex = 0; | 292 int tabindex = 0; |
| 293 if (value.isEmpty()) { | 293 if (value.isEmpty()) { |
| 294 clearTabIndexExplicitlyIfNeeded(); | 294 clearTabIndexExplicitlyIfNeeded(); |
| 295 if (treeScope()->adjustedFocusedElement() == this) { | 295 if (treeScope()->adjustedFocusedElement() == this) { |
| 296 // We might want to call blur(), but it's dangerous to dispatch | 296 // We might want to call blur(), but it's dangerous to dispatch |
| 297 // events here. | 297 // events here. |
| 298 document()->setNeedsFocusedElementCheck(); | 298 document().setNeedsFocusedElementCheck(); |
| 299 } | 299 } |
| 300 } else if (parseHTMLInteger(value, tabindex)) { | 300 } else if (parseHTMLInteger(value, tabindex)) { |
| 301 // Clamp tabindex to the range of 'short' to match Firefox's behavio
r. | 301 // Clamp tabindex to the range of 'short' to match Firefox's behavio
r. |
| 302 setTabIndexExplicitly(max(static_cast<int>(std::numeric_limits<short
>::min()), min(tabindex, static_cast<int>(std::numeric_limits<short>::max())))); | 302 setTabIndexExplicitly(max(static_cast<int>(std::numeric_limits<short
>::min()), min(tabindex, static_cast<int>(std::numeric_limits<short>::max())))); |
| 303 } | 303 } |
| 304 } else { | 304 } else { |
| 305 AtomicString eventName = eventNameForAttributeName(name); | 305 AtomicString eventName = eventNameForAttributeName(name); |
| 306 if (!eventName.isNull()) | 306 if (!eventName.isNull()) |
| 307 setAttributeEventListener(eventName, createAttributeEventListener(th
is, name, value)); | 307 setAttributeEventListener(eventName, createAttributeEventListener(th
is, name, value)); |
| 308 } | 308 } |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 361 RefPtr<Node> node = next ? next->previousSibling() : 0; | 361 RefPtr<Node> node = next ? next->previousSibling() : 0; |
| 362 if (!es.hadException() && node && node->isTextNode()) | 362 if (!es.hadException() && node && node->isTextNode()) |
| 363 mergeWithNextTextNode(node.release(), es); | 363 mergeWithNextTextNode(node.release(), es); |
| 364 | 364 |
| 365 if (!es.hadException() && prev && prev->isTextNode()) | 365 if (!es.hadException() && prev && prev->isTextNode()) |
| 366 mergeWithNextTextNode(prev.release(), es); | 366 mergeWithNextTextNode(prev.release(), es); |
| 367 } | 367 } |
| 368 | 368 |
| 369 PassRefPtr<DocumentFragment> HTMLElement::textToFragment(const String& text, Exc
eptionState& es) | 369 PassRefPtr<DocumentFragment> HTMLElement::textToFragment(const String& text, Exc
eptionState& es) |
| 370 { | 370 { |
| 371 RefPtr<DocumentFragment> fragment = DocumentFragment::create(document()); | 371 RefPtr<DocumentFragment> fragment = DocumentFragment::create(&document()); |
| 372 unsigned int i, length = text.length(); | 372 unsigned int i, length = text.length(); |
| 373 UChar c = 0; | 373 UChar c = 0; |
| 374 for (unsigned int start = 0; start < length; ) { | 374 for (unsigned int start = 0; start < length; ) { |
| 375 | 375 |
| 376 // Find next line break. | 376 // Find next line break. |
| 377 for (i = start; i < length; i++) { | 377 for (i = start; i < length; i++) { |
| 378 c = text[i]; | 378 c = text[i]; |
| 379 if (c == '\r' || c == '\n') | 379 if (c == '\r' || c == '\n') |
| 380 break; | 380 break; |
| 381 } | 381 } |
| 382 | 382 |
| 383 fragment->appendChild(Text::create(document(), text.substring(start, i -
start)), es); | 383 fragment->appendChild(Text::create(&document(), text.substring(start, i
- start)), es); |
| 384 if (es.hadException()) | 384 if (es.hadException()) |
| 385 return 0; | 385 return 0; |
| 386 | 386 |
| 387 if (c == '\r' || c == '\n') { | 387 if (c == '\r' || c == '\n') { |
| 388 fragment->appendChild(HTMLBRElement::create(document()), es); | 388 fragment->appendChild(HTMLBRElement::create(&document()), es); |
| 389 if (es.hadException()) | 389 if (es.hadException()) |
| 390 return 0; | 390 return 0; |
| 391 // Make sure \r\n doesn't result in two line breaks. | 391 // Make sure \r\n doesn't result in two line breaks. |
| 392 if (c == '\r' && i + 1 < length && text[i + 1] == '\n') | 392 if (c == '\r' && i + 1 < length && text[i + 1] == '\n') |
| 393 i++; | 393 i++; |
| 394 } | 394 } |
| 395 | 395 |
| 396 start = i + 1; // Character after line break. | 396 start = i + 1; // Character after line break. |
| 397 } | 397 } |
| 398 | 398 |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 467 } | 467 } |
| 468 | 468 |
| 469 RefPtr<Node> prev = previousSibling(); | 469 RefPtr<Node> prev = previousSibling(); |
| 470 RefPtr<Node> next = nextSibling(); | 470 RefPtr<Node> next = nextSibling(); |
| 471 RefPtr<Node> newChild; | 471 RefPtr<Node> newChild; |
| 472 | 472 |
| 473 // Convert text to fragment with <br> tags instead of linebreaks if needed. | 473 // Convert text to fragment with <br> tags instead of linebreaks if needed. |
| 474 if (text.contains('\r') || text.contains('\n')) | 474 if (text.contains('\r') || text.contains('\n')) |
| 475 newChild = textToFragment(text, es); | 475 newChild = textToFragment(text, es); |
| 476 else | 476 else |
| 477 newChild = Text::create(document(), text); | 477 newChild = Text::create(&document(), text); |
| 478 | 478 |
| 479 if (!this || !parentNode()) | 479 if (!this || !parentNode()) |
| 480 es.throwDOMException(HierarchyRequestError); | 480 es.throwDOMException(HierarchyRequestError); |
| 481 if (es.hadException()) | 481 if (es.hadException()) |
| 482 return; | 482 return; |
| 483 parent->replaceChild(newChild.release(), this, es); | 483 parent->replaceChild(newChild.release(), this, es); |
| 484 | 484 |
| 485 RefPtr<Node> node = next ? next->previousSibling() : 0; | 485 RefPtr<Node> node = next ? next->previousSibling() : 0; |
| 486 if (!es.hadException() && node && node->isTextNode()) | 486 if (!es.hadException() && node && node->isTextNode()) |
| 487 mergeWithNextTextNode(node.release(), es); | 487 mergeWithNextTextNode(node.release(), es); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 567 if (!contextElement) | 567 if (!contextElement) |
| 568 return; | 568 return; |
| 569 RefPtr<DocumentFragment> fragment = createFragmentForInnerOuterHTML(markup,
contextElement, AllowScriptingContent, es); | 569 RefPtr<DocumentFragment> fragment = createFragmentForInnerOuterHTML(markup,
contextElement, AllowScriptingContent, es); |
| 570 if (!fragment) | 570 if (!fragment) |
| 571 return; | 571 return; |
| 572 insertAdjacent(where, fragment.get(), es); | 572 insertAdjacent(where, fragment.get(), es); |
| 573 } | 573 } |
| 574 | 574 |
| 575 void HTMLElement::insertAdjacentText(const String& where, const String& text, Ex
ceptionState& es) | 575 void HTMLElement::insertAdjacentText(const String& where, const String& text, Ex
ceptionState& es) |
| 576 { | 576 { |
| 577 RefPtr<Text> textNode = document()->createTextNode(text); | 577 RefPtr<Text> textNode = document().createTextNode(text); |
| 578 insertAdjacent(where, textNode.get(), es); | 578 insertAdjacent(where, textNode.get(), es); |
| 579 } | 579 } |
| 580 | 580 |
| 581 void HTMLElement::applyAlignmentAttributeToStyle(const AtomicString& alignment,
MutableStylePropertySet* style) | 581 void HTMLElement::applyAlignmentAttributeToStyle(const AtomicString& alignment,
MutableStylePropertySet* style) |
| 582 { | 582 { |
| 583 // Vertical alignment with respect to the current baseline of the text | 583 // Vertical alignment with respect to the current baseline of the text |
| 584 // right or left means floating images. | 584 // right or left means floating images. |
| 585 CSSValueID floatValue = CSSValueInvalid; | 585 CSSValueID floatValue = CSSValueInvalid; |
| 586 CSSValueID verticalAlignValue = CSSValueInvalid; | 586 CSSValueID verticalAlignValue = CSSValueInvalid; |
| 587 | 587 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 619 } | 619 } |
| 620 | 620 |
| 621 bool HTMLElement::supportsSpatialNavigationFocus() const | 621 bool HTMLElement::supportsSpatialNavigationFocus() const |
| 622 { | 622 { |
| 623 // This function checks whether the element satisfies the extended criteria | 623 // This function checks whether the element satisfies the extended criteria |
| 624 // for the element to be focusable, introduced by spatial navigation feature
, | 624 // for the element to be focusable, introduced by spatial navigation feature
, |
| 625 // i.e. checks if click or keyboard event handler is specified. | 625 // i.e. checks if click or keyboard event handler is specified. |
| 626 // This is the way to make it possible to navigate to (focus) elements | 626 // This is the way to make it possible to navigate to (focus) elements |
| 627 // which web designer meant for being active (made them respond to click eve
nts). | 627 // which web designer meant for being active (made them respond to click eve
nts). |
| 628 | 628 |
| 629 if (!document()->settings() || !document()->settings()->spatialNavigationEna
bled()) | 629 if (!document().settings() || !document().settings()->spatialNavigationEnabl
ed()) |
| 630 return false; | 630 return false; |
| 631 EventTarget* target = const_cast<HTMLElement*>(this); | 631 EventTarget* target = const_cast<HTMLElement*>(this); |
| 632 return target->hasEventListeners(eventNames().clickEvent) | 632 return target->hasEventListeners(eventNames().clickEvent) |
| 633 || target->hasEventListeners(eventNames().keydownEvent) | 633 || target->hasEventListeners(eventNames().keydownEvent) |
| 634 || target->hasEventListeners(eventNames().keypressEvent) | 634 || target->hasEventListeners(eventNames().keypressEvent) |
| 635 || target->hasEventListeners(eventNames().keyupEvent); | 635 || target->hasEventListeners(eventNames().keyupEvent); |
| 636 } | 636 } |
| 637 | 637 |
| 638 bool HTMLElement::supportsFocus() const | 638 bool HTMLElement::supportsFocus() const |
| 639 { | 639 { |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 755 } | 755 } |
| 756 | 756 |
| 757 void HTMLElement::setTranslate(bool enable) | 757 void HTMLElement::setTranslate(bool enable) |
| 758 { | 758 { |
| 759 setAttribute(translateAttr, enable ? "yes" : "no"); | 759 setAttribute(translateAttr, enable ? "yes" : "no"); |
| 760 } | 760 } |
| 761 | 761 |
| 762 bool HTMLElement::rendererIsNeeded(const NodeRenderingContext& context) | 762 bool HTMLElement::rendererIsNeeded(const NodeRenderingContext& context) |
| 763 { | 763 { |
| 764 if (hasLocalName(noscriptTag)) { | 764 if (hasLocalName(noscriptTag)) { |
| 765 Frame* frame = document()->frame(); | 765 Frame* frame = document().frame(); |
| 766 if (frame && frame->script()->canExecuteScripts(NotAboutToExecuteScript)
) | 766 if (frame && frame->script()->canExecuteScripts(NotAboutToExecuteScript)
) |
| 767 return false; | 767 return false; |
| 768 } else if (hasLocalName(noembedTag)) { | 768 } else if (hasLocalName(noembedTag)) { |
| 769 Frame* frame = document()->frame(); | 769 Frame* frame = document().frame(); |
| 770 if (frame && frame->loader()->allowPlugins(NotAboutToInstantiatePlugin)) | 770 if (frame && frame->loader()->allowPlugins(NotAboutToInstantiatePlugin)) |
| 771 return false; | 771 return false; |
| 772 } | 772 } |
| 773 return Element::rendererIsNeeded(context); | 773 return Element::rendererIsNeeded(context); |
| 774 } | 774 } |
| 775 | 775 |
| 776 RenderObject* HTMLElement::createRenderer(RenderStyle* style) | 776 RenderObject* HTMLElement::createRenderer(RenderStyle* style) |
| 777 { | 777 { |
| 778 if (hasLocalName(wbrTag)) | 778 if (hasLocalName(wbrTag)) |
| 779 return new RenderWordBreak(this); | 779 return new RenderWordBreak(this); |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 922 { | 922 { |
| 923 Node* strongDirectionalityTextNode; | 923 Node* strongDirectionalityTextNode; |
| 924 TextDirection textDirection = directionality(&strongDirectionalityTextNode); | 924 TextDirection textDirection = directionality(&strongDirectionalityTextNode); |
| 925 setHasDirAutoFlagRecursively(this, true, strongDirectionalityTextNode); | 925 setHasDirAutoFlagRecursively(this, true, strongDirectionalityTextNode); |
| 926 if (renderer() && renderer()->style() && renderer()->style()->direction() !=
textDirection) | 926 if (renderer() && renderer()->style() && renderer()->style()->direction() !=
textDirection) |
| 927 setNeedsStyleRecalc(); | 927 setNeedsStyleRecalc(); |
| 928 } | 928 } |
| 929 | 929 |
| 930 void HTMLElement::adjustDirectionalityIfNeededAfterChildrenChanged(Node* beforeC
hange, int childCountDelta) | 930 void HTMLElement::adjustDirectionalityIfNeededAfterChildrenChanged(Node* beforeC
hange, int childCountDelta) |
| 931 { | 931 { |
| 932 if (document()->renderer() && childCountDelta < 0) { | 932 if (document().renderer() && childCountDelta < 0) { |
| 933 Node* node = beforeChange ? NodeTraversal::nextSkippingChildren(beforeCh
ange) : 0; | 933 Node* node = beforeChange ? NodeTraversal::nextSkippingChildren(beforeCh
ange) : 0; |
| 934 for (int counter = 0; node && counter < childCountDelta; counter++, node
= NodeTraversal::nextSkippingChildren(node)) { | 934 for (int counter = 0; node && counter < childCountDelta; counter++, node
= NodeTraversal::nextSkippingChildren(node)) { |
| 935 if (elementAffectsDirectionality(node)) | 935 if (elementAffectsDirectionality(node)) |
| 936 continue; | 936 continue; |
| 937 | 937 |
| 938 setHasDirAutoFlagRecursively(node, false); | 938 setHasDirAutoFlagRecursively(node, false); |
| 939 } | 939 } |
| 940 } | 940 } |
| 941 | 941 |
| 942 if (!selfOrAncestorHasDirAutoAttribute()) | 942 if (!selfOrAncestorHasDirAutoAttribute()) |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1073 handleKeypressEvent(toKeyboardEvent(event)); | 1073 handleKeypressEvent(toKeyboardEvent(event)); |
| 1074 if (event->defaultHandled()) | 1074 if (event->defaultHandled()) |
| 1075 return; | 1075 return; |
| 1076 } | 1076 } |
| 1077 | 1077 |
| 1078 Element::defaultEventHandler(event); | 1078 Element::defaultEventHandler(event); |
| 1079 } | 1079 } |
| 1080 | 1080 |
| 1081 void HTMLElement::handleKeypressEvent(KeyboardEvent* event) | 1081 void HTMLElement::handleKeypressEvent(KeyboardEvent* event) |
| 1082 { | 1082 { |
| 1083 if (!document()->settings() || !document()->settings()->spatialNavigationEna
bled() || !supportsFocus()) | 1083 if (!document().settings() || !document().settings()->spatialNavigationEnabl
ed() || !supportsFocus()) |
| 1084 return; | 1084 return; |
| 1085 // if the element is a text form control (like <input type=text> or <textare
a>) | 1085 // if the element is a text form control (like <input type=text> or <textare
a>) |
| 1086 // or has contentEditable attribute on, we should enter a space or newline | 1086 // or has contentEditable attribute on, we should enter a space or newline |
| 1087 // even in spatial navigation mode instead of handling it as a "click" actio
n. | 1087 // even in spatial navigation mode instead of handling it as a "click" actio
n. |
| 1088 if (isTextFormControl() || isContentEditable()) | 1088 if (isTextFormControl() || isContentEditable()) |
| 1089 return; | 1089 return; |
| 1090 int charCode = event->charCode(); | 1090 int charCode = event->charCode(); |
| 1091 if (charCode == '\r' || charCode == ' ') { | 1091 if (charCode == '\r' || charCode == ' ') { |
| 1092 dispatchSimulatedClick(event); | 1092 dispatchSimulatedClick(event); |
| 1093 event->setDefaultHandled(); | 1093 event->setDefaultHandled(); |
| 1094 } | 1094 } |
| 1095 } | 1095 } |
| 1096 | 1096 |
| 1097 } // namespace WebCore | 1097 } // namespace WebCore |
| 1098 | 1098 |
| 1099 #ifndef NDEBUG | 1099 #ifndef NDEBUG |
| 1100 | 1100 |
| 1101 // For use in the debugger | 1101 // For use in the debugger |
| 1102 void dumpInnerHTML(WebCore::HTMLElement*); | 1102 void dumpInnerHTML(WebCore::HTMLElement*); |
| 1103 | 1103 |
| 1104 void dumpInnerHTML(WebCore::HTMLElement* element) | 1104 void dumpInnerHTML(WebCore::HTMLElement* element) |
| 1105 { | 1105 { |
| 1106 printf("%s\n", element->innerHTML().ascii().data()); | 1106 printf("%s\n", element->innerHTML().ascii().data()); |
| 1107 } | 1107 } |
| 1108 #endif | 1108 #endif |
| OLD | NEW |