click event
This commit is contained in:
parent
e35b7302cb
commit
f40afe684a
13 changed files with 151 additions and 20 deletions
Binary file not shown.
Binary file not shown.
BIN
Crafter.CppDOM.o
BIN
Crafter.CppDOM.o
Binary file not shown.
|
|
@ -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,
|
||||
addClickListener: addClickListener,
|
||||
removeClickListener: removeClickListener,
|
||||
}
|
||||
|
||||
window.crafter_webbuild_env = env;
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import Crafter.CppDOM;
|
||||
using namespace Crafter::CppDOM;
|
||||
using namespace Crafter;
|
||||
|
||||
int main(){
|
||||
HtmlElement body("body");
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
"name": "main",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "example",
|
||||
"name": "executable",
|
||||
"implementations": ["main"],
|
||||
"target": "wasm32-wasi",
|
||||
"debug" : true,
|
||||
|
|
|
|||
39
examples/InteractiveElement/README.md
Normal file
39
examples/InteractiveElement/README.md
Normal file
|
|
@ -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("<h1>Interactive Element Demo</h1>"
|
||||
"<button id='myButton'>Click Me!</button>"
|
||||
"<p id='output'>Click the button above</p>");
|
||||
|
||||
// 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.
|
||||
16
examples/InteractiveElement/main.cpp
Normal file
16
examples/InteractiveElement/main.cpp
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
import Crafter.CppDOM;
|
||||
import std;
|
||||
using namespace Crafter;
|
||||
|
||||
HtmlElement 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
|
||||
|
||||
|
||||
int main() {
|
||||
button->AddClickListener([](){
|
||||
auto output = HtmlElement("output");
|
||||
output.SetInnerHTML("Button was clicked!");
|
||||
});
|
||||
}
|
||||
17
examples/InteractiveElement/project.json
Normal file
17
examples/InteractiveElement/project.json
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"name": "main",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "executable",
|
||||
"implementations": ["main"],
|
||||
"target": "wasm32-wasi",
|
||||
"debug" : true,
|
||||
"dependencies": [
|
||||
{
|
||||
"path":"../../project.json",
|
||||
"configuration":"lib-debug"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
1
examples/InteractiveElement/run.sh
Executable file
1
examples/InteractiveElement/run.sh
Executable file
|
|
@ -0,0 +1 @@
|
|||
caddy file-server --listen :8080 --root bin/executable
|
||||
|
|
@ -22,13 +22,26 @@ export module Crafter.CppDOM:Bindings;
|
|||
import std;
|
||||
|
||||
export namespace Crafter::CppDOM::Bindings {
|
||||
int clickHandlerMaxId = 0;
|
||||
std::unordered_map<int, std::function<void(void)>>* clickHandlers = new std::unordered_map<int, std::function<void(void)>>();
|
||||
|
||||
__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<int>(a))->second();
|
||||
}
|
||||
}
|
||||
|
|
@ -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<int> 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);
|
||||
}
|
||||
void SetInnerHTML(const std::string_view& html) {
|
||||
CppDOM::Bindings::SetInnerHTML(ptr, html);
|
||||
}
|
||||
|
||||
// Event handling methods - simplified for now
|
||||
int AddClickListener(std::function<void(void)> callback) {
|
||||
int id = CppDOM::Bindings::clickHandlerMaxId++;
|
||||
handlers.push_back(id);
|
||||
CppDOM::Bindings::clickHandlers->insert({id, callback});
|
||||
CppDOM::Bindings::AddClickListener(ptr, id);
|
||||
return id;
|
||||
}
|
||||
inline void SetInnerHTML(const char* html, std::size_t htmlLenght) {
|
||||
Bindings::SetInnerHTML(ptr, html, htmlLenght);
|
||||
|
||||
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);
|
||||
}
|
||||
inline void SetInnerHTML(const std::string& html) {
|
||||
Bindings::SetInnerHTML(ptr, html);
|
||||
|
||||
~HtmlElement(){
|
||||
for(int handler : handlers) {
|
||||
CppDOM::Bindings::clickHandlers->erase(handler);
|
||||
CppDOM::Bindings::RemoveClickListener(ptr, handler);
|
||||
}
|
||||
inline ~HtmlElement(){
|
||||
Bindings::FreeJs(ptr);
|
||||
CppDOM::Bindings::FreeJs(ptr);
|
||||
}
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue