Skip to content

Commit 70f5d30

Browse files
committed
fix: improved action attribute split and trim using regex
1 parent 1569e21 commit 70f5d30

File tree

1 file changed

+191
-169
lines changed

1 file changed

+191
-169
lines changed

src/index.js

Lines changed: 191 additions & 169 deletions
Original file line numberDiff line numberDiff line change
@@ -1,203 +1,225 @@
1-
import { queryElements } from '@cocreate/utils'
2-
import uuid from '@cocreate/uuid'
1+
import { queryElements } from "@cocreate/utils";
2+
import uuid from "@cocreate/uuid";
33

4-
const attribute = 'actions'
5-
const actions = {}
4+
const attribute = "actions";
5+
const actions = {};
66

77
/**
88
* name: string
99
* callback: function
1010
* endEvent: string
1111
**/
1212
function init(data) {
13-
if (!Array.isArray(data))
14-
data = [data]
15-
for (let { name, callback, endEvent } of data) {
16-
if (!Array.isArray(name))
17-
name = [name]
18-
for (let i = 0; i < name.length; i++) {
19-
if (actions[name[i]])
20-
continue;
21-
22-
actions[name[i]] = {
23-
name: name[i],
24-
callback,
25-
endEvent: endEvent || name[i]
26-
}
27-
28-
}
29-
}
13+
if (!Array.isArray(data)) data = [data];
14+
for (let { name, callback, endEvent } of data) {
15+
if (!Array.isArray(name)) name = [name];
16+
for (let i = 0; i < name.length; i++) {
17+
if (actions[name[i]]) continue;
18+
19+
actions[name[i]] = {
20+
name: name[i],
21+
callback,
22+
endEvent: endEvent || name[i]
23+
};
24+
}
25+
}
3026
}
3127

3228
function initActions() {
33-
document.addEventListener('click', function (event) {
34-
let element = event.target;
35-
if (!element.getAttribute(attribute))
36-
element = event.target.closest(`[${attribute}]`);
37-
38-
if (!element) return;
39-
if (element.tagName === 'form') {
40-
const pattern = /^(https?:\/\/)?([\w.-]+)\.([a-z]{2,})(:\d{1,5})?(\/.*)?$/i;
41-
if (pattern.test(element.action))
42-
return form.submit()
43-
}
44-
45-
event.preventDefault();
46-
47-
let actions = (element.getAttribute(attribute) || "").replace(/\s/g, '').split(',');
48-
if (actions.length == 0) return;
49-
50-
let index = 0;
51-
let stagedActions = [];
52-
for (let action of actions) {
53-
let [name, params] = action.split('(')
54-
if (params)
55-
params = params.substring(0, (params.length - 1))
56-
57-
stagedActions.push({ name, params })
58-
}
59-
60-
runAction(stagedActions, index, element);
61-
})
29+
document.addEventListener("click", function (event) {
30+
let element = event.target;
31+
if (!element.getAttribute(attribute))
32+
element = event.target.closest(`[${attribute}]`);
33+
34+
if (!element) return;
35+
if (element.tagName === "form") {
36+
const pattern =
37+
/^(https?:\/\/)?([\w.-]+)\.([a-z]{2,})(:\d{1,5})?(\/.*)?$/i;
38+
if (pattern.test(element.action)) return form.submit();
39+
}
40+
41+
event.preventDefault();
42+
43+
let actions = (element.getAttribute(attribute) || "").split(/\s*,\s*/);
44+
if (actions.length == 0) return;
45+
46+
let index = 0;
47+
let stagedActions = [];
48+
for (let action of actions) {
49+
let [name, params] = action.split("(");
50+
if (params) params = params.substring(0, params.length - 1);
51+
52+
stagedActions.push({ name, params });
53+
}
54+
55+
runAction(stagedActions, index, element);
56+
});
6257
}
6358

