Source/WebCore: Reimplement DETAILS and SUMMARY using selector query.

https://bugs.webkit.org/show_bug.cgi?id=75930

Patch by Shinya Kawanaka <shinyak@google.com> on 2012-02-03
Reviewed by Hajime Morita.

DETAILS is reimplemented using content element and its fallback feature.
We don't need to recreate DOM even if SUMMARY is removed from or added into DETAILS.

No new tests, should be covered by existing tests.

* html/HTMLDetailsElement.cpp:
(WebCore::DetailsSummaryElement::fallbackSummary):
  Takes fallback element of content summary.
(DetailsSummaryElement):
(WebCore::DetailsSummaryElement::create):
  Creates a fallback element also.
(WebCore):
(WebCore::HTMLDetailsElement::create):
(WebCore::HTMLDetailsElement::HTMLDetailsElement):
(WebCore::HTMLDetailsElement::createShadowSubtree):
(WebCore::HTMLDetailsElement::findMainSummary):
(WebCore::HTMLDetailsElement::parseMappedAttribute):
(WebCore::HTMLDetailsElement::childShouldCreateRenderer):
(WebCore::HTMLDetailsElement::toggleOpen):
* html/HTMLDetailsElement.h:
(HTMLDetailsElement):
* html/HTMLSummaryElement.cpp:
(WebCore::HTMLSummaryElement::isMainSummary):

LayoutTests: Reimplement DETAILS and SUMMARY using selector query.
https://bugs.webkit.org/show_bug.cgi?id=75930

Since the implementation of DETAILS shadow tree, the path of caret position is also changed.

Patch by Shinya Kawanaka <shinyak@google.com> on 2012-02-03
Reviewed by Hajime Morita.

