Skip to content

Commit 1b29ea1

Browse files
committed
working on documentation
1 parent 6c5d692 commit 1b29ea1

1 file changed

Lines changed: 123 additions & 7 deletions

File tree

docs/osm.md

Lines changed: 123 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,81 @@ The `h` object is a **Proxy**. When you access a property on it (e.g., `h.div`,
2424
2525
## Attributes & Properties
2626

27-
You can pass attributes as the first argument to the tag function if it is an object (and not a DOM node or State).
27+
Attributes can be passed as **objects** at any point in the argument list. OpenScript treats any argument that is an object (and not a DOM Node or State) as an attributes object.
2828

2929
```javascript
30-
h.a(
30+
// Attributes can be anywhere
31+
h.div("Text first", { id: "my-div" }, " More text");
32+
33+
// Multiple attributes objects are merged
34+
// Note: Underscores in keys are converted to dashes (data_role -> data-role)
35+
h.div({ id: "main" }, "Content", { data_role: "wrapper" });
36+
```
37+
38+
### Class Merging
39+
40+
Special attributes like `class` are intelligently handled. If you pass multiple class attributes (in different objects), they are **concatenated** rather than overwritten.
41+
42+
```javascript
43+
h.div({ class: "btn" }, "Click Me", { class: "btn-primary" });
44+
// Output: <div class="btn btn-primary">Click Me</div>
45+
```
46+
47+
### Event Handling & Memory Safety
48+
49+
> [!WARNING]
50+
> **Avoid `addEventListener`**: Do not use the standard `element.addEventListener` methods on nodes created by OpenScript. Doing so can lead to memory leaks because the framework cannot track and automatically remove these listeners when the component is unmounted.
51+
52+
Instead, always use the `listeners` attribute object. OpenScript modifies the DOM nodes to include safe `addListener` and `removeListener` methods that integrate with the framework's lifecycle management.
53+
54+
```javascript
55+
h.button(
56+
{
57+
listeners: {
58+
click: (e) => console.log("Safe click", e),
59+
},
60+
},
61+
"Safe Button",
62+
);
63+
```
64+
65+
### Extending Node Functionality (`methods`)
66+
67+
You can attach custom methods to a DOM node at runtime using the `methods` attribute. This is useful for exposing logic that needs to be called externally (e.g., after retrieving the node via `document.getElementById`).
68+
69+
```javascript
70+
h.div(
3171
{
32-
href: "https://example.com",
33-
class: "link primary",
34-
target: "_blank",
35-
id: "main-link",
72+
id: "my-widget",
73+
methods: {
74+
refresh: function () {
75+
this.innerHTML = "Refreshed!"; // 'this' refers to the DOM element
76+
},
77+
getData: () => ({ id: 1, value: "test" }),
78+
},
3679
},
37-
"Visit Example",
80+
"Widget Content",
3881
);
82+
83+
// Usage elsewhere:
84+
const widget = document.getElementById("my-widget");
85+
if (widget) {
86+
widget.methods().refresh();
87+
}
88+
```
89+
90+
### Inline Function Calls (`h.func`)
91+
92+
The `h.func` helper formats a function and its arguments as a string, suitable for placement in inline event attributes (like `onclick`). This is how you pass function calls into string-based attributes.
93+
94+
```javascript
95+
// In a component
96+
render() {
97+
return h.div({
98+
// Generates: onclick="greet('Levi', 42)"
99+
onclick: h.func("greet", "Levi", 42)
100+
}, "Click to Greet")
101+
}
39102
```
40103

41104
### Boolean Attributes
@@ -74,3 +137,56 @@ Strings and numbers are automatically converted to text nodes.
74137
```javascript
75138
h.p("You have ", 5, " notifications.");
76139
```
140+
141+
## Logic & Helpers
142+
143+
OpenScript provides helper functions to handle logic like iterations and conditionals directly within your markup structure.
144+
145+
### Executing Logic (`h.call`)
146+
147+
If you need to run arbitrary logic during the creation of the node structure, you can use `h.call(callback)`. The callback should return a valid OSM node (string, element, or array).
148+
149+
```javascript
150+
h.div(
151+
{ class: "container" },
152+
h.call(() => {
153+
// Perform complex logic here
154+
const date = new Date();
155+
return h.span(`Created at: ${date.toLocaleTimeString()}`);
156+
}),
157+
);
158+
```
159+
160+
### Iteration (`each`)
161+
162+
The `each` helper iterates over an array or object and returns an array of results.
163+
164+
```javascript
165+
import { app, each } from "modular-openscriptjs";
166+
167+
const items = ["Apple", "Banana", "Cherry"];
168+
169+
h.ul(
170+
each(items, (item, index) => {
171+
return h.li({ "data-index": index }, item);
172+
}),
173+
);
174+
```
175+
176+
### Conditionals (`ifElse`)
177+
178+
The `ifElse` helper (or `Utils.ifElse`) allows you to conditionally render content.
179+
180+
```javascript
181+
import { app, ifElse } from "modular-openscriptjs";
182+
183+
const isLoggedIn = true;
184+
185+
h.div(
186+
ifElse(
187+
isLoggedIn,
188+
() => h.button("Logout"), // True branch (function executed)
189+
h.button("Login"), // False branch (value returned)
190+
),
191+
);
192+
```

0 commit comments

Comments
 (0)