6459
function runAction(stagedActions, index, element) {
65-
if (index >= stagedActions.length) {
66-
if (index == stagedActions.length) {
67-
runSubmit(element)
68-
runLink(element);
69-
}
70-
return;
71-
}
72-
73-
const currentAction = stagedActions[index];
74-
if (!currentAction) return
75-
76-
let actionName = currentAction.name
77-
if (actionName.includes('.')) {
78-
let name = actionName.split('.')[0]
79-
currentAction.method = actionName.substring(name.length + 1)
80-
currentAction.name = actionName = name
81-
currentAction.endEvent = uuid.generate(6)
82-
}
83-
84-
const action = actions[actionName];
85-
86-
if (action) {
87-
document.addEventListener(currentAction.endEvent || action.endEvent, function () {
88-
runNextAction(stagedActions, index, element);
89-
}, { once: true });
90-
91-
if (action.callback) {
92-
const form = element.closest('form')
93-
action.callback.call(null, { element, form, ...currentAction });
94-
} else
95-
runNextAction(stagedActions, index, element);
96-
97-
} else {
98-
let status = runSpecialAction(stagedActions, index, element, actionName, currentAction.params);
99-
if (status === "next") {
100-
runNextAction(stagedActions, index, element);
101-
}
102-
}
60+
if (index >= stagedActions.length) {
61+
if (index == stagedActions.length) {
62+
runSubmit(element);
63+
runLink(element);
64+
}
65+
return;
66+
}
67+
68+
const currentAction = stagedActions[index];
69+
if (!currentAction) return;
70+
71+
let actionName = currentAction.name;
72+
if (actionName.includes(".")) {
73+
let name = actionName.split(".")[0];
74+
currentAction.method = actionName.substring(name.length + 1);
75+
currentAction.name = actionName = name;
76+
currentAction.endEvent = uuid.generate(6);
77+
}
78+
79+
const action = actions[actionName];
80+
81+
if (action) {
82+
document.addEventListener(
83+
currentAction.endEvent || action.endEvent,
84+
function () {
85+
runNextAction(stagedActions, index, element);
86+
},
87+
{ once: true }
88+
);
89+
90+
if (action.callback) {
91+
const form = element.closest("form");
92+
action.callback.call(null, { element, form, ...currentAction });
93+
} else runNextAction(stagedActions, index, element);
94+
} else {
95+
let status = runSpecialAction(
96+
stagedActions,
97+
index,
98+
element,
99+
actionName,
100+
currentAction.params
101+
);
102+
if (status === "next") {
103+
runNextAction(stagedActions, index, element);
104+
}
105+
}
103106
}
104107

105108
function runSpecialAction(actions, index, element, actionName, params) {
106-
if (!params) return "next";
107-
let elements, status = "next"
108-
switch (actionName) {
109-
case 'event':
110-
console.log("Waiting Event....");
111-
status = ""
112-
document.addEventListener(params, () => {
113-
console.log('Event Action (Received event from other section) ====== ' + params);
114-
runNextAction(actions, index, element);
115-
}, { once: true })
116-
break;
117-
case 'timeout':
118-
status = ""
119-
120-
let delayTime = parseInt(params);
121-
if (delayTime > 0) {
122-
setTimeout(function () {
123-
console.log("Timeout ======= " + params)
124-
runNextAction(actions, index, element);
125-
}, parseInt(params));
126-
}
127-
break;
128-
case 'action':
129-
elements = queryElements({ element, selector: params, type: 'selector' });
130-
for (let i = 0; i < elements.length; i++) {
131-
elements[i].click();
132-
}
133-
break;
134-
case 'read':
135-
case 'save':
136-
case 'renderValue':
137-
elements = queryElements({ element, selector: params, type: 'selector' });
138-
for (let i = 0; i < elements.length; i++) {
139-
if (elements[i][actionName])
140-
elements[i][actionName]();
141-
}
142-
break;
143-
case 'submit':
144-
let form = closest('form');
145-
if (form)
146-
form.click();
147-
break;
148-
default:
149-
elements = queryElements({ element, selector: params, type: 'selector' });
150-
for (let i = 0; i < elements.length; i++) {
151-
if (elements[i][actionName])
152-
elements[i][actionName]();
153-
}
154-
}
155-
156-
return status
109+
if (!params) return "next";
110+
let elements,
111+
status = "next";
112+
switch (actionName) {
113+
case "event":
114+
console.log("Waiting Event....");
115+
status = "";
116+
document.addEventListener(
117+
params,
118+
() => {
119+
console.log(
120+
"Event Action (Received event from other section) ====== " +
121+
params
122+
);
123+
runNextAction(actions, index, element);
124+
},
125+
{ once: true }
126+
);
127+
break;
128+
case "timeout":
129+
status = "";
130+
131+
let delayTime = parseInt(params);
132+
if (delayTime > 0) {
133+
setTimeout(function () {
134+
console.log("Timeout ======= " + params);
135+
runNextAction(actions, index, element);
136+
}, parseInt(params));
137+
}
138+
break;
139+
case "action":
140+
elements = queryElements({
141+
element,
142+
selector: params,
143+
type: "selector"
144+
});
145+
for (let i = 0; i < elements.length; i++) {
146+
elements[i].click();
147+
}
148+
break;
149+
case "read":
150+
case "save":
151+
case "renderValue":
152+
elements = queryElements({
153+
element,
154+
selector: params,
155+
type: "selector"
156+
});
157+
for (let i = 0; i < elements.length; i++) {
158+
if (elements[i][actionName]) elements[i][actionName]();
159+
}
160+
break;
161+
case "submit":
162+
let form = closest("form");
163+
if (form) form.click();
164+
break;
165+
default:
166+
elements = queryElements({
167+
element,
168+
selector: params,
169+
type: "selector"
170+
});
171+
for (let i = 0; i < elements.length; i++) {
172+
if (elements[i][actionName]) elements[i][actionName]();
173+
}
174+
}
175+
176+
return status;
157177
}
158178

