Skip to content

Commit e3ae15b

Browse files
committed
feat: value-selectors to get value from target element
1 parent ba102ce commit e3ae15b

File tree

2 files changed

+123
-2
lines changed

2 files changed

+123
-2
lines changed

src/index.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import { render, renderValue, renderedNodes } from "@cocreate/render";
4040
import "@cocreate/element-prototype";
4141
import "./fetchSrc";
4242
import { reset } from "./form";
43+
import "./value.js";
4344

4445
const selector = "[storage], [database], [array], [render-json]";
4546
const elements = new Map();
@@ -462,7 +463,12 @@ async function filterData(element, data, type, key) {
462463
}
463464

464465
let property = key;
465-
if (operator) property = property.replace(operator + ".", "");
466+
if (operator) {
467+
property = property.replace(operator + ".", "");
468+
if (operator === "$sum") {
469+
value = 0;
470+
}
471+
}
466472
if (Array.isArray(data[type])) {
467473
let Data = [],
468474
isObject;
@@ -482,7 +488,7 @@ async function filterData(element, data, type, key) {
482488
if (docValue) {
483489
if (operator === "$sum" && typeof docValue === "number") {
484490
if (typeof value !== "number") value = 0;
485-
value += docValue;
491+
value += docValue || 0;
486492
} else if (Array.isArray(docValue)) {
487493
Data.push(...docValue);
488494
} else {

src/value.js

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
observe: ["addedNodes"],
90+
selector: selector,
91+
callback: function (mutation) {
92+
init(mutation.target);
93+
}
94+
});
95+
96+
Observer.init({
97+
name: "CoCreateElementsAttributes",
98+
observe: ["attributes"],
99+
attributeName: [
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+
});

0 commit comments

Comments
 (0)