Skip to content

Commit c2ecede

Browse files
author
Frank Pagan
committed
feat: type param to define an interaction. onload, input, action, attributeObserver and nodeObserver
1 parent 2029328 commit c2ecede

File tree

2 files changed

+158
-82
lines changed

2 files changed

+158
-82
lines changed

demo/client.js

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,33 @@ import api from "@cocreate/api";
22

33
const CoCreateExample = {
44
name: "example",
5-
actions: {
5+
endPoints: {
66
'tokens.create':{},
7-
create:{
8-
realtime: true,
9-
request: function (data) {
10-
},
11-
response: function (data) {
7+
create: {
8+
onload: function (name, endPoint, element) {
9+
10+
},
11+
input: function (name, endPoint, element) {
12+
13+
},
14+
action: function (name, endPoint, element){
15+
16+
},
17+
observer: function (name, endPoint, element) {
18+
19+
},
20+
request: function (name, endPoint, element) {
21+
22+
},
23+
response: function (name, endPoint, element) {
1224

1325
},
26+
read: true,
27+
realtime: true,
28+
save: true,
29+
update: true,
30+
listen: true
31+
1432
}
1533
}
1634
};

src/client.js

Lines changed: 134 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,128 +1,186 @@
11
/*globals CustomEvent, config*/
22
import {getAttributes, getValueFromObject, dotNotationToObject} from "@cocreate/utils";
3+
import observer from "@cocreate/observer";
34
import socket from "@cocreate/socket-client";
4-
import CoCreateAction from '@cocreate/actions';
5-
import CoCreateRender from '@cocreate/render';
5+
import action from '@cocreate/actions';
6+
import render from '@cocreate/render';
67
import '@cocreate/element-prototype';
7-
import utils from "@cocreate/utils/src/utils";
88

99
const CoCreateApi = {
1010
components: {},
11-
12-
init: function({name, actions, realtime}) {
13-
this.register({name, actions});
14-
if (!socket.sockets.size)
11+
12+
init: function({name, endPoints, options}) {
13+
this.register({name, endPoints, options});
14+
if (options.socket !== false && !socket.sockets.size)
1515
socket.create({prefix: 'api'});
16-
document.addEventListener('input', (e)=> {
17-
let action = e.target.getAttribute(name)
18-
if (action) {
19-
action = action.split('.', 1)
20-
action = action[0]
21-
if (actions[action].realtime !== false) {
22-
if (realtime !== false && actions[action].realtime !== undefined) {
23-
let functions = actions[action]
24-
if (typeof functions.request === 'function') {
25-
functions.request(name, action, e.target)
26-
}
27-
}
28-
}
29-
}
30-
31-
})
3216
},
3317

34-
register: function({name, actions}) {
18+
register: function({name, endPoints, options}) {
3519
const self = this;
3620
if (typeof this.components[name] === 'undefined') {
37-
this.components[name] = {name, actions};
21+
this.components[name] = {name, endPoints, options};
3822

3923
socket.listen(name, (data) => {
4024
self.__response(name, data);
4125
});
4226

43-
for (const action of Object.keys(actions)) {
44-
let functions = actions[action]
27+
for (const endPoint of Object.keys(endPoints)) {
28+
let functions = endPoints[endPoint]
4529
if (typeof functions.request !== 'function') {
4630
functions.request = self.__request;
4731
}
48-
CoCreateAction.init({
49-
name: action,
50-
endEvent: action,
32+
action.init({
33+
name: endPoint,
34+
endEvent: endPoint,
5135
callback: (element) => {
52-
functions.request(name, action, element);
36+
let params
37+
let form = element.closest('form') || document
38+
const selector = `[${name}^="${endPoint}."]`
39+
let el = form.querySelector(selector)
40+
if (!el) return
41+
params = self.parseParams({name, element: el})
42+
if (params) {
43+
functions.request({name, ...params, element, form, type: 'action'})
44+
}
5345
},
5446
});
5547
}
48+
49+
const inputEvent = (element) => {
50+
const self = this
51+
element.addEventListener('input', (e) => {
52+
if (element.hasAttribute(name)) {
53+
let params = self.parseParams({name, element})
54+
if (params) {
55+
if (!e.detail || e.detail && e.detail.skip != true) {
56+
endPoints[params.endPoint].request({name, ...params, element, type: 'input'})
57+
}
58+
}
59+
}
60+
});
61+
}
62+
63+
let elements = document.querySelectorAll(`[${name}]`)
64+
for (let element of elements) {
65+
let params = this.parseParams({name, element})
66+
if (params) {
67+
endPoints[params.endPoint].request({name, ...params, element, type:'onload'})
68+
inputEvent(element)
69+
}
70+
}
71+
72+
observer.init({
73+
name: `${name}NodeObserver`,
74+
observe: ['addedNodes'],
75+
target: `[${name}]`,
76+
callback: function(mutation) {
77+
let params = self.parseParams({name, element: mutation.target})
78+
if (params) {
79+
endPoints[params.endPoint].request({name, ...params, element: mutation.target, type: 'nodeObserver'});
80+
inputEvent(mutation.target)
81+
}
82+
}
83+
});
84+
85+
observer.init({
86+
name: `${name}AttributeObserver`,
87+
observe: ['attributes'],
88+
attributeName: [name],
89+
callback: function(mutation) {
90+
let params = self.parseParams({name, element: mutation.target})
91+
if (params) {
92+
endPoints[params.endPoint].request({name, ...params, element: mutation.target, type: 'attributeObserver'});
93+
}
94+
}
95+
});
5696
}
5797
},
5898

59-
__request: function(name, action, element) {
99+
__request: function({name, endPoint, element}) {
60100
let form = element.closest('form');
61-
let data = this.getData(name, action, form);
62-
this.send(name, action, data[action]);
101+
let data = this.getData({name, endPoint, form});
102+
this.send(name, endPoint, data[endPoint]);
63103
},
64104

65105
__response: function(name, data) {
66-
const {action, response} = data;
106+
const {endPoint, response} = data;
67107
const component = this.components[name];
68-
const functions = component.actions[action]
69-
if (typeof functions.response === 'function') {
70-
functions.response(response);
108+
const functions = component.endPoints[endPoint]
109+
if (functions.listen !== false) {
110+
if (typeof functions.response === 'function') {
111+
functions.response(response);
112+
} else
113+
this.setData({name, endPoint, data})
114+
115+
document.dispatchEvent(new CustomEvent(endPoint, {
116+
detail: {
117+
data: response
118+
}
119+
}));
71120
}
72-
else
73-
this.render(action, response);
74-
75-
document.dispatchEvent(new CustomEvent(action, {
76-
detail: {
77-
data: response
78-
}
79-
}));
80121
},
81122

82-
send: function(name, action, data) {
83-
socket.send(name, {action, data, broadcastBrowser: false});
123+
send: function(name, endPoint, data) {
124+
socket.send(name, {endPoint, data, broadcastBrowser: false});
84125
},
85126

86-
render: function(action, data) {
87-
CoCreateRender.data({
88-
selector: `[template="${action}"]`,
89-
data: data
90-
});
91-
},
127+
parseParams: function({name, endPoint, element}) {
128+
let attribute = element.getAttribute(name)
129+
if (!attribute)
130+
return false
131+
132+
let dotNotation = attribute
133+
let params = attribute.split('.')
134+
endPoint = params[0]
135+
let key = params[1]
136+
return {endPoint, key, dotNotation, params}
92137

93-
getData: function(attribute, action, form) {
94-
let data = {}
95-
const selector = `[${attribute}^="${action}."]`
96-
if (!form)
97-
form = document;
98-
let elements = form.querySelectorAll(selector);
99-
if (!elements || elements.length == 0) return
138+
},
139+
100140

141+
getData: function({name, endPoint, element, form}) {
142+
const data = {}
143+
const selector = `[${name}^="${endPoint}."]`
144+
let elements
145+
if (form)
146+
elements = form.querySelectorAll(selector);
147+
if (!elements || elements.length == 0)
148+
elements = [element]
101149
for (let el of elements) {
102-
let name = el.getAttribute(attribute)
103-
let value = el.getValue();
104-
if (name)
105-
data[name] = value
106-
}
150+
if (el.closest('[template]')) continue
151+
let attribute = el.getAttribute(name)
152+
if (attribute)
153+
data[attribute] = el.getValue()
154+
}
155+
107156
return dotNotationToObject(data);
108157
},
109158

110-
setData: function(attribute, action, data, form) {
111-
const selector = `[${attribute}^="${action}."]`
159+
setData: function({name, endPoint, data, form}) {
160+
const selector = `[${name}^="${endPoint}."]`
112161
if (!form)
113162
form = document;
114163
let elements = form.querySelectorAll(selector);
115164
if (!elements || elements.length == 0) return
116165

117166
for (let el of elements) {
118-
let name = el.getAttribute(attribute)
119-
const { isRead, isUpdate, isCrdt } = getAttributes(el);
120-
if (!name || isRead == "false" || isUpdate == "false" || isCrdt == "true") continue;
121-
122-
if (el.hasAttribute('actions')) continue;
123-
124-
let value = getValueFromObject({[action]: {[name]: data}}, name);
125-
el.setValue(value);
167+
let attribute = el.getAttribute(name)
168+
if (attribute) {
169+
if (el.hasAttribute('actions')) continue;
170+
let templateid = el.getAttribute('template_id')
171+
if (templateid) {
172+
let items = document.querySelectorAll(`[templateid="${templateid}"]`)
173+
for (let item of items)
174+
item.remove()
175+
render.data({
176+
selector: `[template="${templateid}"]`,
177+
data
178+
});
179+
} else {
180+
let value = getValueFromObject(data, attribute);
181+
el.setValue(value);
182+
}
183+
}
126184
}
127185

128186
}

0 commit comments

Comments
 (0)