resonantjs 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Demo.gif +0 -0
- package/README.md +89 -68
- package/example.html +13 -17
- package/package.json +1 -1
- package/resonant.js +22 -1
package/Demo.gif
ADDED
|
Binary file
|
package/README.md
CHANGED
|
@@ -7,9 +7,28 @@ Resonant.js is an open-source lightweight JavaScript framework that enables reac
|
|
|
7
7
|
- **Reactive Data Binding**: Automatically synchronize your data with the UI.
|
|
8
8
|
- **Dynamic List Rendering**: Easily render lists that react to data changes.
|
|
9
9
|
- **Bidirectional Input Binding**: Bind HTML input fields directly to your data model.
|
|
10
|
+
- **Efficient Conditional Updates**: Only evaluate conditional expressions tied to specific variable changes.
|
|
10
11
|
- **Lightweight and Easy to Integrate**: Minimal setup required to get started.
|
|
11
12
|
- **Compatible with Modern Browsers**: Works seamlessly across all modern web browsers.
|
|
12
13
|
|
|
14
|
+
## Installation
|
|
15
|
+
## NPM
|
|
16
|
+
To install via NPM, use the following command:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm i resonantjs
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## CDN
|
|
23
|
+
To use via CDN, include the following URLs in your HTML file:
|
|
24
|
+
|
|
25
|
+
```html
|
|
26
|
+
<script src="https://unpkg.com/resonantjs@latest/resonant.js"></script>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Demo
|
|
30
|
+

|
|
31
|
+
|
|
13
32
|
## Usage
|
|
14
33
|
Include resonant.js in your HTML file, and use the following example to understand how to integrate it into your web application.
|
|
15
34
|
|
|
@@ -18,79 +37,81 @@ Include resonant.js in your HTML file, and use the following example to understa
|
|
|
18
37
|
<html lang="en">
|
|
19
38
|
<head>
|
|
20
39
|
<title>Resonant.js Quick Demo</title>
|
|
21
|
-
<script src="
|
|
40
|
+
<script src="https://unpkg.com/resonantjs@latest/resonant.js"></script>
|
|
22
41
|
</head>
|
|
23
42
|
<body>
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
43
|
+
<h1>Resonant.js Quick Demo</h1>
|
|
44
|
+
|
|
45
|
+
<!-- Display and update a single item -->
|
|
46
|
+
<div>
|
|
47
|
+
<h2>Counter</h2>
|
|
48
|
+
<p>
|
|
49
|
+
Current count: <span res="counter"></span>
|
|
50
|
+
</p>
|
|
51
|
+
<div res-conditional="counter >= 5">
|
|
52
|
+
Only shows when counter is greater than or equal to 5
|
|
31
53
|
</div>
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
<li>
|
|
50
|
-
<span res-prop="name"></span> - <span res-prop="role"></span>
|
|
51
|
-
</li>
|
|
52
|
-
</ul>
|
|
53
|
-
<button onclick="addTeamMember()">Add Team Member</button>
|
|
54
|
+
<button onclick="counter++">Increment Counter</button>
|
|
55
|
+
</div>
|
|
56
|
+
|
|
57
|
+
<!-- Demonstrate object property binding -->
|
|
58
|
+
<div>
|
|
59
|
+
<h2>Person Information</h2>
|
|
60
|
+
<div res="person">
|
|
61
|
+
<span res-prop="firstname"></span>
|
|
62
|
+
<span res-prop="lastname"></span>
|
|
63
|
+
<br/>
|
|
64
|
+
<div res-conditional="person.firstname == 'Andrew' && person.lastname == 'Murgola'">
|
|
65
|
+
Only shows when firstname is Andrew and lastname is Murgola
|
|
66
|
+
</div>
|
|
67
|
+
<br/>
|
|
68
|
+
|
|
69
|
+
First Name: <input type="text" res-prop="firstname" />
|
|
70
|
+
Last Name: <input type="text" res-prop="lastname" />
|
|
54
71
|
</div>
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
72
|
+
</div>
|
|
73
|
+
|
|
74
|
+
<!-- Demonstrate dynamic list rendering -->
|
|
75
|
+
<div>
|
|
76
|
+
<h2>Team Members</h2>
|
|
77
|
+
<ul res="team">
|
|
78
|
+
<li>
|
|
79
|
+
<span res-prop="name"></span> - <span res-prop="role"></span>
|
|
80
|
+
</li>
|
|
81
|
+
</ul>
|
|
82
|
+
<button onclick="addTeamMember()">Add Team Member</button>
|
|
83
|
+
</div>
|
|
84
|
+
|
|
85
|
+
<script>
|
|
86
|
+
const resonantJs = new Resonant();
|
|
87
|
+
|
|
88
|
+
// Initialize a counter
|
|
89
|
+
resonantJs.add("counter", 0);
|
|
90
|
+
|
|
91
|
+
// Initialize a single object
|
|
92
|
+
resonantJs.add("person", {
|
|
93
|
+
firstname: "Andrew",
|
|
94
|
+
lastname: "Murgola"
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// Initialize an array of objects
|
|
98
|
+
resonantJs.add("team", [
|
|
99
|
+
{ name: "Alice", role: "Developer" },
|
|
100
|
+
{ name: "Bob", role: "Designer" }
|
|
101
|
+
]);
|
|
102
|
+
|
|
103
|
+
// Example of a callback
|
|
104
|
+
resonantJs.addCallback("person", (result) => {
|
|
105
|
+
console.log(result.firstname + " " + result.lastname);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
function addTeamMember() {
|
|
109
|
+
const newMember = { name: "Charlie", role: "Product Manager" };
|
|
110
|
+
team.push(newMember);
|
|
111
|
+
}
|
|
112
|
+
</script>
|
|
91
113
|
</body>
|
|
92
114
|
</html>
|
|
93
|
-
|
|
94
115
|
```
|
|
95
116
|
## Features Overview
|
|
96
117
|
|
|
@@ -98,7 +119,7 @@ Include resonant.js in your HTML file, and use the following example to understa
|
|
|
98
119
|
- **`res` and `res-prop` Attributes**: Bind HTML elements to your data model seamlessly.
|
|
99
120
|
- `res` is used to identify an overarching data model.
|
|
100
121
|
- `res-prop` links individual properties within that model to corresponding UI elements.
|
|
101
|
-
|
|
122
|
+
- **`res-conditional` Attribute**: Conditionally display elements based on the data model's properties.
|
|
102
123
|
- **Automatic UI Updates**: Changes to your JavaScript objects instantly reflect in the associated UI components, reducing manual DOM manipulation.
|
|
103
124
|
|
|
104
125
|
### Advanced Features
|
package/example.html
CHANGED
|
@@ -13,7 +13,10 @@
|
|
|
13
13
|
<p>
|
|
14
14
|
Current count: <span res="counter"></span>
|
|
15
15
|
</p>
|
|
16
|
-
<
|
|
16
|
+
<div res-conditional="counter >= 5">
|
|
17
|
+
Only shows when counter is greater than or equal to 5
|
|
18
|
+
</div>
|
|
19
|
+
<button onclick="counter++">Increment Counter</button>
|
|
17
20
|
</div>
|
|
18
21
|
|
|
19
22
|
<!-- Demonstrate object property binding -->
|
|
@@ -23,6 +26,9 @@
|
|
|
23
26
|
<span res-prop="firstname"></span>
|
|
24
27
|
<span res-prop="lastname"></span>
|
|
25
28
|
<br/>
|
|
29
|
+
<div res-conditional="person.firstname == 'Andrew' && person.lastname == 'Murgola'">
|
|
30
|
+
Only shows when firstname is Andrew and lastname is Murgola
|
|
31
|
+
</div>
|
|
26
32
|
<br/>
|
|
27
33
|
|
|
28
34
|
First Name: <input type="text" res-prop="firstname" />
|
|
@@ -47,32 +53,22 @@
|
|
|
47
53
|
// Initialize a counter
|
|
48
54
|
resonantJs.add("counter", 0);
|
|
49
55
|
|
|
50
|
-
|
|
51
|
-
console.log(result.firstname + " " + result.lastname);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Initialize a single person object
|
|
56
|
+
// Initialize a single object
|
|
55
57
|
resonantJs.add("person", {
|
|
56
|
-
firstname: "
|
|
58
|
+
firstname: "Andrew",
|
|
57
59
|
lastname: "Murgola"
|
|
58
60
|
});
|
|
59
61
|
|
|
60
|
-
// Initialize
|
|
62
|
+
// Initialize an array of objects
|
|
61
63
|
resonantJs.add("team", [
|
|
62
64
|
{ name: "Alice", role: "Developer" },
|
|
63
65
|
{ name: "Bob", role: "Designer" }
|
|
64
66
|
]);
|
|
65
67
|
|
|
66
68
|
// Example of a callback
|
|
67
|
-
resonantJs.addCallback("person",
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
counter++;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function updatePersonInfo(prop, value) {
|
|
74
|
-
person[prop] = value;
|
|
75
|
-
}
|
|
69
|
+
resonantJs.addCallback("person", (result) => {
|
|
70
|
+
console.log(result.firstname + " " + result.lastname);
|
|
71
|
+
});
|
|
76
72
|
|
|
77
73
|
function addTeamMember() {
|
|
78
74
|
const newMember = { name: "Charlie", role: "Product Manager" };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "resonantjs",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "A lightweight JavaScript framework that enables reactive data-binding for building dynamic and responsive web applications. It simplifies creating interactive UIs by automatically updating the DOM when your data changes.",
|
|
5
5
|
"main": "resonant.js",
|
|
6
6
|
"repository": {
|
package/resonant.js
CHANGED
|
@@ -33,6 +33,7 @@ class Resonant {
|
|
|
33
33
|
set: (target, property, value) => {
|
|
34
34
|
target[property] = value;
|
|
35
35
|
this.updateElement(parentName);
|
|
36
|
+
this.updateConditionalsFor(parentName);
|
|
36
37
|
return true;
|
|
37
38
|
}
|
|
38
39
|
});
|
|
@@ -41,7 +42,7 @@ class Resonant {
|
|
|
41
42
|
_createArray(variableName, arr) {
|
|
42
43
|
return new Proxy(arr, {
|
|
43
44
|
get: (target, index) => {
|
|
44
|
-
if (typeof target[index] === 'object') {
|
|
45
|
+
if (typeof target[index] === 'object' && !target[index][Symbol('isProxy')]) {
|
|
45
46
|
target[index] = this._createObject(`${variableName}[${index}]`, target[index]);
|
|
46
47
|
}
|
|
47
48
|
return target[index];
|
|
@@ -49,6 +50,7 @@ class Resonant {
|
|
|
49
50
|
set: (target, index, value) => {
|
|
50
51
|
target[index] = value;
|
|
51
52
|
this.updateElement(variableName);
|
|
53
|
+
this.updateConditionalsFor(variableName);
|
|
52
54
|
return true;
|
|
53
55
|
}
|
|
54
56
|
});
|
|
@@ -60,6 +62,7 @@ class Resonant {
|
|
|
60
62
|
set: (newValue) => {
|
|
61
63
|
this._assignValueToData(variableName, newValue);
|
|
62
64
|
this.updateElement(variableName);
|
|
65
|
+
this.updateConditionalsFor(variableName);
|
|
63
66
|
}
|
|
64
67
|
});
|
|
65
68
|
}
|
|
@@ -91,11 +94,29 @@ class Resonant {
|
|
|
91
94
|
}
|
|
92
95
|
});
|
|
93
96
|
|
|
97
|
+
// Call the variable-specific condition update
|
|
98
|
+
this.updateConditionalsFor(variableName);
|
|
99
|
+
|
|
94
100
|
if (this.callbacks[variableName]) {
|
|
95
101
|
this.callbacks[variableName](value);
|
|
96
102
|
}
|
|
97
103
|
}
|
|
98
104
|
|
|
105
|
+
updateConditionalsFor(variableName) {
|
|
106
|
+
const conditionalElements = document.querySelectorAll(`[res-conditional*="${variableName}"]`);
|
|
107
|
+
conditionalElements.forEach(conditionalElement => {
|
|
108
|
+
const condition = conditionalElement.getAttribute('res-conditional');
|
|
109
|
+
try {
|
|
110
|
+
if (eval(condition)) {
|
|
111
|
+
conditionalElement.style.display = '';
|
|
112
|
+
} else {
|
|
113
|
+
conditionalElement.style.display = 'none';
|
|
114
|
+
}
|
|
115
|
+
} catch (e) {
|
|
116
|
+
console.error(`Error evaluating condition for ${variableName}: ${condition}`, e);
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
}
|
|
99
120
|
|
|
100
121
|
_renderArray(variableName, el) {
|
|
101
122
|
let template = el.cloneNode(true);
|