From f40afe684abc607934bd3f7f44416660e986210e Mon Sep 17 00:00:00 2001 From: Jorijn van der Graaf Date: Sun, 9 Nov 2025 22:43:52 +0100 Subject: [PATCH] click event --- Crafter.CppDOM-Bindings.o | Bin 1015 -> 0 bytes Crafter.CppDOM-HtmlElement.o | Bin 46078 -> 0 bytes Crafter.CppDOM.o | Bin 975 -> 0 bytes README.md | 2 +- additional/env.js | 33 +++++++++++++++-- examples/HelloElement/main.cpp | 2 +- examples/HelloWorld/project.json | 2 +- examples/InteractiveElement/README.md | 39 +++++++++++++++++++++ examples/InteractiveElement/main.cpp | 16 +++++++++ examples/InteractiveElement/project.json | 17 +++++++++ examples/InteractiveElement/run.sh | 1 + interfaces/Crafter.CppDOM-Bindings.cppm | 21 ++++++++--- interfaces/Crafter.CppDOM-HtmlElement.cppm | 38 ++++++++++++++------ 13 files changed, 151 insertions(+), 20 deletions(-) delete mode 100644 Crafter.CppDOM-Bindings.o delete mode 100644 Crafter.CppDOM-HtmlElement.o delete mode 100644 Crafter.CppDOM.o create mode 100644 examples/InteractiveElement/README.md create mode 100644 examples/InteractiveElement/main.cpp create mode 100644 examples/InteractiveElement/project.json create mode 100755 examples/InteractiveElement/run.sh diff --git a/Crafter.CppDOM-Bindings.o b/Crafter.CppDOM-Bindings.o deleted file mode 100644 index 9336cb6744c97769d21d05821a6174c294f262cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1015 zcmZQbEY4+QU|?WuX=rF*U`$|OV7drmF*B#;mGQ^N=Va!kCKko#rsn1sRWdO!K!uA- z5|gvz3-UAbN>YoM>ls19lJW7Gc`2DismUerX{C9|C7Jno@g<2#IjM{V3=GUoAY&OB zxLUz9GXp<2!)6eZS1%-8mtZ zEipM2t{bXL*9jDMdFjP^1>9irgl&`urqQ5 zF)%V50LgL|6y>LsCZ`q^GjV{@L}_ArDkGnBd_hiWF@!KQVc;n!%1=%$E>2C+O{!#M z1t%UhXrh?{N?H6RiACwDCGlygi6x~)sl^=H+)1T5*}9NCrOl7T(akR?(H2Wi%*oLO zB?nMe(#U?6<}XT3OD#&xOHS1-sVqn>*5)YAOwZFzttbHiP$nbc diff --git a/Crafter.CppDOM-HtmlElement.o b/Crafter.CppDOM-HtmlElement.o deleted file mode 100644 index 701dcf9456e00cdbba376d381135cd9cac51b8cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 46078 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 diff --git a/README.md b/README.md index fd0fe6e..20a4f00 100644 --- a/README.md +++ b/README.md @@ -56,4 +56,4 @@ int main(){ Save and close, then run ``crafter-build build executable && caddy file-server --listen :8080 --root bin/executable``. if you have caddy installed, if not use your favorite static file server instead. Now you can open the browser at ``http://localhost:8080`` and ``Hello World!`` will appear in the browser. -This sample can also be viewed in the [HelloElement example](https://forgejo.catcrafts.net/Catcrafts/Crafter.CppDOM/src/branch/master/examples) +This sample can also be viewed in the [HelloElement example](https://forgejo.catcrafts.net/Catcrafts/Crafter.CppDOM/src/branch/master/examples) \ No newline at end of file diff --git a/additional/env.js b/additional/env.js index 6c6ef3c..6cfd40f 100644 --- a/additional/env.js +++ b/additional/env.js @@ -19,9 +19,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ const decoder = new TextDecoder(); +const encoder = new TextEncoder(); let memorycounter = -1; const jsmemory = new Map(); +const eventHandlers = new Map(); function freeJs(ptr) { jsmemory.delete(ptr); @@ -37,10 +39,35 @@ function setInnerHTML(ptr, html, htmlLenght) { jsmemory.get(ptr).innerHTML = decoder.decode(new Int8Array(window.crafter_webbuild_wasi.instance.exports.memory.buffer, html, htmlLenght)); } +function addClickListener(ptr, handlerID) { + const element = jsmemory.get(ptr); + + // Create a handler that will trigger a notification to C++ + const handler = function(event) { + const { ExecuteClickHandler } = window.crafter_webbuild_wasi.instance.exports; + ExecuteClickHandler(handlerID); + }; + + eventHandlers.set(`${ptr}-${handlerID}`, handler); + + element.addEventListener("click", handler); +} + +function removeClickListener(ptr, handlerID) { + const element = jsmemory.get(ptr); + + const handler = eventHandlers.get(`${ptr}-${handlerID}`); + + element.removeEventListener("click", handler); + eventHandlers.delete(handlerID); +} + let env = { - freeJs:freeJs, - getElementById:getElementById, - setInnerHTML:setInnerHTML, + freeJs: freeJs, + getElementById: getElementById, + setInnerHTML: setInnerHTML, + addClickListener: addClickListener, + removeClickListener: removeClickListener, } window.crafter_webbuild_env = env; \ No newline at end of file diff --git a/examples/HelloElement/main.cpp b/examples/HelloElement/main.cpp index f806cbf..fce4639 100644 --- a/examples/HelloElement/main.cpp +++ b/examples/HelloElement/main.cpp @@ -1,5 +1,5 @@ import Crafter.CppDOM; -using namespace Crafter::CppDOM; +using namespace Crafter; int main(){ HtmlElement body("body"); diff --git a/examples/HelloWorld/project.json b/examples/HelloWorld/project.json index 660f28d..9750e20 100644 --- a/examples/HelloWorld/project.json +++ b/examples/HelloWorld/project.json @@ -2,7 +2,7 @@ "name": "main", "configurations": [ { - "name": "example", + "name": "executable", "implementations": ["main"], "target": "wasm32-wasi", "debug" : true, diff --git a/examples/InteractiveElement/README.md b/examples/InteractiveElement/README.md new file mode 100644 index 0000000..972191e --- /dev/null +++ b/examples/InteractiveElement/README.md @@ -0,0 +1,39 @@ +# Interactive Element Example + +This example demonstrates how to use DOM event handling with Crafter.CppDOM. + +## Features + +- Shows how to create interactive UI elements using C++ +- Demonstrates the framework for attaching event listeners +- Illustrates the planned callback mechanism for event handling + +## Usage + +The library now provides the foundation for interactive web applications: + +```cpp +import Crafter.CppDOM; +using namespace Crafter::CppDOM; + +int main(){ + // Create UI elements + HtmlElement body("body"); + body.SetInnerHTML("

Interactive Element Demo

" + "" + "

Click the button above

"); + + // Attach event listener + HtmlElement button("myButton"); + button.AddEventListener("click"); + + // Future: button.OnClick([]() { + // HtmlElement output("output"); + // output.SetInnerHTML("Button was clicked!"); + // }); + + return 0; +} +``` + +Note: The full callback mechanism requires additional infrastructure to properly bridge between JavaScript events and C++ callbacks. This implementation provides the framework for future development. \ No newline at end of file diff --git a/examples/InteractiveElement/main.cpp b/examples/InteractiveElement/main.cpp new file mode 100644 index 0000000..f4c2d91 --- /dev/null +++ b/examples/InteractiveElement/main.cpp @@ -0,0 +1,16 @@ +import Crafter.CppDOM; +import std; +using namespace Crafter; + +HtmlElement body("body","

Interactive Element Demo

" + "" + "

Click the button above

"); +HtmlElement* button = new HtmlElement("myButton"); //prevent destruction + + +int main() { + button->AddClickListener([](){ + auto output = HtmlElement("output"); + output.SetInnerHTML("Button was clicked!"); + }); +} \ No newline at end of file diff --git a/examples/InteractiveElement/project.json b/examples/InteractiveElement/project.json new file mode 100644 index 0000000..9750e20 --- /dev/null +++ b/examples/InteractiveElement/project.json @@ -0,0 +1,17 @@ +{ + "name": "main", + "configurations": [ + { + "name": "executable", + "implementations": ["main"], + "target": "wasm32-wasi", + "debug" : true, + "dependencies": [ + { + "path":"../../project.json", + "configuration":"lib-debug" + } + ] + } + ] +} \ No newline at end of file diff --git a/examples/InteractiveElement/run.sh b/examples/InteractiveElement/run.sh new file mode 100755 index 0000000..e706621 --- /dev/null +++ b/examples/InteractiveElement/run.sh @@ -0,0 +1 @@ +caddy file-server --listen :8080 --root bin/executable \ No newline at end of file diff --git a/interfaces/Crafter.CppDOM-Bindings.cppm b/interfaces/Crafter.CppDOM-Bindings.cppm index 5ead784..fc431db 100644 --- a/interfaces/Crafter.CppDOM-Bindings.cppm +++ b/interfaces/Crafter.CppDOM-Bindings.cppm @@ -22,13 +22,26 @@ export module Crafter.CppDOM:Bindings; import std; export namespace Crafter::CppDOM::Bindings { + int clickHandlerMaxId = 0; + std::unordered_map>* clickHandlers = new std::unordered_map>(); + __attribute__((import_module("env"), import_name("freeJs"))) void FreeJs(void* ptr); __attribute__((import_module("env"), import_name("getElementById"))) void* GetElementById(const char* id, std::size_t idLenght); - inline void* GetElementById(const std::string& id) { - return GetElementById(id.c_str(), id.size()); + void* GetElementById(const std::string_view id) { + return GetElementById(id.data(), id.size()); } __attribute__((import_module("env"), import_name("setInnerHTML"))) void SetInnerHTML(void* ptr, const char* html, std::size_t htmlLenght); - inline void SetInnerHTML(void* ptr, const std::string& html) { - SetInnerHTML(ptr, html.c_str(), html.size()); + void SetInnerHTML(void* ptr, const std::string_view html) { + SetInnerHTML(ptr, html.data(), html.size()); } + + // Event handling functions + __attribute__((import_module("env"), import_name("addClickListener"))) void AddClickListener(void* ptr, int id); + __attribute__((import_module("env"), import_name("removeClickListener"))) void RemoveClickListener(void* ptr, int id); } + +extern "C" { + __attribute__((export_name("ExecuteClickHandler"))) void ExecuteClickHandler(int a) { + Crafter::CppDOM::Bindings::clickHandlers->find(static_cast(a))->second(); + } +} \ No newline at end of file diff --git a/interfaces/Crafter.CppDOM-HtmlElement.cppm b/interfaces/Crafter.CppDOM-HtmlElement.cppm index 32cee49..bd0da22 100644 --- a/interfaces/Crafter.CppDOM-HtmlElement.cppm +++ b/interfaces/Crafter.CppDOM-HtmlElement.cppm @@ -22,24 +22,42 @@ export module Crafter.CppDOM:HtmlElement; import std; import :Bindings; -namespace Crafter::CppDOM { +namespace Crafter { export class HtmlElement { public: void* const ptr; - inline HtmlElement(const char* id, std::size_t idLenght): ptr(Bindings::GetElementById(id, idLenght)) { + std::vector handlers; + HtmlElement(const std::string_view id): ptr(CppDOM::Bindings::GetElementById(id)) { } - inline HtmlElement(const std::string& id): ptr(Bindings::GetElementById(id)) { - + HtmlElement(const std::string_view id, const std::string_view html): ptr(CppDOM::Bindings::GetElementById(id)) { + CppDOM::Bindings::SetInnerHTML(ptr, html); } - inline void SetInnerHTML(const char* html, std::size_t htmlLenght) { - Bindings::SetInnerHTML(ptr, html, htmlLenght); + void SetInnerHTML(const std::string_view& html) { + CppDOM::Bindings::SetInnerHTML(ptr, html); } - inline void SetInnerHTML(const std::string& html) { - Bindings::SetInnerHTML(ptr, html); + + // Event handling methods - simplified for now + int AddClickListener(std::function callback) { + int id = CppDOM::Bindings::clickHandlerMaxId++; + handlers.push_back(id); + CppDOM::Bindings::clickHandlers->insert({id, callback}); + CppDOM::Bindings::AddClickListener(ptr, id); + return id; } - inline ~HtmlElement(){ - Bindings::FreeJs(ptr); + + void RemoveClickListener(int id) { + handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); + CppDOM::Bindings::clickHandlers->erase(id); + CppDOM::Bindings::RemoveClickListener(ptr, id); + } + + ~HtmlElement(){ + for(int handler : handlers) { + CppDOM::Bindings::clickHandlers->erase(handler); + CppDOM::Bindings::RemoveClickListener(ptr, handler); + } + CppDOM::Bindings::FreeJs(ptr); } }; } \ No newline at end of file