added view

This commit is contained in:
Jorijn van der Graaf 2025-11-10 22:46:05 +01:00
commit 580e53d3bc
11 changed files with 68 additions and 34 deletions

View file

@ -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!");
}
```

View file

@ -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,

View file

@ -8,7 +8,7 @@ using namespace Crafter;
import std;
// Create the main container element
HtmlElement* body = new HtmlElement("body", "<div id='container'>"
HtmlElementView* body = new HtmlElementView("body", "<div id='container'>"
"<h1>Enhanced Event Handling Demo</h1>"
"<div id='events-container'>"
"<div class='event-section'>"
@ -58,22 +58,22 @@ HtmlElement* body = new HtmlElement("body", "<div id='container'>"
"</div>");
// Get references to elements
HtmlElement* mouseButton = new HtmlElement("mouseButton");
HtmlElement* mouseOutput = new HtmlElement("mouseOutput");
HtmlElement* keyInput = new HtmlElement("keyInput");
HtmlElement* keyOutput = new HtmlElement("keyOutput");
HtmlElement* focusInput = new HtmlElement("focusInput");
HtmlElement* focusOutput = new HtmlElement("focusOutput");
HtmlElement* formInput = new HtmlElement("formInput");
HtmlElement* formSelect = new HtmlElement("formSelect");
HtmlElement* formElement = new HtmlElement("formElement");
HtmlElement* formOutput = new HtmlElement("formOutput");
HtmlElement* windowOutput = new HtmlElement("windowOutput");
HtmlElement* dragSource = new HtmlElement("dragSource");
HtmlElement* dropTarget = new HtmlElement("dropTarget");
HtmlElement* dragOutput = new HtmlElement("dragOutput");
HtmlElement* wheelContainer = new HtmlElement("wheelContainer");
HtmlElement* wheelOutput = new HtmlElement("wheelOutput");
HtmlElementView* mouseButton = new HtmlElementView("mouseButton");
HtmlElementView* mouseOutput = new HtmlElementView("mouseOutput");
HtmlElementView* keyInput = new HtmlElementView("keyInput");
HtmlElementView* keyOutput = new HtmlElementView("keyOutput");
HtmlElementView* focusInput = new HtmlElementView("focusInput");
HtmlElementView* focusOutput = new HtmlElementView("focusOutput");
HtmlElementView* formInput = new HtmlElementView("formInput");
HtmlElementView* formSelect = new HtmlElementView("formSelect");
HtmlElementView* formElement = new HtmlElementView("formElement");
HtmlElementView* formOutput = new HtmlElementView("formOutput");
HtmlElementView* windowOutput = new HtmlElementView("windowOutput");
HtmlElementView* dragSource = new HtmlElementView("dragSource");
HtmlElementView* dropTarget = new HtmlElementView("dropTarget");
HtmlElementView* dragOutput = new HtmlElementView("dragOutput");
HtmlElementView* wheelContainer = new HtmlElementView("wheelContainer");
HtmlElementView* wheelOutput = new HtmlElementView("wheelOutput");
int main() {
// Mouse Events

View file

@ -15,7 +15,7 @@ import Crafter.CppDOM;
using namespace Crafter::CppDOM;
int main(){
HtmlElement body("body");
HtmlElementView body("body");
body.SetInnerHTML("Hello World!");
}
```

View file

@ -2,7 +2,7 @@ import Crafter.CppDOM;
using namespace Crafter;
int main(){
HtmlElement body("body");
HtmlElementView body("body");
body.SetInnerHTML("Hello World!");
//No need to call FreeJs, this is done in the destructor of HtmlElement.
//No need to call FreeJs, this is done in the destructor of HtmlElementView.
}

View file

@ -2,15 +2,15 @@ import Crafter.CppDOM;
import std;
using namespace Crafter;
HtmlElement body("body","<h1>Interactive Element Demo</h1>"
HtmlElementView body("body","<h1>Interactive Element Demo</h1>"
"<button id='myButton'>Click Me!</button>"
"<p id='output'>Click the button above</p>");
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) + ")!");
});
}

View file

@ -2,9 +2,9 @@ import Crafter.CppDOM;
using namespace Crafter;
int main(){
HtmlElement body("body","<div id=\"myDiv\"></div>");
HtmlElementView body("body","<div id=\"myDiv\"></div>");
// Create a div element
HtmlElement div("myDiv");
HtmlElementView div("myDiv");
// Set some initial content
div.SetInnerHTML("<p>This is a styled paragraph</p>");

View file

@ -507,8 +507,7 @@ namespace Crafter {
}
HtmlElement::~HtmlElement() {
CppDOMBindings::DeleteElement(ptr);
}
}

View file

@ -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));
}

View file

@ -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);
}

View file

@ -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();
};
}