|
1 | 1 | /*globals CustomEvent, config*/ |
2 | 2 | import {getAttributes, getValueFromObject, dotNotationToObject} from "@cocreate/utils"; |
| 3 | +import observer from "@cocreate/observer"; |
3 | 4 | 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'; |
6 | 7 | import '@cocreate/element-prototype'; |
7 | | -import utils from "@cocreate/utils/src/utils"; |
8 | 8 |
|
9 | 9 | const CoCreateApi = { |
10 | 10 | 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) |
15 | 15 | 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 | | - }) |
32 | 16 | }, |
33 | 17 |
|
34 | | - register: function({name, actions}) { |
| 18 | + register: function({name, endPoints, options}) { |
35 | 19 | const self = this; |
36 | 20 | if (typeof this.components[name] === 'undefined') { |
37 | | - this.components[name] = {name, actions}; |
| 21 | + this.components[name] = {name, endPoints, options}; |
38 | 22 |
|
39 | 23 | socket.listen(name, (data) => { |
40 | 24 | self.__response(name, data); |
41 | 25 | }); |
42 | 26 |
|
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] |
45 | 29 | if (typeof functions.request !== 'function') { |
46 | 30 | functions.request = self.__request; |
47 | 31 | } |
48 | | - CoCreateAction.init({ |
49 | | - name: action, |
50 | | - endEvent: action, |
| 32 | + action.init({ |
| 33 | + name: endPoint, |
| 34 | + endEvent: endPoint, |
51 | 35 | 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 | + } |
53 | 45 | }, |
54 | 46 | }); |
55 | 47 | } |
| 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 | + }); |
56 | 96 | } |
57 | 97 | }, |
58 | 98 |
|
59 | | - __request: function(name, action, element) { |
| 99 | + __request: function({name, endPoint, element}) { |
60 | 100 | 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]); |
63 | 103 | }, |
64 | 104 |
|
65 | 105 | __response: function(name, data) { |
66 | | - const {action, response} = data; |
| 106 | + const {endPoint, response} = data; |
67 | 107 | 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 | + })); |
71 | 120 | } |
72 | | - else |
73 | | - this.render(action, response); |
74 | | - |
75 | | - document.dispatchEvent(new CustomEvent(action, { |
76 | | - detail: { |
77 | | - data: response |
78 | | - } |
79 | | - })); |
80 | 121 | }, |
81 | 122 |
|
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}); |
84 | 125 | }, |
85 | 126 |
|
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} |
92 | 137 |
|
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 | + |
100 | 140 |
|
| 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] |
101 | 149 | 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 | + |
107 | 156 | return dotNotationToObject(data); |
108 | 157 | }, |
109 | 158 |
|
110 | | - setData: function(attribute, action, data, form) { |
111 | | - const selector = `[${attribute}^="${action}."]` |
| 159 | + setData: function({name, endPoint, data, form}) { |
| 160 | + const selector = `[${name}^="${endPoint}."]` |
112 | 161 | if (!form) |
113 | 162 | form = document; |
114 | 163 | let elements = form.querySelectorAll(selector); |
115 | 164 | if (!elements || elements.length == 0) return |
116 | 165 |
|
117 | 166 | 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 | + } |
126 | 184 | } |
127 | 185 |
|
128 | 186 | } |
|
0 commit comments