diff --git a/README.md b/README.md index 20a4f00..096032f 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,28 @@ Crafter.CppDOM is a C++ library that exposes the browser DOM api's to C++ WebAssembly. +# HtmlElement vs HtmlElementView + +The library provides two main classes for working with HTML elements: + +## HtmlElementView +`HtmlElementView` is a base class that provides read and write access to HTML element properties and methods, but does **not** own the underlying DOM element. It's designed to be used when you want to interact with existing elements in the DOM without managing their lifecycle. + +Key characteristics: +- Provides access to element properties and methods like `SetInnerHTML`, `SetStyle`, `AddClass`, etc. +- Supports event handling through various `Add*Listener` methods +- Does not delete the underlying DOM element when destroyed +- Used when you're working with elements that already exist in the DOM + +## HtmlElement +`HtmlElement` is a derived class from `HtmlElementView` that adds ownership semantics. It creates a new DOM element when instantiated and properly manages its lifecycle. + +Key characteristics: +- Inherits all functionality from `HtmlElementView` +- Creates and owns a new DOM element when constructed +- Automatically deletes the DOM element when the `HtmlElement` object is destroyed +- Used when you want to create new elements programmatically + # How to use Please view the examples folder, this is a snippit from the HelloElement example: @@ -12,7 +34,7 @@ import Crafter.CppDOM; using namespace Crafter::CppDOM; int main(){ - HtmlElement body("body"); + HtmlElementView body("body"); body.SetInnerHTML("Hello World!"); } ``` @@ -49,7 +71,7 @@ import Crafter.CppDOM; using namespace Crafter::CppDOM; int main(){ - HtmlElement body("body"); + HtmlElementView body("body"); body.SetInnerHTML("Hello World!"); } ``` diff --git a/additional/env.js b/additional/env.js index a379805..c5645c5 100644 --- a/additional/env.js +++ b/additional/env.js @@ -624,6 +624,12 @@ let env = { const cls = decoder.decode(new Int8Array(window.crafter_webbuild_wasi.instance.exports.memory.buffer, className, classNameLength)); return jsmemory.get(ptr).classList.contains(cls); }, + deleteElement: function(ptr) { + const element = jsmemory.get(ptr); + if(element && element.parentNode) { + element.parentNode.removeChild(element); + } + }, addClickListener: addClickListener, removeClickListener: removeClickListener, addMouseOverListener: addMouseOverListener, diff --git a/examples/AllEventHandling/main.cpp b/examples/AllEventHandling/main.cpp index b477bc7..584caf5 100644 --- a/examples/AllEventHandling/main.cpp +++ b/examples/AllEventHandling/main.cpp @@ -8,7 +8,7 @@ using namespace Crafter; import std; // Create the main container element -HtmlElement* body = new HtmlElement("body", "
Click the button above
"); -HtmlElement* button = new HtmlElement("myButton"); //prevent destruction +HtmlElementView* button = new HtmlElement("myButton"); //prevent destruction int main() { button->AddClickListener([](Crafter::MouseEvent event){ - auto output = HtmlElement("output"); + auto output = HtmlElementView("output"); output.SetInnerHTML("Button was clicked at (" + std::to_string(event.clientX) + ", " + std::to_string(event.clientY) + ")!"); }); } \ No newline at end of file diff --git a/examples/StyleExample/main.cpp b/examples/StyleExample/main.cpp index 251fe24..5fa2db2 100644 --- a/examples/StyleExample/main.cpp +++ b/examples/StyleExample/main.cpp @@ -2,9 +2,9 @@ import Crafter.CppDOM; using namespace Crafter; int main(){ - HtmlElement body("body",""); + HtmlElementView body("body",""); // Create a div element - HtmlElement div("myDiv"); + HtmlElementView div("myDiv"); // Set some initial content div.SetInnerHTML("This is a styled paragraph
"); diff --git a/implementations/Crafter.CppDOM-HtmlElement.cpp b/implementations/Crafter.CppDOM-HtmlElement.cpp index 199f157..921f277 100644 --- a/implementations/Crafter.CppDOM-HtmlElement.cpp +++ b/implementations/Crafter.CppDOM-HtmlElement.cpp @@ -507,8 +507,7 @@ namespace Crafter { } HtmlElement::~HtmlElement() { - + CppDOMBindings::DeleteElement(ptr); } - } diff --git a/interfaces/Crafter.CppDOM-BindingsExport.cppm b/interfaces/Crafter.CppDOM-BindingsExport.cppm index f6647da..02d45f2 100644 --- a/interfaces/Crafter.CppDOM-BindingsExport.cppm +++ b/interfaces/Crafter.CppDOM-BindingsExport.cppm @@ -105,6 +105,10 @@ extern "C" { std::free(ptr); } + __attribute__((export_name("deleteElement"))) void DeleteElement(void* ptr) { + // This will be implemented in JavaScript + } + __attribute__((export_name("ExecuteClickHandler"))) void ExecuteClickHandler(std::int32_t handlerID, double clientX, double clientY, double screenX, double screenY, std::int32_t button, std::int32_t buttons, bool altKey, bool ctrlKey, bool shiftKey, bool metaKey) { Crafter::CppDOMBindings::clickHandlers->find(handlerID)->second(Crafter::MouseEvent(clientX, clientY, screenX, screenY, button, buttons, altKey, ctrlKey, shiftKey, metaKey)); } diff --git a/interfaces/Crafter.CppDOM-BindingsImport.cppm b/interfaces/Crafter.CppDOM-BindingsImport.cppm index 56db1fb..07d5efb 100644 --- a/interfaces/Crafter.CppDOM-BindingsImport.cppm +++ b/interfaces/Crafter.CppDOM-BindingsImport.cppm @@ -136,4 +136,6 @@ export namespace Crafter::CppDOMBindings { bool HasClass(void* ptr, const std::string_view className) { return HasClass(ptr, className.data(), className.size()); } + + __attribute__((import_module("env"), import_name("deleteElement"))) void DeleteElement(void* ptr); } \ No newline at end of file diff --git a/interfaces/Crafter.CppDOM-HtmlElement.cppm b/interfaces/Crafter.CppDOM-HtmlElement.cppm index ebd5288..71b64d0 100644 --- a/interfaces/Crafter.CppDOM-HtmlElement.cppm +++ b/interfaces/Crafter.CppDOM-HtmlElement.cppm @@ -18,7 +18,7 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -export module Crafter.CppDOM:HtmlElementView; +export module Crafter.CppDOM:HtmlElement; import std; import :BindingsExport; import :BindingsImport; @@ -139,8 +139,9 @@ namespace Crafter { }; export class HtmlElement : public HtmlElementView { - HtmlElementView(const std::string_view id); - HtmlElementView(const std::string_view id, const std::string_view html); - ~HtmlElementView(); - } + public: + HtmlElement(const std::string_view id); + HtmlElement(const std::string_view id, const std::string_view html); + ~HtmlElement(); + }; } \ No newline at end of file