mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 20:37:34 +00:00
LibWeb: Add Node.textContent
This requires moving remove_all_children() from ParentNode to Node, which makes ParentNode.cpp empty, so remove it. It also co-opts the existing Node::text_content() method and tweaks it slightly to fit the semantics of Node.textContent.
This commit is contained in:
parent
c0c7b4a098
commit
e9b56b5b9c
7 changed files with 44 additions and 44 deletions
|
@ -33,7 +33,6 @@ set(SOURCES
|
||||||
DOM/EventListener.cpp
|
DOM/EventListener.cpp
|
||||||
DOM/EventTarget.cpp
|
DOM/EventTarget.cpp
|
||||||
DOM/Node.cpp
|
DOM/Node.cpp
|
||||||
DOM/ParentNode.cpp
|
|
||||||
DOM/Position.cpp
|
DOM/Position.cpp
|
||||||
DOM/TagNames.cpp
|
DOM/TagNames.cpp
|
||||||
DOM/Text.cpp
|
DOM/Text.cpp
|
||||||
|
|
|
@ -84,14 +84,25 @@ String Node::text_content() const
|
||||||
auto text = child->text_content();
|
auto text = child->text_content();
|
||||||
if (!text.is_empty()) {
|
if (!text.is_empty()) {
|
||||||
builder.append(child->text_content());
|
builder.append(child->text_content());
|
||||||
builder.append(' ');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (builder.length() > 1)
|
|
||||||
builder.trim(1);
|
|
||||||
return builder.to_string();
|
return builder.to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Node::set_text_content(const String& content)
|
||||||
|
{
|
||||||
|
if (is_text()) {
|
||||||
|
downcast<Text>(this)->set_data(content);
|
||||||
|
} else {
|
||||||
|
remove_all_children();
|
||||||
|
append_child(document().create_text_node(content));
|
||||||
|
}
|
||||||
|
|
||||||
|
set_needs_style_update(true);
|
||||||
|
document().schedule_style_update();
|
||||||
|
document().invalidate_layout();
|
||||||
|
}
|
||||||
|
|
||||||
RefPtr<LayoutNode> Node::create_layout_node(const CSS::StyleProperties*)
|
RefPtr<LayoutNode> Node::create_layout_node(const CSS::StyleProperties*)
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -197,6 +208,13 @@ RefPtr<Node> Node::insert_before(NonnullRefPtr<Node> node, RefPtr<Node> child, b
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Node::remove_all_children()
|
||||||
|
{
|
||||||
|
while (RefPtr<Node> child = first_child()) {
|
||||||
|
remove_child(*child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Node::set_document(Badge<Document>, Document& document)
|
void Node::set_document(Badge<Document>, Document& document)
|
||||||
{
|
{
|
||||||
m_document = &document;
|
m_document = &document;
|
||||||
|
|
|
@ -79,12 +79,14 @@ public:
|
||||||
|
|
||||||
RefPtr<Node> append_child(NonnullRefPtr<Node>, bool notify = true);
|
RefPtr<Node> append_child(NonnullRefPtr<Node>, bool notify = true);
|
||||||
RefPtr<Node> insert_before(NonnullRefPtr<Node> node, RefPtr<Node> child, bool notify = true);
|
RefPtr<Node> insert_before(NonnullRefPtr<Node> node, RefPtr<Node> child, bool notify = true);
|
||||||
|
void remove_all_children();
|
||||||
|
|
||||||
virtual RefPtr<LayoutNode> create_layout_node(const CSS::StyleProperties* parent_style);
|
virtual RefPtr<LayoutNode> create_layout_node(const CSS::StyleProperties* parent_style);
|
||||||
|
|
||||||
virtual FlyString node_name() const = 0;
|
virtual FlyString node_name() const = 0;
|
||||||
|
|
||||||
virtual String text_content() const;
|
virtual String text_content() const;
|
||||||
|
void set_text_content(const String&);
|
||||||
|
|
||||||
Document& document() { return *m_document; }
|
Document& document() { return *m_document; }
|
||||||
const Document& document() const { return *m_document; }
|
const Document& document() const { return *m_document; }
|
||||||
|
|
|
@ -7,6 +7,7 @@ interface Node : EventTarget {
|
||||||
readonly attribute Node? nextSibling;
|
readonly attribute Node? nextSibling;
|
||||||
readonly attribute Node? parentNode;
|
readonly attribute Node? parentNode;
|
||||||
readonly attribute Element? parentElement;
|
readonly attribute Element? parentElement;
|
||||||
|
attribute DOMString textContent;
|
||||||
|
|
||||||
Node appendChild(Node node);
|
Node appendChild(Node node);
|
||||||
Node insertBefore(Node node, Node? child);
|
Node insertBefore(Node node, Node? child);
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
|
||||||
* list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <LibWeb/DOM/ParentNode.h>
|
|
||||||
|
|
||||||
namespace Web::DOM {
|
|
||||||
|
|
||||||
void ParentNode::remove_all_children()
|
|
||||||
{
|
|
||||||
while (RefPtr<Node> child = first_child()) {
|
|
||||||
remove_child(*child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -35,8 +35,6 @@ public:
|
||||||
template<typename F> void for_each_child(F) const;
|
template<typename F> void for_each_child(F) const;
|
||||||
template<typename F> void for_each_child(F);
|
template<typename F> void for_each_child(F);
|
||||||
|
|
||||||
void remove_all_children();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
explicit ParentNode(Document& document, NodeType type)
|
explicit ParentNode(Document& document, NodeType type)
|
||||||
: Node(document, type)
|
: Node(document, type)
|
||||||
|
|
20
Libraries/LibWeb/Tests/DOM/Node.js
Normal file
20
Libraries/LibWeb/Tests/DOM/Node.js
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
loadPage("file:///res/html/misc/small.html");
|
||||||
|
|
||||||
|
afterInitialPageLoad(() => {
|
||||||
|
test("Node.textContent", () => {
|
||||||
|
var p = document.getElementsByTagName("p")[0];
|
||||||
|
expect(p.textContent).toBe("This is a very small test page :^)");
|
||||||
|
expect(p.firstChild.textContent).toBe("This is a ");
|
||||||
|
expect(p.firstChild.firstChild).toBe(null);
|
||||||
|
|
||||||
|
p.firstChild.textContent = "foo";
|
||||||
|
expect(p.firstChild.textContent).toBe("foo");
|
||||||
|
expect(p.firstChild.firstChild).toBe(null);
|
||||||
|
expect(p.textContent).toBe("foovery small test page :^)");
|
||||||
|
|
||||||
|
p.textContent = "bar";
|
||||||
|
expect(p.textContent).toBe("bar");
|
||||||
|
expect(p.firstChild.textContent).toBe("bar");
|
||||||
|
expect(p.firstChild.firstChild).toBe(null);
|
||||||
|
});
|
||||||
|
});
|
Loading…
Add table
Add a link
Reference in a new issue