@cocreate/elements 1.41.0 → 1.42.0
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/CHANGELOG.md +23 -0
- package/package.json +1 -1
- package/src/fetchSrc.js +140 -149
- package/src/form.js +29 -12
- package/src/index.js +58 -31
- package/src/value.js +115 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,26 @@
|
|
|
1
|
+
# [1.42.0](https://github.com/CoCreate-app/CoCreate-elements/compare/v1.41.1...v1.42.0) (2025-04-11)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* $relativePath handeling ([e9d41df](https://github.com/CoCreate-app/CoCreate-elements/commit/e9d41df24291083acc2bd5fa928c6b8b621e8f7c))
|
|
7
|
+
* handeling onRest ([ba102ce](https://github.com/CoCreate-app/CoCreate-elements/commit/ba102cedec35c41f1a974d0f62de3670ed40105e))
|
|
8
|
+
* update observer obseve param to type and and attributeName to attributeFilter ([3ce1a06](https://github.com/CoCreate-app/CoCreate-elements/commit/3ce1a0615fd16eeacc24b89c722593d7a470a566))
|
|
9
|
+
* update to how action is handled ([25f2654](https://github.com/CoCreate-app/CoCreate-elements/commit/25f26548618397c3cbae0469ff284ca1be5a8a7b))
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
### Features
|
|
13
|
+
|
|
14
|
+
* value-selectors to get value from target element ([e3ae15b](https://github.com/CoCreate-app/CoCreate-elements/commit/e3ae15b5e0d2d953399bd45dc82ea44aa7aa6cde))
|
|
15
|
+
|
|
16
|
+
## [1.41.1](https://github.com/CoCreate-app/CoCreate-elements/compare/v1.41.0...v1.41.1) (2025-01-18)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
### Bug Fixes
|
|
20
|
+
|
|
21
|
+
* path handling ([1276f2d](https://github.com/CoCreate-app/CoCreate-elements/commit/1276f2d3988ec556ce95d3166596526d9d5851c3))
|
|
22
|
+
* sum handling ([86f1e74](https://github.com/CoCreate-app/CoCreate-elements/commit/86f1e74af2e14b51b925e36fd22b2935796073fa))
|
|
23
|
+
|
|
1
24
|
# [1.41.0](https://github.com/CoCreate-app/CoCreate-elements/compare/v1.40.1...v1.41.0) (2025-01-02)
|
|
2
25
|
|
|
3
26
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cocreate/elements",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.42.0",
|
|
4
4
|
"description": "Fetch content into any html element by using html5 attributes to query data stored in CoCreate headless CMS. If data is changed it will instantly reflect in html tags as changes are broadcasted in realtime",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"elements",
|
package/src/fetchSrc.js
CHANGED
|
@@ -22,159 +22,137 @@ async function initElements(elements) {
|
|
|
22
22
|
if (!src || /{{\s*([\w\W]+)\s*}}/g.test(src)) continue;
|
|
23
23
|
|
|
24
24
|
let initialize = initializing.get(element);
|
|
25
|
-
if (
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
"updateend",
|
|
49
|
-
() => {
|
|
50
|
-
console.log(
|
|
51
|
-
"Update ended, buffered ranges:",
|
|
52
|
-
sourceBuffer.buffered
|
|
53
|
-
);
|
|
54
|
-
if (
|
|
55
|
-
!sourceBuffer.updating &&
|
|
56
|
-
mediaSource.readyState ===
|
|
57
|
-
"open"
|
|
58
|
-
) {
|
|
59
|
-
mediaSource.endOfStream();
|
|
60
|
-
|
|
61
|
-
element.addEventListener(
|
|
62
|
-
"ended",
|
|
63
|
-
() => {
|
|
64
|
-
URL.revokeObjectURL(
|
|
65
|
-
element.src
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
);
|
|
72
|
-
sourceBuffer.addEventListener(
|
|
73
|
-
"error",
|
|
74
|
-
(e) => {
|
|
75
|
-
console.error(
|
|
76
|
-
"SourceBuffer error event:",
|
|
77
|
-
e
|
|
78
|
-
);
|
|
79
|
-
console.log(
|
|
80
|
-
"MediaSource readyState:",
|
|
81
|
-
mediaSource.readyState
|
|
82
|
-
);
|
|
83
|
-
console.log(
|
|
84
|
-
"SourceBuffer updating:",
|
|
85
|
-
sourceBuffer.updating
|
|
86
|
-
);
|
|
87
|
-
console.log(
|
|
88
|
-
"SourceBuffer buffered ranges:",
|
|
89
|
-
sourceBuffer.buffered
|
|
90
|
-
);
|
|
91
|
-
// Any other state information you can log
|
|
92
|
-
}
|
|
93
|
-
);
|
|
94
|
-
|
|
95
|
-
getSegment(
|
|
96
|
-
sourceBuffer,
|
|
97
|
-
mediaConfig.segments[0]
|
|
98
|
-
);
|
|
99
|
-
}
|
|
100
|
-
);
|
|
101
|
-
|
|
102
|
-
mediaSource.addEventListener("sourceended", () => {
|
|
103
|
-
console.log("MediaSource ended event fired");
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
mediaSource.addEventListener("sourceclose", () => {
|
|
107
|
-
console.log("MediaSource close event fired");
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
// Event listener for seeking
|
|
111
|
-
element.addEventListener("seeking", () => {
|
|
112
|
-
let currentTime = element.currentTime;
|
|
113
|
-
let chunkIndex = Math.floor(
|
|
114
|
-
currentTime / chunkDuration
|
|
115
|
-
);
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
// Event listener for seeked
|
|
119
|
-
element.addEventListener("seeked", () => {
|
|
120
|
-
let currentTime = element.currentTime;
|
|
121
|
-
if (isBuffered(element, currentTime)) return;
|
|
122
|
-
|
|
123
|
-
let query = {
|
|
124
|
-
start: { $lte: currentTime },
|
|
125
|
-
end: { $gte: currentTime }
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
let segments = queryData(
|
|
129
|
-
mediaConfig.segments,
|
|
130
|
-
query
|
|
131
|
-
);
|
|
132
|
-
for (let segment of segments) {
|
|
133
|
-
getSegment(sourceBuffer, segment);
|
|
134
|
-
}
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
element.addEventListener("timeupdate", function () {
|
|
138
|
-
const bufferEnd = element.buffered.end(0);
|
|
139
|
-
const currentTime = element.currentTime;
|
|
140
|
-
const threshold = 10; // seconds before buffer end to fetch the next segment
|
|
141
|
-
|
|
142
|
-
if (bufferEnd - currentTime < threshold) {
|
|
143
|
-
// Time to fetch the next segment
|
|
144
|
-
getSegment(sourceBuffer, mediaConfig);
|
|
145
|
-
}
|
|
146
|
-
});
|
|
147
|
-
} catch (error) {
|
|
148
|
-
element.src = src;
|
|
149
|
-
// let blob = await response.json();
|
|
150
|
-
// URL.createObjectURL(blob);
|
|
151
|
-
}
|
|
152
|
-
} else if (element.hasAttribute("rendered")) {
|
|
153
|
-
element.removeAttribute("rendered");
|
|
154
|
-
// let path = element.getAttribute("path");
|
|
155
|
-
// if (path) {
|
|
156
|
-
// let elements = element.querySelectorAll("[src]");
|
|
157
|
-
// for (let i = 0; i < elements.length; i++) {
|
|
158
|
-
// text = text.replaceAll("{{path}}", path);
|
|
159
|
-
// }
|
|
160
|
-
// }
|
|
161
|
-
} else {
|
|
162
|
-
let text = await response.text();
|
|
163
|
-
if (text) {
|
|
164
|
-
let path = element.getAttribute("path");
|
|
165
|
-
if (path) text = text.replaceAll("{{path}}", path);
|
|
166
|
-
element.setValue(text);
|
|
167
|
-
initializing.delete(element);
|
|
168
|
-
}
|
|
25
|
+
if (initialize && initialize.src === src) continue;
|
|
26
|
+
|
|
27
|
+
initializing.set(element, { src });
|
|
28
|
+
try {
|
|
29
|
+
let state = localStorage.getItem("state"); // Assume this is your state object
|
|
30
|
+
let response = await fetch(src, {
|
|
31
|
+
headers: {
|
|
32
|
+
"X-State": state // Custom header to send state
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
if (element.tagName === "AUDIO" || element.tagName === "VIDEO") {
|
|
37
|
+
initMediaSource(element, src);
|
|
38
|
+
} else {
|
|
39
|
+
element.removeAttribute("rendered");
|
|
40
|
+
|
|
41
|
+
let text = await response.text();
|
|
42
|
+
if (text) {
|
|
43
|
+
let pathElement = element.closest("[path]");
|
|
44
|
+
if (pathElement) {
|
|
45
|
+
let path =
|
|
46
|
+
pathElement.getAttribute("path") || getPath();
|
|
47
|
+
if (path) text = text.replaceAll("$relativePath", path);
|
|
169
48
|
}
|
|
170
|
-
|
|
171
|
-
|
|
49
|
+
element.setValue(text);
|
|
50
|
+
initializing.delete(element);
|
|
172
51
|
}
|
|
173
52
|
}
|
|
53
|
+
} catch (err) {
|
|
54
|
+
console.log("FetchSrc error:" + err);
|
|
174
55
|
}
|
|
175
56
|
}
|
|
176
57
|
}
|
|
177
58
|
|
|
59
|
+
function getPath() {
|
|
60
|
+
let currentPath = window.location.pathname.replace(/\/[^\/]*$/, ""); // Remove file from path
|
|
61
|
+
let depth = currentPath.split("/").filter(Boolean).length; // Count depth levels
|
|
62
|
+
|
|
63
|
+
return depth > 0 ? "../".repeat(depth) : "./"; // Return the correct relative path
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async function initMediaSource(element, src) {
|
|
67
|
+
try {
|
|
68
|
+
let mediaConfig = await response.json();
|
|
69
|
+
let sourceBuffer;
|
|
70
|
+
|
|
71
|
+
const mediaSource = new MediaSource();
|
|
72
|
+
element.src = URL.createObjectURL(mediaSource);
|
|
73
|
+
mediaSource.addEventListener("sourceopen", async () => {
|
|
74
|
+
sourceBuffer = mediaSource.addSourceBuffer(
|
|
75
|
+
`${mediaConfig["content-type"]}; codecs="${mediaConfig.codecs}"`
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
sourceBuffer.addEventListener("updateend", () => {
|
|
79
|
+
console.log(
|
|
80
|
+
"Update ended, buffered ranges:",
|
|
81
|
+
sourceBuffer.buffered
|
|
82
|
+
);
|
|
83
|
+
if (
|
|
84
|
+
!sourceBuffer.updating &&
|
|
85
|
+
mediaSource.readyState === "open"
|
|
86
|
+
) {
|
|
87
|
+
mediaSource.endOfStream();
|
|
88
|
+
|
|
89
|
+
element.addEventListener("ended", () => {
|
|
90
|
+
URL.revokeObjectURL(element.src);
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
sourceBuffer.addEventListener("error", (e) => {
|
|
96
|
+
console.error("SourceBuffer error event:", e);
|
|
97
|
+
console.log("MediaSource readyState:", mediaSource.readyState);
|
|
98
|
+
console.log("SourceBuffer updating:", sourceBuffer.updating);
|
|
99
|
+
console.log(
|
|
100
|
+
"SourceBuffer buffered ranges:",
|
|
101
|
+
sourceBuffer.buffered
|
|
102
|
+
);
|
|
103
|
+
// Any other state information you can log
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
getSegment(sourceBuffer, mediaConfig.segments[0]);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
mediaSource.addEventListener("sourceended", () => {
|
|
110
|
+
console.log("MediaSource ended event fired");
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
mediaSource.addEventListener("sourceclose", () => {
|
|
114
|
+
console.log("MediaSource close event fired");
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
// Event listener for seeking
|
|
118
|
+
element.addEventListener("seeking", () => {
|
|
119
|
+
let currentTime = element.currentTime;
|
|
120
|
+
let chunkIndex = Math.floor(currentTime / chunkDuration);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// Event listener for seeked
|
|
124
|
+
element.addEventListener("seeked", () => {
|
|
125
|
+
let currentTime = element.currentTime;
|
|
126
|
+
if (isBuffered(element, currentTime)) return;
|
|
127
|
+
|
|
128
|
+
let query = {
|
|
129
|
+
start: { $lte: currentTime },
|
|
130
|
+
end: { $gte: currentTime }
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
let segments = queryData(mediaConfig.segments, query);
|
|
134
|
+
for (let segment of segments) {
|
|
135
|
+
getSegment(sourceBuffer, segment);
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
element.addEventListener("timeupdate", function () {
|
|
140
|
+
const bufferEnd = element.buffered.end(0);
|
|
141
|
+
const currentTime = element.currentTime;
|
|
142
|
+
const threshold = 10; // seconds before buffer end to fetch the next segment
|
|
143
|
+
|
|
144
|
+
if (bufferEnd - currentTime < threshold) {
|
|
145
|
+
// Time to fetch the next segment
|
|
146
|
+
getSegment(sourceBuffer, mediaConfig);
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
} catch (error) {
|
|
150
|
+
element.src = src;
|
|
151
|
+
// let blob = await response.json();
|
|
152
|
+
// URL.createObjectURL(blob);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
178
156
|
async function getSegment(sourceBuffer, segment) {
|
|
179
157
|
// TODO: use socket/crud/file with room using the url to get one or more segments and append
|
|
180
158
|
let segments = [];
|
|
@@ -262,17 +240,30 @@ function base64ToArrayBuffer(base64) {
|
|
|
262
240
|
|
|
263
241
|
observer.init({
|
|
264
242
|
name: "CoCreateSrc",
|
|
265
|
-
|
|
243
|
+
types: ["addedNodes"],
|
|
266
244
|
selector: selector,
|
|
267
245
|
callback: function (mutation) {
|
|
268
246
|
init(mutation.target);
|
|
269
247
|
}
|
|
270
248
|
});
|
|
271
249
|
|
|
250
|
+
observer.init({
|
|
251
|
+
name: "CoCreateSrcOperator",
|
|
252
|
+
types: ["addedNodes"],
|
|
253
|
+
selector: "img",
|
|
254
|
+
// selector: "img, video, audio, script, input, iframe, frame, link, source",
|
|
255
|
+
callback: function (mutation) {
|
|
256
|
+
let src = mutation.target.getAttribute("src");
|
|
257
|
+
if (src) {
|
|
258
|
+
mutation.target.setAttribute("src", src);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
|
|
272
263
|
observer.init({
|
|
273
264
|
name: "CoCreateSrcAttributes",
|
|
274
|
-
|
|
275
|
-
|
|
265
|
+
types: ["attributes"],
|
|
266
|
+
attributeFilter: ["src"],
|
|
276
267
|
selector: selector,
|
|
277
268
|
callback: function (mutation) {
|
|
278
269
|
if (
|
package/src/form.js
CHANGED
|
@@ -21,11 +21,18 @@ function init(elements) {
|
|
|
21
21
|
setAttribute(element);
|
|
22
22
|
disableAutoFill(element);
|
|
23
23
|
setValue(element);
|
|
24
|
+
|
|
24
25
|
element.addEventListener("submit", function (event) {
|
|
25
26
|
if (!element.hasAttribute("action")) {
|
|
26
27
|
event.preventDefault();
|
|
27
28
|
}
|
|
28
29
|
});
|
|
30
|
+
|
|
31
|
+
// Handle form reset event
|
|
32
|
+
element.addEventListener("reset", function (event) {
|
|
33
|
+
event.preventDefault(); // Prevent default reset
|
|
34
|
+
reset({ form: event.target }); // Call custom reset logic
|
|
35
|
+
});
|
|
29
36
|
}
|
|
30
37
|
}
|
|
31
38
|
|
|
@@ -93,7 +100,9 @@ function disableAutoFill(element) {
|
|
|
93
100
|
/**
|
|
94
101
|
* @param form
|
|
95
102
|
*/
|
|
96
|
-
function reset(
|
|
103
|
+
function reset(action) {
|
|
104
|
+
let form = action.form;
|
|
105
|
+
|
|
97
106
|
// Convert the form elements collection to an array
|
|
98
107
|
const formElementsArray = Array.from(form.elements);
|
|
99
108
|
|
|
@@ -127,7 +136,13 @@ function reset(form) {
|
|
|
127
136
|
element.value ||
|
|
128
137
|
element.getAttribute("value")
|
|
129
138
|
);
|
|
130
|
-
if (!resetType || resetType === "value")
|
|
139
|
+
if (!resetType || resetType === "value") {
|
|
140
|
+
if (element.contentEditable === "true") {
|
|
141
|
+
element.innerHTML = "";
|
|
142
|
+
} else {
|
|
143
|
+
element.setValue("");
|
|
144
|
+
}
|
|
145
|
+
}
|
|
131
146
|
}
|
|
132
147
|
|
|
133
148
|
if (form.hasAttribute("object")) form.setAttribute("object", "");
|
|
@@ -141,11 +156,13 @@ function reset(form) {
|
|
|
141
156
|
});
|
|
142
157
|
|
|
143
158
|
// Dispatch a custom reset event
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
159
|
+
if (action.element) {
|
|
160
|
+
action.element.dispatchEvent(
|
|
161
|
+
new CustomEvent("reset", {
|
|
162
|
+
detail: {}
|
|
163
|
+
})
|
|
164
|
+
);
|
|
165
|
+
}
|
|
149
166
|
}
|
|
150
167
|
|
|
151
168
|
function setValue(form) {
|
|
@@ -166,15 +183,15 @@ function setValue(form) {
|
|
|
166
183
|
|
|
167
184
|
Observer.init({
|
|
168
185
|
name: "CoCreateForm",
|
|
169
|
-
|
|
186
|
+
types: ["addedNodes"],
|
|
170
187
|
selector: "form",
|
|
171
188
|
callback: (mutation) => init(mutation.target)
|
|
172
189
|
});
|
|
173
190
|
|
|
174
191
|
Observer.init({
|
|
175
192
|
name: "CoCreateForm",
|
|
176
|
-
|
|
177
|
-
|
|
193
|
+
types: ["attributes"],
|
|
194
|
+
attributeFilter: getAttributeNames([
|
|
178
195
|
"organization_id",
|
|
179
196
|
"host",
|
|
180
197
|
"storage",
|
|
@@ -190,7 +207,7 @@ Observer.init({
|
|
|
190
207
|
|
|
191
208
|
Observer.init({
|
|
192
209
|
name: "CoCreateFormElements",
|
|
193
|
-
|
|
210
|
+
types: ["addedNodes"],
|
|
194
211
|
selector:
|
|
195
212
|
"[organization_id], [host], [storage], [database], [array], [index], [object], [key]",
|
|
196
213
|
callback: function (mutation) {
|
|
@@ -203,7 +220,7 @@ Action.init({
|
|
|
203
220
|
name: "reset",
|
|
204
221
|
endEvent: "reset",
|
|
205
222
|
callback: (action) => {
|
|
206
|
-
if (action.form) reset(action
|
|
223
|
+
if (action.form) reset(action);
|
|
207
224
|
}
|
|
208
225
|
});
|
|
209
226
|
|
package/src/index.js
CHANGED
|
@@ -40,6 +40,7 @@ import { render, renderValue, renderedNodes } from "@cocreate/render";
|
|
|
40
40
|
import "@cocreate/element-prototype";
|
|
41
41
|
import "./fetchSrc";
|
|
42
42
|
import { reset } from "./form";
|
|
43
|
+
import "./value.js";
|
|
43
44
|
|
|
44
45
|
const selector = "[storage], [database], [array], [render-json]";
|
|
45
46
|
const elements = new Map();
|
|
@@ -462,7 +463,12 @@ async function filterData(element, data, type, key) {
|
|
|
462
463
|
}
|
|
463
464
|
|
|
464
465
|
let property = key;
|
|
465
|
-
if (operator)
|
|
466
|
+
if (operator) {
|
|
467
|
+
property = property.replace(operator + ".", "");
|
|
468
|
+
if (operator === "$sum") {
|
|
469
|
+
value = 0;
|
|
470
|
+
}
|
|
471
|
+
}
|
|
466
472
|
if (Array.isArray(data[type])) {
|
|
467
473
|
let Data = [],
|
|
468
474
|
isObject;
|
|
@@ -480,8 +486,12 @@ async function filterData(element, data, type, key) {
|
|
|
480
486
|
}
|
|
481
487
|
let docValue = getValueFromObject(doc, property);
|
|
482
488
|
if (docValue) {
|
|
483
|
-
if (
|
|
484
|
-
|
|
489
|
+
if (operator === "$sum" && typeof docValue === "number") {
|
|
490
|
+
if (typeof value !== "number") value = 0;
|
|
491
|
+
value += docValue || 0;
|
|
492
|
+
} else if (Array.isArray(docValue)) {
|
|
493
|
+
Data.push(...docValue);
|
|
494
|
+
} else {
|
|
485
495
|
isObject = true;
|
|
486
496
|
Data.push(docValue);
|
|
487
497
|
}
|
|
@@ -496,11 +506,11 @@ async function filterData(element, data, type, key) {
|
|
|
496
506
|
// data = { [property]: Data[0] }
|
|
497
507
|
// } else
|
|
498
508
|
if (!operator) data = Data;
|
|
499
|
-
else if (operator === "$sum") {
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
}
|
|
509
|
+
// else if (operator === "$sum") {
|
|
510
|
+
// value = data[type].reduce((accumulator, currentValue) => {
|
|
511
|
+
// return accumulator + currentValue;
|
|
512
|
+
// }, 0);
|
|
513
|
+
// }
|
|
504
514
|
} else {
|
|
505
515
|
data = { [property]: data[type][property] };
|
|
506
516
|
}
|
|
@@ -1006,7 +1016,7 @@ async function getData(form) {
|
|
|
1006
1016
|
return dataArray;
|
|
1007
1017
|
}
|
|
1008
1018
|
|
|
1009
|
-
async function save(element) {
|
|
1019
|
+
async function save(element, action) {
|
|
1010
1020
|
if (!element) return;
|
|
1011
1021
|
let data, value;
|
|
1012
1022
|
let upsert = element.getAttribute("upsert");
|
|
@@ -1112,19 +1122,28 @@ async function save(element) {
|
|
|
1112
1122
|
(data[i].type !== "object" &&
|
|
1113
1123
|
data[i].method.endsWith(".update")))
|
|
1114
1124
|
) {
|
|
1115
|
-
setTypeValue(element, data[i]);
|
|
1116
|
-
} else if (data[i])
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1125
|
+
setTypeValue(element, data[i], action);
|
|
1126
|
+
} else if (data[i]) {
|
|
1127
|
+
if (action) {
|
|
1128
|
+
action.element.dispatchEvent(
|
|
1129
|
+
new CustomEvent("saved", {
|
|
1130
|
+
detail: data
|
|
1131
|
+
})
|
|
1132
|
+
);
|
|
1133
|
+
} else {
|
|
1134
|
+
document.dispatchEvent(
|
|
1135
|
+
new CustomEvent("saved", {
|
|
1136
|
+
detail: data
|
|
1137
|
+
})
|
|
1138
|
+
);
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1122
1141
|
}
|
|
1123
1142
|
|
|
1124
1143
|
return Data;
|
|
1125
1144
|
}
|
|
1126
1145
|
|
|
1127
|
-
function setTypeValue(element, data) {
|
|
1146
|
+
function setTypeValue(element, data, action) {
|
|
1128
1147
|
// TODO: if an array name is updated, the attibute array="" needs to be updated.
|
|
1129
1148
|
|
|
1130
1149
|
if (!data) return;
|
|
@@ -1160,7 +1179,7 @@ function setTypeValue(element, data) {
|
|
|
1160
1179
|
}
|
|
1161
1180
|
setData(Array.from(elements.keys()), data);
|
|
1162
1181
|
|
|
1163
|
-
// const state_ids = new Map()
|
|
1182
|
+
// const state_ids = new Map()
|
|
1164
1183
|
|
|
1165
1184
|
// let state_id = form.getAttribute('state_id');
|
|
1166
1185
|
// if (state_id) {
|
|
@@ -1213,11 +1232,19 @@ function setTypeValue(element, data) {
|
|
|
1213
1232
|
// }
|
|
1214
1233
|
}
|
|
1215
1234
|
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1235
|
+
if (action) {
|
|
1236
|
+
action.element.dispatchEvent(
|
|
1237
|
+
new CustomEvent("saved", {
|
|
1238
|
+
detail: data
|
|
1239
|
+
})
|
|
1240
|
+
);
|
|
1241
|
+
} else {
|
|
1242
|
+
document.dispatchEvent(
|
|
1243
|
+
new CustomEvent("saved", {
|
|
1244
|
+
detail: data
|
|
1245
|
+
})
|
|
1246
|
+
);
|
|
1247
|
+
}
|
|
1221
1248
|
}
|
|
1222
1249
|
|
|
1223
1250
|
async function remove(element) {
|
|
@@ -1296,7 +1323,7 @@ function initSocket() {
|
|
|
1296
1323
|
|
|
1297
1324
|
Observer.init({
|
|
1298
1325
|
name: "render",
|
|
1299
|
-
|
|
1326
|
+
types: ["addedNodes"],
|
|
1300
1327
|
selector: "[render-clone]",
|
|
1301
1328
|
callback: function (mutation) {
|
|
1302
1329
|
if (!mutation.parentElement.hasAttribute("dnd")) return;
|
|
@@ -1445,16 +1472,16 @@ function dndCrudSend(data, crudType) {
|
|
|
1445
1472
|
|
|
1446
1473
|
Observer.init({
|
|
1447
1474
|
name: "CoCreateElementsChildList",
|
|
1448
|
-
|
|
1475
|
+
types: ["addedNodes"],
|
|
1449
1476
|
selector: selector,
|
|
1450
1477
|
callback: function (mutation) {
|
|
1451
|
-
init(mutation.
|
|
1478
|
+
init([mutation.target]);
|
|
1452
1479
|
}
|
|
1453
1480
|
});
|
|
1454
1481
|
|
|
1455
1482
|
Observer.init({
|
|
1456
1483
|
name: "CoCreateElementsRemovedNodes",
|
|
1457
|
-
|
|
1484
|
+
types: ["removedNodes"],
|
|
1458
1485
|
selector: selector,
|
|
1459
1486
|
callback: function (mutation) {
|
|
1460
1487
|
// if (mutation.target.parentElement) return
|
|
@@ -1472,8 +1499,8 @@ Observer.init({
|
|
|
1472
1499
|
|
|
1473
1500
|
Observer.init({
|
|
1474
1501
|
name: "CoCreateElementsAttributes",
|
|
1475
|
-
|
|
1476
|
-
|
|
1502
|
+
types: ["attributes"],
|
|
1503
|
+
attributeFilter: [
|
|
1477
1504
|
"organization_id",
|
|
1478
1505
|
"host",
|
|
1479
1506
|
"storage",
|
|
@@ -1499,7 +1526,7 @@ Actions.init([
|
|
|
1499
1526
|
name: "save",
|
|
1500
1527
|
endEvent: "saved",
|
|
1501
1528
|
callback: (action) => {
|
|
1502
|
-
if (action.form) save(action.form);
|
|
1529
|
+
if ((action.form, action)) save(action.form, action);
|
|
1503
1530
|
}
|
|
1504
1531
|
},
|
|
1505
1532
|
{
|
|
@@ -1542,7 +1569,7 @@ Actions.init([
|
|
|
1542
1569
|
data[data.type] = { _id: data[data.type] };
|
|
1543
1570
|
|
|
1544
1571
|
let response = await CRUD.send(data);
|
|
1545
|
-
|
|
1572
|
+
action.element.dispatchEvent(
|
|
1546
1573
|
new CustomEvent("deleted", {
|
|
1547
1574
|
detail: response
|
|
1548
1575
|
})
|
package/src/value.js
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import Observer from "@cocreate/observer";
|
|
2
|
+
import "@cocreate/element-prototype";
|
|
3
|
+
|
|
4
|
+
const selector =
|
|
5
|
+
"[value-selector], [value-closest], [value-parent], [value-next], [value-previous], [value-document], [value-frame], [value-top]";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Initializes elements with value-* attributes to enable dynamic value retrieval and setting.
|
|
9
|
+
*
|
|
10
|
+
* @param {HTMLElement|HTMLCollection|NodeList|Array<HTMLElement>} [element] - Optional element(s) to initialize. If not provided, initializes all matching elements in the document.
|
|
11
|
+
*/
|
|
12
|
+
async function init(element) {
|
|
13
|
+
if (
|
|
14
|
+
element &&
|
|
15
|
+
!(element instanceof HTMLCollection) &&
|
|
16
|
+
!(element instanceof NodeList) &&
|
|
17
|
+
!Array.isArray(element)
|
|
18
|
+
) {
|
|
19
|
+
element = [element];
|
|
20
|
+
} else if (!element) {
|
|
21
|
+
element = document.querySelectorAll(selector);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
for (let i = 0; i < element.length; i++) {
|
|
25
|
+
initElement(element[i]);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Initializes a single element with value-* attributes.
|
|
31
|
+
*
|
|
32
|
+
* @param {HTMLElement} element - The element to initialize.
|
|
33
|
+
*/
|
|
34
|
+
function initElement(element) {
|
|
35
|
+
let targets = element.queryElements();
|
|
36
|
+
|
|
37
|
+
valueHandler(element, targets, true);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Handles the retrieval and setting of values based on value-* attributes.
|
|
42
|
+
*
|
|
43
|
+
* @param {HTMLElement} element - The element to set the value on.
|
|
44
|
+
* @param {object} targets - An object containing elements retrieved by queryElements().
|
|
45
|
+
*/
|
|
46
|
+
function valueHandler(element, targets = [], initialize) {
|
|
47
|
+
let values = [];
|
|
48
|
+
// TODO: consdier the potential of targets being an array of elements, should value be an array of the values?
|
|
49
|
+
for (let i = 0; i < targets.length; i++) {
|
|
50
|
+
if (!targets[i] || !targets[i].isConnected) {
|
|
51
|
+
targets.splice(i, 1); // Remove the element
|
|
52
|
+
i -= 1; // Adjust the index
|
|
53
|
+
continue; // Skip to the next iteration
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (initialize) {
|
|
57
|
+
// Remove existing listener (if any)
|
|
58
|
+
targets[i].removeEventListener("input", elementValueHandler);
|
|
59
|
+
|
|
60
|
+
// Add new listener
|
|
61
|
+
targets[i].addEventListener("input", elementValueHandler);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
values.push(targets[i].getValue());
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (!values.length) {
|
|
68
|
+
return;
|
|
69
|
+
} else if (values.length === 1) {
|
|
70
|
+
values = values[0];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
let attribute = element.getAttribute("value-attribute");
|
|
74
|
+
if (attribute) {
|
|
75
|
+
element.setAttribute(attribute, values);
|
|
76
|
+
} else {
|
|
77
|
+
element.setValue(values);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function elementValueHandler(e) {
|
|
81
|
+
valueHandler(element, targets);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
init();
|
|
86
|
+
|
|
87
|
+
Observer.init({
|
|
88
|
+
name: "CoCreateElementsValueAdded",
|
|
89
|
+
types: ["addedNodes"],
|
|
90
|
+
selector: selector,
|
|
91
|
+
callback: function (mutation) {
|
|
92
|
+
init(mutation.target);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
Observer.init({
|
|
97
|
+
name: "CoCreateElementsAttributes",
|
|
98
|
+
types: ["attributes"],
|
|
99
|
+
attributeFilter: [
|
|
100
|
+
"value-selector",
|
|
101
|
+
"value-closest",
|
|
102
|
+
"value-parent",
|
|
103
|
+
"value-next",
|
|
104
|
+
"value-previous",
|
|
105
|
+
"value-document",
|
|
106
|
+
"value-frame",
|
|
107
|
+
"value-top"
|
|
108
|
+
],
|
|
109
|
+
callback: function (mutation) {
|
|
110
|
+
let currentValue = mutation.target.getAttribute(mutation.attributeName);
|
|
111
|
+
if (currentValue !== mutation.oldValue) {
|
|
112
|
+
initElement(mutation.target);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
});
|