159179
function runNextAction(actions, index, element) {
160-
runAction(actions, index += 1, element);
180+
runAction(actions, (index += 1), element);
161181
}
162182

163183
function runSubmit(element) {
164-
let button = element.closest('[type="submit"]');
165-
if (!button)
166-
button = element.querySelector('[type="submit"]');
167-
if (button) {
168-
let form = element.closest('form')
169-
if (form && form.action) {
170-
const pattern = /^(https?:\/\/)?([\w.-]+)\.([a-z]{2,})(:\d{1,5})?(\/.*)?$/i;
171-
if (pattern.test(form.action))
172-
form.submit()
173-
}
174-
}
184+
let button = element.closest('[type="submit"]');
185+
if (!button) button = element.querySelector('[type="submit"]');
186+
if (button) {
187+
let form = element.closest("form");
188+
if (form && form.action) {
189+
const pattern =
190+
/^(https?:\/\/)?([\w.-]+)\.([a-z]{2,})(:\d{1,5})?(\/.*)?$/i;
191+
if (pattern.test(form.action)) form.submit();
192+
}
193+
}
175194
}
176195

177196
function runLink(element) {
178-
let link = element.closest('[href], [target], [state_to]');
179-
if (!link)
180-
link = element.querySelector('[href], [target], [state_to]');
181-
if (link)
182-
run(link);
197+
let link = element.closest("[href], [target], [state_to]");
198+
if (!link) link = element.querySelector("[href], [target], [state_to]");
199+
if (link) run(link);
183200
}
184201

185202
function run(link) {
186-
if (typeof CoCreate.link !== 'undefined') {
187-
CoCreate.link.open(link)
188-
} else if (link.hasAttribute('href')) {
189-
let href = link.getAttribute('href') || '';
190-
// Normalize both URLs to compare paths in a uniform way
191-
const currentPath = new URL(location.href).pathname.replace('/index.html', '/');
192-
const targetPath = new URL(href, location.href).pathname.replace('/index.html', '/');
193-
194-
if (currentPath !== targetPath) {
195-
location.href = href;
196-
}
197-
}
203+
if (typeof CoCreate.link !== "undefined") {
204+
CoCreate.link.open(link);
205+
} else if (link.hasAttribute("href")) {
206+
let href = link.getAttribute("href") || "";
207+
// Normalize both URLs to compare paths in a uniform way
208+
const currentPath = new URL(location.href).pathname.replace(
209+
"/index.html",
210+
"/"
211+
);
212+
const targetPath = new URL(href, location.href).pathname.replace(
213+
"/index.html",
214+
"/"
215+
);
216+
217+
if (currentPath !== targetPath) {
218+
location.href = href;
219+
}
220+
}
198221
}
199222

200-
201223
initActions();
202224

203225
export default { init };

0 commit comments

Comments
 (0)