diff options
author | Linus Groh <mail@linusgroh.de> | 2020-05-25 21:12:00 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-05-26 00:12:20 +0200 |
commit | 67b742bf3218ced0cc0471ae8615beed66fe2cd3 (patch) | |
tree | ae4cf82a9d288da33b153ff07edd217eddf2a157 | |
parent | 6e505b853ed32c1e3eaafd06bdb1023b235c1f50 (diff) | |
download | serenity-67b742bf3218ced0cc0471ae8615beed66fe2cd3.zip |
LibWeb: Add document.querySelector()
-rw-r--r-- | Base/home/anon/www/canvas-path-quadratic-curve.html | 2 | ||||
-rw-r--r-- | Base/home/anon/www/canvas-path.html | 2 | ||||
-rw-r--r-- | Base/home/anon/www/img-canvas.html | 4 | ||||
-rw-r--r-- | Base/home/anon/www/location.html | 2 | ||||
-rw-r--r-- | Libraries/LibWeb/Bindings/DocumentWrapper.cpp | 19 | ||||
-rw-r--r-- | Libraries/LibWeb/Bindings/DocumentWrapper.h | 1 | ||||
-rw-r--r-- | Libraries/LibWeb/DOM/Document.cpp | 20 | ||||
-rw-r--r-- | Libraries/LibWeb/DOM/Document.h | 1 |
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; } |