summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Groh <mail@linusgroh.de>2020-05-25 21:12:00 +0100
committerAndreas Kling <kling@serenityos.org>2020-05-26 00:12:20 +0200
commit67b742bf3218ced0cc0471ae8615beed66fe2cd3 (patch)
treeae4cf82a9d288da33b153ff07edd217eddf2a157
parent6e505b853ed32c1e3eaafd06bdb1023b235c1f50 (diff)
downloadserenity-67b742bf3218ced0cc0471ae8615beed66fe2cd3.zip
LibWeb: Add document.querySelector()
-rw-r--r--Base/home/anon/www/canvas-path-quadratic-curve.html2
-rw-r--r--Base/home/anon/www/canvas-path.html2
-rw-r--r--Base/home/anon/www/img-canvas.html4
-rw-r--r--Base/home/anon/www/location.html2
-rw-r--r--Libraries/LibWeb/Bindings/DocumentWrapper.cpp19
-rw-r--r--Libraries/LibWeb/Bindings/DocumentWrapper.h1
-rw-r--r--Libraries/LibWeb/DOM/Document.cpp20
-rw-r--r--Libraries/LibWeb/DOM/Document.h1
8 files changed, 46 insertions, 5 deletions
diff --git a/Base/home/anon/www/canvas-path-quadratic-curve.html b/Base/home/anon/www/canvas-path-quadratic-curve.html
index 89c4a1d098..0985f97184 100644
--- a/Base/home/anon/www/canvas-path-quadratic-curve.html
+++ b/Base/home/anon/www/canvas-path-quadratic-curve.html
@@ -9,7 +9,7 @@
function drawSomeCurves() {
-var canvas = document.querySelectorAll("canvas")[0];
+var canvas = document.querySelector("canvas");
var ctx = canvas.getContext("2d");
var x = 150;
var y = 150;
diff --git a/Base/home/anon/www/canvas-path.html b/Base/home/anon/www/canvas-path.html
index 2f6c26c068..b44c7d655f 100644
--- a/Base/home/anon/www/canvas-path.html
+++ b/Base/home/anon/www/canvas-path.html
@@ -9,7 +9,7 @@
function drawHouse() {
-var ctx = document.querySelectorAll("canvas")[0].getContext("2d");
+var ctx = document.querySelector("canvas").getContext("2d");
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, 300, 300);
diff --git a/Base/home/anon/www/img-canvas.html b/Base/home/anon/www/img-canvas.html
index 5a4f0fde80..a21add25ac 100644
--- a/Base/home/anon/www/img-canvas.html
+++ b/Base/home/anon/www/img-canvas.html
@@ -9,10 +9,10 @@
</style>
<script>
document.addEventListener("DOMContentLoaded", function() {
- img = document.querySelectorAll("img")[0];
+ img = document.querySelector("img");
img.addEventListener("load", function() {
- var ctx = document.querySelectorAll("canvas")[0].getContext("2d");
+ var ctx = document.querySelector("canvas").getContext("2d");
ctx.fillStyle = '#666';
ctx.fillRect(0, 0, 400, 400);
ctx.scale(2, 2);
diff --git a/Base/home/anon/www/location.html b/Base/home/anon/www/location.html
index d7e08fe5d4..5633fa3df9 100644
--- a/Base/home/anon/www/location.html
+++ b/Base/home/anon/www/location.html
@@ -12,7 +12,7 @@
<div id="set_href">Click me to set location.href!</div>
<div id="reload">Click me to call location.reload()!</div>
<script>
- var pre = document.querySelectorAll("pre")[0];
+ var pre = document.querySelector("pre");
pre.innerHTML += "href: " + location.href + '\n';
pre.innerHTML += "protocol: " + location.protocol + '\n';
pre.innerHTML += "host: " + location.host + '\n';
diff --git a/Libraries/LibWeb/Bindings/DocumentWrapper.cpp b/Libraries/LibWeb/Bindings/DocumentWrapper.cpp
index 13381d82a7..a74fa06b01 100644
--- a/Libraries/LibWeb/Bindings/DocumentWrapper.cpp
+++ b/Libraries/LibWeb/Bindings/DocumentWrapper.cpp
@@ -41,6 +41,7 @@ DocumentWrapper::DocumentWrapper(Document& document)
: NodeWrapper(document)
{
put_native_function("getElementById", get_element_by_id, 1);
+ put_native_function("querySelector", query_selector, 1);
put_native_function("querySelectorAll", query_selector_all, 1);
}
@@ -86,6 +87,23 @@ JS::Value DocumentWrapper::get_element_by_id(JS::Interpreter& interpreter)
return wrap(interpreter.heap(), const_cast<Element&>(*element));
}
+JS::Value DocumentWrapper::query_selector(JS::Interpreter& interpreter)
+{
+ auto* document = document_from(interpreter);
+ if (!document)
+ return {};
+ if (!interpreter.argument_count())
+ return interpreter.throw_exception<JS::TypeError>("querySelector() needs one argument");
+ auto selector = interpreter.argument(0).to_string(interpreter);
+ if (interpreter.exception())
+ return {};
+ // FIXME: Throw if selector is invalid
+ auto element = document->query_selector(selector);
+ if (!element)
+ return JS::js_null();
+ return wrap(interpreter.heap(), *element);
+}
+
JS::Value DocumentWrapper::query_selector_all(JS::Interpreter& interpreter)
{
auto* document = document_from(interpreter);
@@ -96,6 +114,7 @@ JS::Value DocumentWrapper::query_selector_all(JS::Interpreter& interpreter)
auto selector = interpreter.argument(0).to_string(interpreter);
if (interpreter.exception())
return {};
+ // FIXME: Throw if selector is invalid
auto elements = document->query_selector_all(selector);
// FIXME: This should be a static NodeList, not a plain JS::Array.
auto* node_list = JS::Array::create(interpreter.global_object());
diff --git a/Libraries/LibWeb/Bindings/DocumentWrapper.h b/Libraries/LibWeb/Bindings/DocumentWrapper.h
index 86f2270ae9..9cf4c765b3 100644
--- a/Libraries/LibWeb/Bindings/DocumentWrapper.h
+++ b/Libraries/LibWeb/Bindings/DocumentWrapper.h
@@ -43,6 +43,7 @@ private:
virtual const char* class_name() const override { return "DocumentWrapper"; }
static JS::Value get_element_by_id(JS::Interpreter&);
+ static JS::Value query_selector(JS::Interpreter&);
static JS::Value query_selector_all(JS::Interpreter&);
};
diff --git a/Libraries/LibWeb/DOM/Document.cpp b/Libraries/LibWeb/DOM/Document.cpp
index dec30f6e80..c01cb1c1ba 100644
--- a/Libraries/LibWeb/DOM/Document.cpp
+++ b/Libraries/LibWeb/DOM/Document.cpp
@@ -321,6 +321,26 @@ Vector<const Element*> Document::get_elements_by_name(const String& name) const
return elements;
}
+RefPtr<Element> Document::query_selector(const StringView& selector_text)
+{
+ auto selector = parse_selector(selector_text);
+ if (!selector.has_value())
+ return {};
+
+ dump_selector(selector.value());
+
+ RefPtr<Element> result;
+ for_each_in_subtree_of_type<Element>([&](auto& element) {
+ if (SelectorEngine::matches(selector.value(), element)) {
+ result = element;
+ return IterationDecision::Break;
+ }
+ return IterationDecision::Continue;
+ });
+
+ return result;
+}
+
NonnullRefPtrVector<Element> Document::query_selector_all(const StringView& selector_text)
{
auto selector = parse_selector(selector_text);
diff --git a/Libraries/LibWeb/DOM/Document.h b/Libraries/LibWeb/DOM/Document.h
index dc9c88bb56..8829171c7a 100644
--- a/Libraries/LibWeb/DOM/Document.h
+++ b/Libraries/LibWeb/DOM/Document.h
@@ -116,6 +116,7 @@ public:
void schedule_style_update();
Vector<const Element*> get_elements_by_name(const String&) const;
+ RefPtr<Element> query_selector(const StringView&);
NonnullRefPtrVector<Element> query_selector_all(const StringView&);
const String& source() const { return m_source; }