Skip to content

Commit a74713e

Browse files
committed
feat: calculte supports tenary and conditionals
- update to functional programing
1 parent 9e2ea92 commit a74713e

File tree

1 file changed

+112
-120
lines changed

1 file changed

+112
-120
lines changed

src/index.js

Lines changed: 112 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -1,177 +1,169 @@
11
import observer from '@cocreate/observer';
22
import { getAttributes } from '@cocreate/utils';
3+
// import { renderValue } from '@cocreate/render';
34
import '@cocreate/element-prototype';
45

5-
var CoCreateCalculation = {
66

7-
init: function () {
8-
let calculationElements = document.querySelectorAll('[calculate]');
9-
this.initElements(calculationElements);
10-
},
7+
function init() {
8+
let calculationElements = document.querySelectorAll('[calculate]');
9+
initElements(calculationElements);
10+
}
1111

12-
initElements: function (elements) {
13-
for (let el of elements)
14-
this.initElement(el);
15-
},
12+
function initElements(elements) {
13+
for (let el of elements)
14+
initElement(el);
15+
}
1616

17-
initElement: function (ele) {
18-
const self = this;
19-
let calculation = ele.getAttribute('calculate');
20-
let selectors = this.getSelectors(calculation);
17+
function initElement(element) {
18+
let calculation = element.getAttribute('calculate');
19+
if (calculation.includes('{{') || calculation.includes('{['))
20+
return;
2121

22-
for (let i = 0; i < selectors.length; i++) {
23-
let id = selectors[i];
24-
if (id.includes('{{')) return;
22+
let selectors = getSelectors(calculation);
2523

26-
// self.initEvents(ele, id);
27-
let inputs = document.querySelectorAll(id);
28-
for (let input of inputs) {
29-
self.initEvent(ele, input);
30-
}
24+
for (let i = 0; i < selectors.length; i++) {
25+
// if (selectors[i].includes('{{')) return;
3126

32-
observer.init({
33-
name: 'calculationSelectorInit',
34-
observe: ['addedNodes'],
35-
target: id,
36-
callback: function (mutation) {
37-
self.initEvent(ele, mutation.target);
38-
self.setCalcationResult(ele);
39-
}
40-
});
41-
42-
self.setCalcationResult(ele);
27+
// initEvents(element, selectors[i]);
28+
let inputs = document.querySelectorAll(selectors[i]);
29+
for (let input of inputs) {
30+
initEvent(element, input);
4331
}
44-
},
4532

46-
initEvent: function (ele, input) {
47-
const self = this;
48-
input.addEventListener('input', function () {
49-
self.setCalcationResult(ele);
33+
observer.init({
34+
name: 'calculationSelectorInit',
35+
observe: ['addedNodes'],
36+
target: selectors[i],
37+
callback(mutation) {
38+
initEvent(element, mutation.target);
39+
setCalcationResult(element);
40+
}
5041
});
42+
}
43+
setCalcationResult(element);
44+
}
5145

52-
// if (input.hasAttribute('calculate')) {
53-
// input.addEventListener('changedCalcValue', function(e) {
54-
// self.setCalcationResult(ele);
55-
// });
56-
// }
57-
// self.setCalcationResult(ele);
58-
},
59-
60-
getSelectors: function (string) {
61-
let tmp = string;
62-
63-
let selectors = [];
64-
if (!tmp) return selectors;
65-
while (tmp.length > 0) {
66-
let firstIndex = tmp.indexOf('{');
67-
let secondIndex = tmp.indexOf('}', firstIndex);
68-
69-
if (firstIndex > -1 && secondIndex > -1) {
70-
let id = tmp.substring(firstIndex + 1, secondIndex);
71-
72-
if (selectors.indexOf(id) == -1) selectors.push(id);
46+
function getSelectors(string) {
47+
let regex = /\{\((?:(?!\{\().)*?\)\}/;
48+
let selectors = [];
7349

74-
tmp = tmp.substring(secondIndex + 1);
50+
let match;
51+
while ((match = regex.exec(string)) !== null) {
52+
// Extract the content inside the braces (excluding the leading '{(' and trailing ')}')
53+
let selector = match[0].slice(2, -2);
7554

76-
}
77-
else {
78-
return selectors;
79-
}
55+
if (selectors.indexOf(selector) === -1) {
56+
selectors.push(selector);
8057
}
8158

82-
return selectors;
83-
},
59+
// Replace the found match with an empty string to avoid reprocessing in the next iteration
60+
string = string.replace(match[0], '');
61+
}
62+
63+
return selectors;
64+
}
8465

85-
getValues: async function (calculation) {
86-
let selectors = this.getSelectors(calculation);
66+
async function getValues(calculation) {
67+
let selectors = getSelectors(calculation);
8768

88-
for (let i = 0; i < selectors.length; i++) {
89-
let selector = selectors[i];
69+
for (let i = 0; i < selectors.length; i++) {
70+
let selector = selectors[i];
9071

91-
let value = null;
92-
let inputs = document.querySelectorAll(selector);
72+
let value = null;
73+
let inputs = document.querySelectorAll(selector);
9374

94-
for (let input of inputs) {
95-
let val = null;
96-
if (input.getValue)
97-
val = Number(await input.getValue());
75+
for (let input of inputs) {
76+
let val = null;
77+
if (input.getValue)
78+
val = Number(await input.getValue());
9879

99-
if (!Number.isNaN(value)) {
100-
value += val;
101-
}
80+
if (!Number.isNaN(value)) {
81+
value += val;
10282
}
83+
}
10384

104-
if (value != null && !Number.isNaN(value)) {
105-
calculation = calculation.replaceAll('{' + selector + '}', value);
106-
}
85+
if (value != null && !Number.isNaN(value)) {
86+
calculation = calculation.replaceAll('{' + selector + '}', value);
10787
}
88+
}
10889

109-
return calculation;
110-
},
90+
return calculation;
91+
}
11192

112-
setCalcationResult: async function (element) {
113-
const { object, isRealtime } = getAttributes(element);
114-
let calculation = element.getAttribute('calculate');
93+
function initEvent(element, input) {
94+
input.addEventListener('input', function () {
95+
setCalcationResult(element);
96+
});
97+
98+
// if (input.hasAttribute('calculate')) {
99+
// input.addEventListener('changedCalcValue', function(e) {
100+
// setCalcationResult(element);
101+
// });
102+
// }
103+
// setCalcationResult(element);
104+
}
115105

116-
let calString = await this.getValues(calculation);
106+
async function setCalcationResult(element) {
107+
const { object, isRealtime } = getAttributes(element);
108+
let calculation = element.getAttribute('calculate');
117109

118-
if (calString) {
119-
let result = calculate(calString);
110+
let calString = await getValues(calculation);
120111

121-
// TODO: input event below triggers save for all input elements but will not save for regular elements
122-
if (element.setValue) {
123-
element.setValue(result)
124-
if (object && isRealtime != "false") {
125-
element.save(element);
126-
}
127-
}
128-
else {
129-
// if (element.value){
112+
if (calString) {
113+
let result = calculate(calString);
130114

131-
// }
132-
// else {
133-
element.innerHTML = result;
134-
// }
115+
// TODO: input event below triggers save for all input elements but will not save for regular elements
116+
if (element.setValue) {
117+
element.setValue(result)
118+
if (object && isRealtime != "false") {
119+
element.save(element);
135120
}
121+
}
122+
else {
123+
// if (element.value){
136124

137-
let inputEvent = new CustomEvent('input', { bubbles: true });
138-
Object.defineProperty(inputEvent, 'target', { writable: false, value: element });
139-
element.dispatchEvent(inputEvent);
140-
141-
//. set custom event
142-
// var event = new CustomEvent('changedCalcValue', {
143-
// bubbles: true,
144-
// });
145-
// element.dispatchEvent(event);
125+
// }
126+
// else {
127+
element.innerHTML = result;
128+
// }
146129
}
147130

148-
},
131+
let inputEvent = new CustomEvent('input', { bubbles: true });
132+
Object.defineProperty(inputEvent, 'target', { writable: false, value: element });
133+
element.dispatchEvent(inputEvent);
149134

150-
};
135+
//. set custom event
136+
// var event = new CustomEvent('changedCalcValue', {
137+
// bubbles: true,
138+
// });
139+
// element.dispatchEvent(event);
140+
}
141+
142+
}
151143

152144
function calculate(string) {
153-
if (!string.match(/[a-z_]/i))
145+
if (/^[0-9+\-*/()%||?\s:=.]*$/.test(string))
154146
return eval(string);
155147
}
156148

157149
observer.init({
158150
name: 'CoCreateCalculationChangeValue',
159151
observe: ['attributes'],
160152
attributeName: ['calculate'],
161-
callback: function (mutation) {
162-
CoCreateCalculation.setCalcationResult(mutation.target);
153+
callback(mutation) {
154+
setCalcationResult(mutation.target);
163155
}
164156
});
165157

166158
observer.init({
167159
name: 'CoCreateCalculationInit',
168160
observe: ['addedNodes'],
169161
target: '[calculate]',
170-
callback: function (mutation) {
171-
CoCreateCalculation.initElement(mutation.target);
162+
callback(mutation) {
163+
initElement(mutation.target);
172164
}
173165
});
174166

175-
CoCreateCalculation.init();
167+
init();
176168

177-
export default CoCreateCalculation;
169+
export default { initElements, initElement, calculate };

0 commit comments

Comments
 (0)