* platform/chromium-win/fast/html/details-remove-summary-1-and-click-expected.txt:
* platform/chromium-win/fast/html/details-remove-summary-4-and-click-expected.txt:
* platform/gtk/fast/html/details-remove-summary-1-and-click-expected.txt:
* platform/gtk/fast/html/details-remove-summary-4-and-click-expected.txt:
* platform/mac/fast/html/details-remove-summary-1-and-click-expected.txt:
* platform/mac/fast/html/details-remove-summary-4-and-click-expected.txt:
* platform/qt/fast/html/details-remove-summary-1-and-click-expected.txt:
* platform/qt/fast/html/details-remove-summary-4-and-click-expected.txt:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@106637 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent b7158476
2012-02-03 Shinya Kawanaka <shinyak@google.com>
Reimplement DETAILS and SUMMARY using selector query.
https://bugs.webkit.org/show_bug.cgi?id=75930
Since the implementation of DETAILS shadow tree, the path of caret position is also changed.
Reviewed by Hajime Morita.
* platform/chromium-win/fast/html/details-remove-summary-1-and-click-expected.txt:
* platform/chromium-win/fast/html/details-remove-summary-4-and-click-expected.txt:
* platform/gtk/fast/html/details-remove-summary-1-and-click-expected.txt:
* platform/gtk/fast/html/details-remove-summary-4-and-click-expected.txt:
* platform/mac/fast/html/details-remove-summary-1-and-click-expected.txt:
* platform/mac/fast/html/details-remove-summary-4-and-click-expected.txt:
* platform/qt/fast/html/details-remove-summary-1-and-click-expected.txt:
* platform/qt/fast/html/details-remove-summary-4-and-click-expected.txt:
2012-02-02 Alexei Filippov <alexeif@chromium.org>
Web Inspector: Always show percents together with counters in heap inspector.
......@@ -8,4 +8,4 @@ layer at (0,0) size 800x600
RenderDetailsMarker {DIV} at (0,5) size 10x10: down
RenderText {#text} at (16,0) size 41x19
text run at (16,0) width 41: "Details"
caret: position 0 of child 0 {DIV} of {#shadow-root} of child 0 {SUMMARY} of {#shadow-root} of child 1 {DETAILS} of body
caret: position 0 of child 0 {DIV} of {#shadow-root} of child 0 {SUMMARY} of child 0 {DIV} of {#shadow-root} of child 1 {DETAILS} of body
......@@ -8,4 +8,4 @@ layer at (0,0) size 800x600
RenderDetailsMarker {DIV} at (0,5) size 10x10: right
RenderText {#text} at (16,0) size 41x19
text run at (16,0) width 41: "Details"
caret: position 0 of child 0 {DIV} of {#shadow-root} of child 0 {SUMMARY} of {#shadow-root} of child 1 {DETAILS} of body
caret: position 0 of child 0 {DIV} of {#shadow-root} of child 0 {SUMMARY} of child 0 {DIV} of {#shadow-root} of child 1 {DETAILS} of body
......@@ -8,4 +8,4 @@ layer at (0,0) size 800x600
RenderDetailsMarker {DIV} at (0,4) size 10x10: down
RenderText {#text} at (16,0) size 46x17
text run at (16,0) width 46: "Details"
caret: position 0 of child 0 {DIV} of {#shadow-root} of child 0 {SUMMARY} of {#shadow-root} of child 1 {DETAILS} of body
caret: position 0 of child 0 {DIV} of {#shadow-root} of child 0 {SUMMARY} of child 0 {DIV} of {#shadow-root} of child 1 {DETAILS} of body
......@@ -8,4 +8,4 @@ layer at (0,0) size 800x600
RenderDetailsMarker {DIV} at (0,4) size 10x10: right
RenderText {#text} at (16,0) size 46x17
text run at (16,0) width 46: "Details"
caret: position 0 of child 0 {DIV} of {#shadow-root} of child 0 {SUMMARY} of {#shadow-root} of child 1 {DETAILS} of body
caret: position 0 of child 0 {DIV} of {#shadow-root} of child 0 {SUMMARY} of child 0 {DIV} of {#shadow-root} of child 1 {DETAILS} of body
......@@ -8,4 +8,4 @@ layer at (0,0) size 800x600
RenderDetailsMarker {DIV} at (0,4) size 10x10: down
RenderText {#text} at (16,0) size 44x18
text run at (16,0) width 44: "Details"
caret: position 0 of child 0 {DIV} of {#shadow-root} of child 0 {SUMMARY} of {#shadow-root} of child 1 {DETAILS} of body
caret: position 0 of child 0 {DIV} of {#shadow-root} of child 0 {SUMMARY} of child 0 {DIV} of {#shadow-root} of child 1 {DETAILS} of body
......@@ -8,4 +8,4 @@ layer at (0,0) size 800x600
RenderDetailsMarker {DIV} at (0,4) size 10x10: right
RenderText {#text} at (16,0) size 44x18
text run at (16,0) width 44: "Details"
caret: position 0 of child 0 {DIV} of {#shadow-root} of child 0 {SUMMARY} of {#shadow-root} of child 1 {DETAILS} of body
caret: position 0 of child 0 {DIV} of {#shadow-root} of child 0 {SUMMARY} of child 0 {DIV} of {#shadow-root} of child 1 {DETAILS} of body
......@@ -8,4 +8,4 @@ layer at (0,0) size 800x600
RenderDetailsMarker {DIV} at (0,6) size 10x10: down
RenderText {#text} at (16,0) size 50x21
text run at (16,0) width 50: "Details"
caret: position 0 of child 0 {DIV} of {#shadow-root} of child 0 {SUMMARY} of {#shadow-root} of child 1 {DETAILS} of body
caret: position 0 of child 0 {DIV} of {#shadow-root} of child 0 {SUMMARY} of child 0 {DIV} of {#shadow-root} of child 1 {DETAILS} of body
......@@ -8,4 +8,4 @@ layer at (0,0) size 800x600
RenderDetailsMarker {DIV} at (0,6) size 10x10: right
RenderText {#text} at (16,0) size 50x21
text run at (16,0) width 50: "Details"
caret: position 0 of child 0 {DIV} of {#shadow-root} of child 0 {SUMMARY} of {#shadow-root} of child 1 {DETAILS} of body
caret: position 0 of child 0 {DIV} of {#shadow-root} of child 0 {SUMMARY} of child 0 {DIV} of {#shadow-root} of child 1 {DETAILS} of body
2012-02-03 Shinya Kawanaka <shinyak@google.com>
Reimplement DETAILS and SUMMARY using selector query.
https://bugs.webkit.org/show_bug.cgi?id=75930
Reviewed by Hajime Morita.
DETAILS is reimplemented using content element and its fallback feature.
We don't need to recreate DOM even if SUMMARY is removed from or added into DETAILS.
No new tests, should be covered by existing tests.
* html/HTMLDetailsElement.cpp:
(WebCore::DetailsSummaryElement::fallbackSummary):
Takes fallback element of content summary.
(DetailsSummaryElement):
(WebCore::DetailsSummaryElement::create):
Creates a fallback element also.
(WebCore):
(WebCore::HTMLDetailsElement::create):
(WebCore::HTMLDetailsElement::HTMLDetailsElement):
(WebCore::HTMLDetailsElement::createShadowSubtree):
(WebCore::HTMLDetailsElement::findMainSummary):
(WebCore::HTMLDetailsElement::parseMappedAttribute):
(WebCore::HTMLDetailsElement::childShouldCreateRenderer):
(WebCore::HTMLDetailsElement::toggleOpen):
* html/HTMLDetailsElement.h:
(HTMLDetailsElement):
* html/HTMLSummaryElement.cpp:
(WebCore::HTMLSummaryElement::isMainSummary):
2012-02-03 Jochen Eisinger <jochen@chromium.org>
Crash when trying to add a timer to a detached document.
......@@ -62,6 +62,12 @@ class DetailsSummaryElement : public HTMLContentElement {
public:
static PassRefPtr<DetailsSummaryElement> create(Document*);
Element* fallbackSummary()
{
ASSERT(firstChild() && firstChild()->hasTagName(summaryTag));
return toElement(firstChild());
}
private:
DetailsSummaryElement(Document* document)
: HTMLContentElement(HTMLNames::divTag, document)
......@@ -72,20 +78,24 @@ private:
PassRefPtr<DetailsSummaryElement> DetailsSummaryElement::create(Document* document)
{
return adoptRef(new DetailsSummaryElement(document));
RefPtr<HTMLSummaryElement> defaultSummary = HTMLSummaryElement::create(summaryTag, document);
defaultSummary->appendChild(Text::create(document, defaultDetailsSummaryText()), ASSERT_NO_EXCEPTION);
DetailsSummaryElement* elem = new DetailsSummaryElement(document);
elem->appendChild(defaultSummary);
return adoptRef(elem);
}
PassRefPtr<HTMLDetailsElement> HTMLDetailsElement::create(const QualifiedName& tagName, Document* document)
{
RefPtr<HTMLDetailsElement> result = adoptRef(new HTMLDetailsElement(tagName, document));
result->ensureShadowSubtreeOf(ForwardingSummary);
return result;
RefPtr<HTMLDetailsElement> elem = adoptRef(new HTMLDetailsElement(tagName, document));
elem->createShadowSubtree();
return elem.release();
}
HTMLDetailsElement::HTMLDetailsElement(const QualifiedName& tagName, Document* document)
: HTMLElement(tagName, document)
, m_summaryType(NoSummary)
, m_mainSummary(0)
, m_isOpen(false)
{
ASSERT(hasTagName(detailsTag));
......@@ -96,83 +106,21 @@ RenderObject* HTMLDetailsElement::createRenderer(RenderArena* arena, RenderStyle
return new (arena) RenderDetails(this);
}
void HTMLDetailsElement::ensureShadowSubtreeOf(SummaryType type)
{
if (type == m_summaryType)
return;
m_summaryType = type;
removeShadowRoot();
createShadowSubtree();
}
static Node* findSummaryFor(PassRefPtr<ContainerNode> container)
{
for (Node* child = container->firstChild(); child; child = child->nextSibling()) {
if (child->hasTagName(summaryTag))
return child;
}
return 0;
}
Node* HTMLDetailsElement::ensureMainSummary()
{
Node* summary = findSummaryFor(this);
if (summary) {
ensureShadowSubtreeOf(ForwardingSummary);
return summary;
}
ensureShadowSubtreeOf(DefaultSummary);
return findSummaryFor(shadowRoot());
}
void HTMLDetailsElement::refreshMainSummary(RefreshRenderer refreshRenderer)
{
RefPtr<Node> oldSummary = m_mainSummary;
m_mainSummary = ensureMainSummary();
if (oldSummary == m_mainSummary || !attached())
return;
if (oldSummary && oldSummary->parentNodeForRenderingAndStyle())
oldSummary->reattach();
if (m_mainSummary && refreshRenderer == RefreshRendererAllowed)
m_mainSummary->reattach();
}
void HTMLDetailsElement::createShadowSubtree()
{
ASSERT(!shadowRoot());
ExceptionCode ec = 0;
if (m_summaryType == DefaultSummary) {
RefPtr<HTMLSummaryElement> defaultSummary = HTMLSummaryElement::create(summaryTag, document());
defaultSummary->appendChild(Text::create(document(), defaultDetailsSummaryText()), ec);
ensureShadowRoot()->appendChild(defaultSummary, ec, true);
ensureShadowRoot()->appendChild(DetailsContentElement::create(document()), ec, true);
} else {
ASSERT(m_summaryType == ForwardingSummary);
ensureShadowRoot()->appendChild(DetailsSummaryElement::create(document()), ec, true);
ensureShadowRoot()->appendChild(DetailsContentElement::create(document()), ec, true);
}
ensureShadowRoot()->appendChild(DetailsSummaryElement::create(document()), ASSERT_NO_EXCEPTION, true);
ensureShadowRoot()->appendChild(DetailsContentElement::create(document()), ASSERT_NO_EXCEPTION, true);
}
void HTMLDetailsElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
Element* HTMLDetailsElement::findMainSummary() const
{
HTMLElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
// If childCountDelta is less then zero and the main summary has changed it must be because previous main
// summary was removed. The new main summary was then inside the unrevealed content and needs to be
// reattached to create its renderer. If childCountDelta is not less then zero then a new <summary> element
// has been added and it will be attached without our help.
if (!changedByParser)
refreshMainSummary(childCountDelta < 0 ? RefreshRendererAllowed : RefreshRendererSupressed);
}
for (Node* child = firstChild(); child; child = child->nextSibling()) {
if (child->hasTagName(summaryTag))
return toElement(child);
}
void HTMLDetailsElement::finishParsingChildren()
{
HTMLElement::finishParsingChildren();
refreshMainSummary(RefreshRendererAllowed);
return static_cast<DetailsSummaryElement*>(shadowRoot()->firstChild())->fallbackSummary();
}
void HTMLDetailsElement::parseMappedAttribute(Attribute* attr)
......@@ -188,7 +136,13 @@ void HTMLDetailsElement::parseMappedAttribute(Attribute* attr)
bool HTMLDetailsElement::childShouldCreateRenderer(Node* child) const
{
return m_isOpen || child == m_mainSummary;
if (m_isOpen)
return true;
if (!child->hasTagName(summaryTag))
return false;
return child == findMainSummary();
}
void HTMLDetailsElement::toggleOpen()
......
......@@ -28,37 +28,20 @@ namespace WebCore {
class HTMLDetailsElement : public HTMLElement {
public:
static PassRefPtr<HTMLDetailsElement> create(const QualifiedName& tagName, Document* document);
Node* mainSummary() const { return m_mainSummary; }
void toggleOpen();
private:
enum RefreshRenderer {
RefreshRendererAllowed,
RefreshRendererSupressed,
};
enum SummaryType {
NoSummary,
DefaultSummary,
ForwardingSummary
};
Element* findMainSummary() const;
private:
HTMLDetailsElement(const QualifiedName&, Document*);
virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
virtual void childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta);
virtual void finishParsingChildren();
void parseMappedAttribute(Attribute*);
bool childShouldCreateRenderer(Node*) const;
Node* ensureMainSummary();
void refreshMainSummary(RefreshRenderer);
void ensureShadowSubtreeOf(SummaryType);
void createShadowSubtree();
SummaryType m_summaryType;
Node* m_mainSummary;
bool m_isOpen;
};
......
......@@ -89,8 +89,9 @@ HTMLDetailsElement* HTMLSummaryElement::detailsElement() const
bool HTMLSummaryElement::isMainSummary() const
{
if (HTMLDetailsElement* details = detailsElement())
return details->mainSummary() == this;
return 0;
return details->findMainSummary() == this;
return false;
}
static bool isClickableControl(Node* node)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment