diff options
author | Nico Weber <thakis@chromium.org> | 2020-08-17 22:06:08 -0400 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-08-18 16:58:46 +0200 |
commit | 2460980d2c4cda800d50e8e323f0e510c943a022 (patch) | |
tree | 3c197a4ab6b80273cd2e8236ed74972a0e782674 /Libraries | |
parent | 2f85af2a20bdc3d994256078fafbf58162ec8d36 (diff) | |
download | serenity-2460980d2c4cda800d50e8e323f0e510c943a022.zip |
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.
Diffstat (limited to 'Libraries')
-rw-r--r-- | Libraries/LibWeb/DOM/Element.cpp | 34 | ||||
-rw-r--r-- | Libraries/LibWeb/DOM/Element.h | 3 | ||||
-rw-r--r-- | Libraries/LibWeb/DOM/Element.idl | 1 | ||||
-rw-r--r-- | Libraries/LibWeb/Tests/DOM/Element.js | 24 | ||||
-rw-r--r-- | Libraries/LibWeb/Tests/DOM/Node.js | 10 |
5 files changed, 71 insertions, 1 deletions
diff --git a/Libraries/LibWeb/DOM/Element.cpp b/Libraries/LibWeb/DOM/Element.cpp index 19cc1733ad..b5445ab593 100644 --- a/Libraries/LibWeb/DOM/Element.cpp +++ b/Libraries/LibWeb/DOM/Element.cpp @@ -41,6 +41,7 @@ #include <LibWeb/Layout/LayoutTableCell.h> #include <LibWeb/Layout/LayoutTableRow.h> #include <LibWeb/Layout/LayoutTableRowGroup.h> +#include <LibWeb/Layout/LayoutText.h> #include <LibWeb/Layout/LayoutTreeBuilder.h> namespace Web::DOM { @@ -295,6 +296,39 @@ String Element::inner_html() const 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 { return document().focused_element() == this; diff --git a/Libraries/LibWeb/DOM/Element.h b/Libraries/LibWeb/DOM/Element.h index b08ff34e42..253f532aff 100644 --- a/Libraries/LibWeb/DOM/Element.h +++ b/Libraries/LibWeb/DOM/Element.h @@ -87,6 +87,9 @@ public: String inner_html() const; void set_inner_html(StringView); + String inner_text(); + void set_inner_text(StringView); + bool is_focused() const; virtual bool is_focusable() const { return false; } diff --git a/Libraries/LibWeb/DOM/Element.idl b/Libraries/LibWeb/DOM/Element.idl index 082d0a951a..34baef070e 100644 --- a/Libraries/LibWeb/DOM/Element.idl +++ b/Libraries/LibWeb/DOM/Element.idl @@ -9,6 +9,7 @@ interface Element : Node { ArrayFromVector querySelectorAll(DOMString selectors); attribute DOMString innerHTML; + attribute DOMString innerText; [Reflect] attribute DOMString id; [Reflect=class] attribute DOMString className; diff --git a/Libraries/LibWeb/Tests/DOM/Element.js b/Libraries/LibWeb/Tests/DOM/Element.js new file mode 100644 index 0000000000..0fd40594cc --- /dev/null +++ b/Libraries/LibWeb/Tests/DOM/Element.js @@ -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. `); + }); +}); diff --git a/Libraries/LibWeb/Tests/DOM/Node.js b/Libraries/LibWeb/Tests/DOM/Node.js index 2af91d1cbb..5427d143bd 100644 --- a/Libraries/LibWeb/Tests/DOM/Node.js +++ b/Libraries/LibWeb/Tests/DOM/Node.js @@ -1,4 +1,4 @@ -loadPage("file:///res/html/misc/small.html"); +loadPage("file:///res/html/misc/innertext_textcontent.html"); afterInitialPageLoad(() => { test("Node.textContent", () => { @@ -16,5 +16,13 @@ afterInitialPageLoad(() => { expect(p.textContent).toBe("bar"); expect(p.firstChild.textContent).toBe("bar"); 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 + `); }); }); |