mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 23:37:35 +00:00
LibWeb: Implement Element.innerText
Reading the property has a few warts (see FIXMEs in the included tests), but with this the timestamps on http://45.33.8.238/ get localized :^) Since the Date() constructor currently ignores all arguments, they don't get localized correctly but are all set to the current time, but hey, it's still progress from a certain point of view.
This commit is contained in:
parent
2f85af2a20
commit
2460980d2c
6 changed files with 86 additions and 1 deletions
15
Base/res/html/misc/innertext_textcontent.html
Normal file
15
Base/res/html/misc/innertext_textcontent.html
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
<html>
|
||||||
|
<head><title>Small test page</title></head>
|
||||||
|
<body bgcolor="#408080" text="#ffffff">
|
||||||
|
<h1 title="This is a heading" >Hello friends!</h1>
|
||||||
|
<p>This is a <b>very small</b> test page :^)</p>
|
||||||
|
<p>Visit the <a title="This is a link" href="http://www.serenityos.org/">SerenityOS home page</a> today!</p>
|
||||||
|
|
||||||
|
<p id="source">
|
||||||
|
<style>#source { color: red; } #text { text-transform: uppercase; }</style>
|
||||||
|
<span id=text>Take a look at<br>how this text<br>is interpreted
|
||||||
|
below.</span>
|
||||||
|
<span style="display:none">HIDDEN TEXT</span>
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -41,6 +41,7 @@
|
||||||
#include <LibWeb/Layout/LayoutTableCell.h>
|
#include <LibWeb/Layout/LayoutTableCell.h>
|
||||||
#include <LibWeb/Layout/LayoutTableRow.h>
|
#include <LibWeb/Layout/LayoutTableRow.h>
|
||||||
#include <LibWeb/Layout/LayoutTableRowGroup.h>
|
#include <LibWeb/Layout/LayoutTableRowGroup.h>
|
||||||
|
#include <LibWeb/Layout/LayoutText.h>
|
||||||
#include <LibWeb/Layout/LayoutTreeBuilder.h>
|
#include <LibWeb/Layout/LayoutTreeBuilder.h>
|
||||||
|
|
||||||
namespace Web::DOM {
|
namespace Web::DOM {
|
||||||
|
@ -295,6 +296,39 @@ String Element::inner_html() const
|
||||||
return builder.to_string();
|
return builder.to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Element::set_inner_text(StringView text)
|
||||||
|
{
|
||||||
|
remove_all_children();
|
||||||
|
append_child(document().create_text_node(text));
|
||||||
|
|
||||||
|
set_needs_style_update(true);
|
||||||
|
document().schedule_style_update();
|
||||||
|
document().invalidate_layout();
|
||||||
|
}
|
||||||
|
|
||||||
|
String Element::inner_text()
|
||||||
|
{
|
||||||
|
StringBuilder builder;
|
||||||
|
|
||||||
|
// innerText for element being rendered takes visibility into account, so force a layout and then walk the layout tree.
|
||||||
|
document().layout();
|
||||||
|
if (!layout_node())
|
||||||
|
return text_content();
|
||||||
|
|
||||||
|
Function<void(const LayoutNode&)> recurse = [&](auto& node) {
|
||||||
|
for (auto* child = node.first_child(); child; child = child->next_sibling()) {
|
||||||
|
if (child->is_text())
|
||||||
|
builder.append(downcast<LayoutText>(*child).text_for_rendering());
|
||||||
|
if (child->is_break())
|
||||||
|
builder.append('\n');
|
||||||
|
recurse(*child);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
recurse(*layout_node());
|
||||||
|
|
||||||
|
return builder.to_string();
|
||||||
|
}
|
||||||
|
|
||||||
bool Element::is_focused() const
|
bool Element::is_focused() const
|
||||||
{
|
{
|
||||||
return document().focused_element() == this;
|
return document().focused_element() == this;
|
||||||
|
|
|
@ -87,6 +87,9 @@ public:
|
||||||
String inner_html() const;
|
String inner_html() const;
|
||||||
void set_inner_html(StringView);
|
void set_inner_html(StringView);
|
||||||
|
|
||||||
|
String inner_text();
|
||||||
|
void set_inner_text(StringView);
|
||||||
|
|
||||||
bool is_focused() const;
|
bool is_focused() const;
|
||||||
virtual bool is_focusable() const { return false; }
|
virtual bool is_focusable() const { return false; }
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ interface Element : Node {
|
||||||
ArrayFromVector querySelectorAll(DOMString selectors);
|
ArrayFromVector querySelectorAll(DOMString selectors);
|
||||||
|
|
||||||
attribute DOMString innerHTML;
|
attribute DOMString innerHTML;
|
||||||
|
attribute DOMString innerText;
|
||||||
[Reflect] attribute DOMString id;
|
[Reflect] attribute DOMString id;
|
||||||
[Reflect=class] attribute DOMString className;
|
[Reflect=class] attribute DOMString className;
|
||||||
|
|
||||||
|
|
24
Libraries/LibWeb/Tests/DOM/Element.js
Normal file
24
Libraries/LibWeb/Tests/DOM/Element.js
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
loadPage("file:///res/html/misc/innertext_textcontent.html");
|
||||||
|
|
||||||
|
afterInitialPageLoad(() => {
|
||||||
|
test("Element.innerText", () => {
|
||||||
|
var p = document.getElementsByTagName("p")[0];
|
||||||
|
expect(p.innerText).toBe("This is a very small test page :^)");
|
||||||
|
|
||||||
|
// FIXME: Call this on p once that's supported.
|
||||||
|
var b = document.getElementsByTagName("b")[0];
|
||||||
|
b.innerText = "foo";
|
||||||
|
expect(b.innerText).toBe("foo");
|
||||||
|
expect(p.innerText).toBe("This is a foo test page :^)");
|
||||||
|
|
||||||
|
p.innerText = "bar";
|
||||||
|
expect(p.innerText).toBe("bar");
|
||||||
|
|
||||||
|
var p = document.getElementById("source");
|
||||||
|
// FIXME: The leading and trailing two spaces each are wrong.
|
||||||
|
// FIXME: The text should be affected by the text-transform:uppercase.
|
||||||
|
expect(p.innerText).toBe(` Take a look at
|
||||||
|
how this text
|
||||||
|
is interpreted below. `);
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,4 +1,4 @@
|
||||||
loadPage("file:///res/html/misc/small.html");
|
loadPage("file:///res/html/misc/innertext_textcontent.html");
|
||||||
|
|
||||||
afterInitialPageLoad(() => {
|
afterInitialPageLoad(() => {
|
||||||
test("Node.textContent", () => {
|
test("Node.textContent", () => {
|
||||||
|
@ -16,5 +16,13 @@ afterInitialPageLoad(() => {
|
||||||
expect(p.textContent).toBe("bar");
|
expect(p.textContent).toBe("bar");
|
||||||
expect(p.firstChild.textContent).toBe("bar");
|
expect(p.firstChild.textContent).toBe("bar");
|
||||||
expect(p.firstChild.firstChild).toBe(null);
|
expect(p.firstChild.firstChild).toBe(null);
|
||||||
|
|
||||||
|
var p = document.getElementById("source");
|
||||||
|
expect(p.textContent).toBe(`
|
||||||
|
#source { color: red; } #text { text-transform: uppercase; }
|
||||||
|
Take a look athow this textis interpreted
|
||||||
|
below.
|
||||||
|
HIDDEN TEXT
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue