@cocreate/events 1.9.4 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ # [1.10.0](https://github.com/CoCreate-app/CoCreate-events/compare/v1.9.4...v1.10.0) (2023-05-18)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * apikey renamed to key ([75296fb](https://github.com/CoCreate-app/CoCreate-events/commit/75296fb44dfab0c599700498e389147755ffbf05))
7
+
8
+
9
+ ### Features
10
+
11
+ * Refactor CoCreateEvents and add custom event functionality ([be5e630](https://github.com/CoCreate-app/CoCreate-events/commit/be5e63069d1b1249bea59d3bd5c29db5272837fc))
12
+
1
13
  ## [1.9.4](https://github.com/CoCreate-app/CoCreate-events/compare/v1.9.3...v1.9.4) (2023-05-06)
2
14
 
3
15
 
@@ -1,7 +1,7 @@
1
1
  module.exports = {
2
2
  "config": {
3
3
  "organization_id": "5ff747727005da1c272740ab",
4
- "apiKey": "2061acef-0451-4545-f754-60cf8160",
4
+ "key": "2061acef-0451-4545-f754-60cf8160",
5
5
  "host": "general.cocreate.app"
6
6
  },
7
7
  "sources": [
package/demo/index.html CHANGED
@@ -1,89 +1,135 @@
1
1
  <!DOCTYPE html>
2
2
  <html>
3
- <head>
4
- <title>Events | CoCreateJS</title>
5
-
6
- <!-- CoCreate Favicon -->
7
- <link rel="icon" href="https://cdn.cocreate.app/favicon.ico" type="image/ico" sizes="16x16">
8
-
9
-
10
- <!-- Custom CSS -->
11
- <style type="text/css">
12
- .test{background:red}
13
- .new{background:yellow}
14
- .active{
15
- background-color:blue;
16
- }
17
- .hidden {
18
- display: none;
19
- }
20
- </style>
21
- <link rel="manifest" href="/manifest.webmanifest" />
22
- </head>
23
- <body>
24
-
25
- <div toggle="active" class="test">hhh
26
- <!--<div class="test">click me</div><br/>-->
27
- </div>
28
-
29
-
30
-
31
-
32
- <i class="fas fa-plus-circle" toggle="fa-minus-circle, fa-plus-circle"></i>
33
-
34
- <article>
35
- <div id="div-01" class="vdom-item">
36
- <p>Here is div-01 i should get class hidden</p>
37
- <div>
38
- <div class="vdom-item" >some content1</div>
39
- <span toggle="test" toggle-closest=".vdom-item"><i class="height:16px fill:#505050" src="/assets/svg/caret-down".svg"></i></span>
40
- </div>
41
- <div class="vdom-item" >some content2</div>
42
- </div>
43
- <div class="vdom-item" >some content3</div>
44
- <div id="div-03">Here is div-03</div>
45
- </article>
46
- <br>
47
- <hr>
48
- <div class="vdom-item" toggle="active" toggle-target="article > div">some content</div>
49
- <br>
50
- <hr>
51
- <div class="vdom-item" toggle-attribute='class' toggle="active" toggle-target=".vdom-item">
52
- click for active
53
- </div>
54
- <br>
55
- <hr>
56
- TEST HERE
57
- <div class="vdom-item" id="hey" data-test="" toggle-attribute='id' toggle="active, other, hi, jean">
58
- some content
59
- </div>
60
-
61
- <!-- custom event example -->
62
- <div test-value="active" test-events="click" event>
63
- other content
64
- </div>
65
- <!-- defining key example -->
66
- <div click-target="#testing" click-value="hello, bye" click-key="ty"> click here</div>
67
- <div id="testing" class="{{ty}}">
68
- <span class="{{ty}}"><b a="{{ty}}">other content {{ty}}</b></span>
69
- <span class="{{ty}}"><b a="{{ty}}">other content {{ty}}</b></span>
70
- </div>
71
-
72
- <!-- defining key example -->
73
- <div >
74
- <div observe-target=".testing" observe-attribute="value">testing this new value</div>
75
- <input input-target=".testing" input-attribute="value" input-events="input, onload" value="great test">
76
- <input class="testing {{ty}}">
77
- <div class="testing {{ty}}">other content</div>
78
- </div>
3
+ <head>
4
+ <title>Events | CoCreateJS</title>
79
5
 
80
- <span id="keyname" clone-data='{"attributes": {"key": "{{keyname}}", "value": ""}}' {{keyname}}="test" style="margin-right:10px; padding:5px">
81
- <svg class="svg" width="12" height="12" viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg"><path d="M5 5V0h1v5h5v1H6v5H5V6H0V5h5z" fill-rule="nonzero" fill-opacity="1" fill="#fff" stroke="none"></path></svg>
82
- </span>
83
- <input placeholder="Search all attributes" input-value input-key="keyname" input-target="#keyname">
84
-
85
- <!--<script src="../dist/CoCreate-events.js"></script>-->
86
- <script src="https://cdn.cocreate.app/latest/CoCreate.min.js"></script>
6
+ <!-- CoCreate Favicon -->
7
+ <link
8
+ rel="icon"
9
+ href="https://cdn.cocreate.app/favicon.ico"
10
+ type="image/ico"
11
+ sizes="16x16" />
12
+
13
+ <!-- Custom CSS -->
14
+ <style type="text/css">
15
+ .test {
16
+ background: red;
17
+ }
18
+ .new {
19
+ background: yellow;
20
+ }
21
+ .active {
22
+ background-color: blue;
23
+ }
24
+ .hidden {
25
+ display: none;
26
+ }
27
+ </style>
28
+ <link rel="manifest" href="/manifest.webmanifest" />
29
+ </head>
30
+ <body>
31
+ <div toggle="active" class="test">
32
+ hhh
33
+ <!--<div class="test">click me</div><br/>-->
34
+ </div>
35
+
36
+ <i
37
+ class="fas fa-plus-circle"
38
+ toggle="fa-minus-circle, fa-plus-circle"></i>
39
+
40
+ <article>
41
+ <div id="div-01" class="vdom-item">
42
+ <p>Here is div-01 i should get class hidden</p>
43
+ <div>
44
+ <div class="vdom-item">some content1</div>
45
+ <span toggle="test" toggle-closest=".vdom-item">
46
+ <i
47
+ class="height:16px fill:#505050"
48
+ src="/assets/svg/caret-down.svg"></i>
49
+ </span>
50
+ </div>
51
+ <div class="vdom-item">some content2</div>
52
+ </div>
53
+ <div class="vdom-item">some content3</div>
54
+ <div id="div-03">Here is div-03</div>
55
+ </article>
56
+ <br />
57
+ <hr />
58
+ <div class="vdom-item" toggle="active" toggle-target="article > div">
59
+ some content
60
+ </div>
61
+ <br />
62
+ <hr />
63
+ <div
64
+ class="vdom-item"
65
+ toggle-attribute="class"
66
+ toggle="active"
67
+ toggle-target=".vdom-item">
68
+ click for active
69
+ </div>
70
+ <br />
71
+ <hr />
72
+ TEST HERE
73
+ <div
74
+ class="vdom-item"
75
+ id="hey"
76
+ data-test=""
77
+ toggle-attribute="id"
78
+ toggle="active, other, hi, jean">
79
+ some content
80
+ </div>
87
81
 
88
- </body>
89
- </html>
82
+ <!-- custom event example -->
83
+ <div test-value="active" test-events="click" event>other content</div>
84
+ <!-- defining key example -->
85
+ <div click-target="#testing" click-value="hello, bye" click-key="ty">
86
+ click here
87
+ </div>
88
+ <div id="testing" class="{{ty}}">
89
+ <span class="{{ty}}"><b a="{{ty}}">other content {{ty}}</b></span>
90
+ <span class="{{ty}}"><b a="{{ty}}">other content {{ty}}</b></span>
91
+ </div>
92
+
93
+ <!-- defining key example -->
94
+ <div>
95
+ <div observe-target=".testing" observe-attribute="value">
96
+ testing this new value
97
+ </div>
98
+ <input
99
+ input-target=".testing"
100
+ input-attribute="value"
101
+ input-events="input, onload"
102
+ value="great test" />
103
+ <input class="testing {{ty}}" />
104
+ <div class="testing {{ty}}">other content</div>
105
+ </div>
106
+
107
+ <span
108
+ id="keyname"
109
+ clone-data="{'attributes': {'key': '{{keyname}}', 'value': ''}}"
110
+ {{keyname}}="test"
111
+ style="margin-right: 10px; padding: 5px">
112
+ <svg
113
+ class="svg"
114
+ width="12"
115
+ height="12"
116
+ viewBox="0 0 12 12"
117
+ xmlns="http://www.w3.org/2000/svg">
118
+ <path
119
+ d="M5 5V0h1v5h5v1H6v5H5V6H0V5h5z"
120
+ fill-rule="nonzero"
121
+ fill-opacity="1"
122
+ fill="#fff"
123
+ stroke="none"></path>
124
+ </svg>
125
+ </span>
126
+ <input
127
+ placeholder="Search all attributes"
128
+ input-value
129
+ input-key="keyname"
130
+ input-target="#keyname" />
131
+
132
+ <!--<script src="../dist/CoCreate-events.js"></script>-->
133
+ <script src="https://cdn.cocreate.app/latest/CoCreate.min.js"></script>
134
+ </body>
135
+ </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cocreate/events",
3
- "version": "1.9.4",
3
+ "version": "1.10.0",
4
4
  "description": "A simple events component in vanilla javascript. Easily configured using HTML5 attributes and/or JavaScript API.",
5
5
  "keywords": [
6
6
  "events",
package/src/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import {queryDocumentSelectorAll} from '@cocreate/utils';
1
+ import { queryDocumentSelectorAll } from '@cocreate/utils';
2
2
  import action from '@cocreate/actions';
3
3
  import observer from '@cocreate/observer';
4
4
  import '@cocreate/element-prototype';
@@ -6,376 +6,376 @@ import '@cocreate/element-prototype';
6
6
 
7
7
  const CoCreateEvents = {
8
8
 
9
- init: function(prefix, events) {
10
- if (prefix && events)
11
- this.initPrefix(prefix, events);
12
- else {
13
- this.initPrefix('toggle', ['click']);
14
- this.initPrefix('click', ['click']);
15
- this.initPrefix('hover', ['mouseover', 'mouseout']);
16
- this.initPrefix('mouseover', ['mouseover']);
17
- this.initPrefix('mouseout', ['mouseout']);
18
- this.initPrefix('input', ['input']);
19
- this.initPrefix('change', ['change']);
20
- this.initPrefix('selected', ['click']);
21
- this.initPrefix('onload', ['onload']);
22
- this.initPrefix('observe', ['observer']);
23
- this.initPrefix('localstorage', ['onload', 'observer']);
24
- }
25
-
26
- let customEventEls = document.querySelectorAll('[event-name]')
27
- let names = {}
28
- for (let customEventEl of customEventEls) {
29
- let name = customEventEl.getAttribute('event-name')
30
- if(!names[name]) {
31
- names[name] = name
32
- this.initPrefix(name);
33
- }
34
- }
35
-
36
- const self = this
37
- observer.init({
38
- name: 'CoCreateEventName',
39
- observe: ['addedNodes'],
40
- target: `[event-name]`,
41
- callback: function(mutation) {
42
- let name = mutation.target.getAttribute('event-name')
43
- self.initPrefix(name);
44
- }
45
- });
46
-
47
- },
48
-
49
- initPrefix: function(prefix, events) {
50
- const self = this;
51
-
52
- action.init({
53
- name: prefix,
54
- endEvent: `${prefix}End`,
55
- callback: (btn, data) => {
56
- this.__updateElements(btn, prefix)
57
- }
58
- });
59
-
60
- let selector = `[${prefix}], [${prefix}-key], [${prefix}-value], [${prefix}-target], [${prefix}-closest], [${prefix}-parent], [${prefix}-next], [${prefix}-previous]`
61
-
62
- observer.init({
63
- name: 'CoCreateEventattributes',
64
- observe: ['attributes', 'addedNodes'],
65
- attributeName: [`${prefix}-events`],
66
- target: selector,
67
- callback: function(mutation) {
68
- self.initElements([mutation.target], prefix, events)
69
- }
70
- });
71
-
72
- if (events.includes('observer')) {
73
- observer.init({
74
- name: 'observerAttributes',
75
- observe: ['attributes'],
76
- attributeName: [`${prefix}-key`, `${prefix}-value`, `${prefix}-target`, `${prefix}-closest`, `${prefix}-parent`, `${prefix}-next`, `${prefix}-previous`],
77
- callback: function(mutation) {
78
- // remove previous observer
79
- self.initElements([mutation.target], prefix, events)
80
- }
81
- });
82
- }
83
-
84
- let elements = document.querySelectorAll(selector)
85
- this.initElements(elements, prefix, events);
86
- },
87
-
88
- elements: new Map(),
89
- initElements: function(elements, prefix, events = []) {
90
- const self = this
91
- for (const el of elements) {
92
- let isEventable = true
93
- let prefixes = this.elements.get(el)
94
- if (!prefixes) {
95
- prefixes = {[prefix]: {events}}
96
- this.elements.set(el, prefixes)
97
- } else if (!prefixes[prefix]) {
98
- prefixes[prefix] = {events}
99
- } else {
100
- isEventable = false
101
- // events = //prefixes[prefix].events
102
- }
103
-
104
- let customEvents = el.getAttribute(`${prefix}-events`)
105
- if (customEvents) {
106
- customEvents = customEvents.split(',')
107
- for (let i = 0; i < customEvents.length; i++)
108
- customEvents[i] = customEvents[i].trim()
109
-
110
- for (let i = 0; i < events.length; i++)
111
- el.removeEventListener(events[i], eventFunction)
112
-
113
- events = customEvents
114
- prefixes[prefix].events = events
115
- isEventable = true
116
- }
117
- if (!events || !isEventable)
118
- continue
119
- if (events.includes('onload'))
120
- this.__updateElements(el, prefix);
121
-
122
- if (events.includes('observer')) {
123
- let target;
124
- for (let attribute of el.attributes) {
125
- if ([`${prefix}-target`, `${prefix}-closest`, `${prefix}-parent`, `${prefix}-next`, `${prefix}-previous`].includes(attribute.name)) {
126
- target = attribute.value
127
- break;
128
- }
129
- }
130
-
131
- observer.init({
132
- observe: ['addedNodes'],
133
- target,
134
- callback: function(mutation) {
135
- self.__updateElements(el, prefix, mutation.target);
136
- }
137
- });
138
- }
139
-
140
- for (let i = 0; i < events.length; i++) {
141
- if (events[i] !== 'onload' && events[i] !== 'observer') {
142
- el.removeEventListener(events[i], eventFunction)
143
- el.addEventListener(events[i], eventFunction);
144
- }
145
- }
146
-
147
- function eventFunction(event) {
148
- // ToDo: apply debounce
149
- // let debounce;
150
- // clearTimeout(debounce);
151
- // debounce = setTimeout(function() {
152
- const target = event.currentTarget
153
- if (target) {
154
- let prefixes = self.elements.get(target)
155
- if (prefixes[prefix].prev === event.type && ['mouseover', 'mouseout'].includes(event.type))
156
- return
157
- else
158
- prefixes[prefix].prev = event.type
159
-
160
- let attribute = target.getAttribute('actions') || ""
161
- if (attribute.includes(prefix))
162
- return;
163
- // if (target.closest(`[actions*="${prefix}"]`))
164
- // return;
165
- self.__updateElements(target, prefix);
166
-
167
- let selector = `[${prefix}], [${prefix}-key], [${prefix}-value], [${prefix}-target], [${prefix}-closest], [${prefix}-parent], [${prefix}-next], [${prefix}-previous]`
168
-
169
- let parentElement = target.parentElement;
170
- if (parentElement) {
171
- do {
172
- parentElement = parentElement.closest(selector)
173
- if (parentElement) {
174
- self.__updateElements(parentElement, prefix);
175
- parentElement = parentElement.parentElement
176
- }
177
- }
178
- while (parentElement)
179
-
180
- }
181
-
182
- }
183
- // }, 500);
184
- }
185
-
186
-
187
- }
188
- },
189
-
190
- __updateElements: function(element, prefix, target) {
191
- const self = this;
192
- // ToDo: support empty value when prefix-attribute defined, add and remove the attribute
193
-
194
- let values
195
- if (prefix === 'localstorage') {
196
- let key = element.getAttribute('localstorage-get')
197
- if (key)
198
- values = localStorage.getItem(key)
199
- else
200
- return
201
- } else
202
- values = element.getAttribute(`${prefix}-value`) || element.getAttribute(prefix);
203
- if (values)
204
- values = values.split(',');
205
- else {
206
- values = element.getValue()
207
- if (!Array.isArray(values))
208
- values = [values]
209
- }
210
-
211
- if (!values || values.length == 0)
212
- return;
213
-
214
- let targetAttribute = element.getAttribute(`${prefix}-attribute`) || 'class';
215
- let targetText = element.getAttribute(`${prefix}-text`);
216
- let targetHtml = element.getAttribute(`${prefix}-html`);
217
- let targetSelector = element.getAttribute(`${prefix}-target`);
218
- let targetClosest = element.getAttribute(`${prefix}-closest`);
219
- let targetParent = element.getAttribute(`${prefix}-parent`);
220
- let targetNext = element.getAttribute(`${prefix}-next`);
221
- let targetPrevious = element.getAttribute(`${prefix}-previous`);
222
-
223
- let targetKey = element.getAttribute(`${prefix}-key`);
224
-
225
- let targetGroup = element.getAttribute(`${prefix}-group`);
226
- if (targetGroup) {
227
- document.querySelectorAll(`[${prefix}-group="${targetGroup}"]`).forEach((el) => {
228
- let groupValue = el.getAttribute(`${prefix}-value`) || el.getAttribute(prefix);
229
- let groupValues = groupValue.split(',');
230
- if (!groupValues || groupValues.length == 0) {
231
- return;
232
- }
233
-
234
- groupValues = groupValues.map(x => x.trim());
235
-
236
- let groupTarget = el.getAttribute(`${prefix}-target`);
237
- let groupClosest = el.getAttribute(`${prefix}-closest`);
238
- let groupParent = el.getAttribute(`${prefix}-parent`);
239
- let groupNext = el.getAttribute(`${prefix}-next`);
240
- let groupPrevious = el.getAttribute(`${prefix}-previous`);
241
- let groupAttribute = el.getAttribute(`${prefix}-attribute`) || 'class';
242
- let groupKey = el.getAttribute(`${prefix}-key`)
243
-
244
- // el.removeAttribute(prefix)
245
- self.setValue(prefix, el, groupAttribute, groupValues, groupKey, 'deactivate')
246
- if (groupTarget)
247
- document.querySelectorAll(groupTarget).forEach((el) =>
248
- self.setValue(prefix, el, groupAttribute, groupValues, groupKey, 'deactivate')
249
- );
250
- else if (groupClosest) {
251
- let element = el.closest(groupClosest)
252
- if (element)
253
- self.setValue(prefix, element, groupAttribute, groupValues, groupKey, 'deactivate');
254
- }
255
- else if (groupParent)
256
- el.parentElement.querySelectorAll(groupParent).forEach((el) =>
257
- self.setValue(prefix, el, groupAttribute, groupValues, groupKey, 'deactivate')
258
- );
259
- else if (groupNext)
260
- el.nextElementSibling.querySelectorAll(groupNext).forEach((el) =>
261
- self.setValue(prefix, el, groupAttribute, groupValues, groupKey, 'deactivate')
262
- );
263
- else if (groupPrevious)
264
- el.previousElementSibling.querySelectorAll(groupPrevious).forEach((el) =>
265
- self.setValue(prefix, el, groupAttribute, groupValues, groupKey, 'deactivate')
266
- );
267
-
268
- });
269
- }
270
-
271
- values = values.map(x => x.trim());
272
- let targetElements = [element];
273
- if (target) {
274
- self.setValue(prefix, target, targetAttribute, values, targetKey);
275
- } else if (targetSelector) {
276
- if (/{{\s*([\w\W]+)\s*}}/g.test(targetSelector)) return;
277
- targetElements = queryDocumentSelectorAll(targetSelector);
278
- targetElements.forEach((el) => self.setValue(prefix, el, targetAttribute, values, targetKey));
279
- } else if (targetClosest) {
280
- element = element.closest(targetClosest);
281
- self.setValue(prefix, element, targetAttribute, values, targetKey);
282
- } else if (targetParent) {
283
- element.parentElement.querySelectorAll(targetParent).forEach((el) =>
284
- self.setValue(prefix, el, targetAttribute, values, targetKey)
285
- );
286
- } else if (targetNext) {
287
- element.nextElementSibling.querySelectorAll(targetNext).forEach((el) =>
288
- self.setValue(prefix, el, targetAttribute, values, targetKey)
289
- );
290
- } else if (targetPrevious) {
291
- element.previousElementSibling.querySelectorAll(targetPrevious).forEach((el) =>
292
- self.setValue(prefix, el, targetAttribute, values, targetKey)
293
- );
294
- } else
295
- self.setValue(prefix, element, targetAttribute, values, targetKey);
296
-
297
- document.dispatchEvent(new CustomEvent(`${prefix}End`, {
298
- detail: {}
299
- }))
300
-
301
- },
302
-
303
- setValue: function(prefix, element, attrName, values, key, deactivate) {
304
- let attrValues, oldValue;
305
- if (key) {
306
- key = `{{${key}}}`;
307
- // let value = values[0]
308
- replaceKey(prefix, element, key, values)
309
- } else {
310
- if (attrName === 'style') {
311
- if (element.getAttribute(attrName)) {
312
- attrValues = element.getAttribute(attrName).split(';').map(x => x.trim());
313
- attrValues = attrValues.map(function(item, index){
314
- return item.replace(' ','');
315
- });
316
- oldValue = values.filter(x => attrValues.includes(x))[0] || '';
317
- }
318
- let newValue = this.__getNextValue(values, oldValue);
319
-
320
- if (oldValue) {
321
- let [property, value] = oldValue.split(":");
322
- element.style[property] = '';
323
- }
324
-
325
- if (newValue != '') {
326
- newValue = newValue.split(';').map(x => x.trim())
327
- for (let style of newValue) {
328
- let [property, value] = style.split(":");
329
- element.style[property] = value;
330
- }
331
- }
332
- } else {
333
- if (attrName === 'value') {
334
- oldValue = element.getValue()
335
- } else if (attrName === 'text') {
336
- attrValues = element.getAttribute(attrName).split(' ').map(x => x.trim());
337
- oldValue = values.filter(x => attrValues.includes(x))[0] || '';
338
- } else if (attrName === 'html') {
339
- attrValues = element.getAttribute(attrName).split(' ').map(x => x.trim());
340
- oldValue = values.filter(x => attrValues.includes(x))[0] || '';
341
- } else if (element.getAttribute(attrName)) {
342
- attrValues = element.getAttribute(attrName).split(' ').map(x => x.trim());
343
- oldValue = values.filter(x => attrValues.includes(x))[0] || '';
344
- }
345
-
346
- let newValue = this.__getNextValue(values, oldValue);
347
- if (deactivate)
348
- newValue = ""
349
-
350
- if (attrName === 'class') {
351
- if (oldValue) {
352
- element.classList.remove(oldValue);
353
- if (values.length === 1) {
354
- return;
355
- }
356
- }
357
-
358
- if (newValue) {
359
- element.classList.add(newValue);
360
- }
361
- } else if (attrName === 'value') {
362
- element.setValue(newValue);
363
- } else {
364
- element.setAttribute(attrName, newValue);
365
- }
366
- }
367
- }
368
- },
369
-
370
- __getNextValue: function(values, val) {
371
- let size = values.length;
372
- let nn = values.indexOf(val);
373
- if (nn == -1) {
374
- return values[0];
375
- } else {
376
- return values[(nn + 1) % size];
377
- }
378
- }
9
+ init: function (prefix, events) {
10
+ if (prefix && events)
11
+ this.initPrefix(prefix, events);
12
+ else {
13
+ this.initPrefix('toggle', ['click']);
14
+ this.initPrefix('click', ['click']);
15
+ this.initPrefix('hover', ['mouseover', 'mouseout']);
16
+ this.initPrefix('mouseover', ['mouseover']);
17
+ this.initPrefix('mouseout', ['mouseout']);
18
+ this.initPrefix('input', ['input']);
19
+ this.initPrefix('change', ['change']);
20
+ this.initPrefix('selected', ['click']);
21
+ this.initPrefix('onload', ['onload']);
22
+ this.initPrefix('observe', ['observer']);
23
+ this.initPrefix('localstorage', ['onload', 'observer']);
24
+ }
25
+
26
+ let customEventEls = document.querySelectorAll('[event-name]')
27
+ let names = {}
28
+ for (let customEventEl of customEventEls) {
29
+ let name = customEventEl.getAttribute('event-name')
30
+ if (!names[name]) {
31
+ names[name] = name
32
+ this.initPrefix(name);
33
+ }
34
+ }
35
+
36
+ const self = this
37
+ observer.init({
38
+ name: 'CoCreateEventName',
39
+ observe: ['addedNodes'],
40
+ target: `[event-name]`,
41
+ callback: function (mutation) {
42
+ let name = mutation.target.getAttribute('event-name')
43
+ self.initPrefix(name);
44
+ }
45
+ });
46
+
47
+ },
48
+
49
+ initPrefix: function (prefix, events) {
50
+ const self = this;
51
+
52
+ action.init({
53
+ name: prefix,
54
+ endEvent: `${prefix}End`,
55
+ callback: (btn, data) => {
56
+ this.__updateElements(btn, prefix)
57
+ }
58
+ });
59
+
60
+ let selector = `[${prefix}], [${prefix}-key], [${prefix}-attribute], [${prefix}-value], [${prefix}-target], [${prefix}-closest], [${prefix}-parent], [${prefix}-next], [${prefix}-previous]`
61
+
62
+ observer.init({
63
+ name: 'CoCreateEventattributes',
64
+ observe: ['attributes', 'addedNodes'],
65
+ attributeName: [`${prefix}-events`],
66
+ target: selector,
67
+ callback: function (mutation) {
68
+ self.initElements([mutation.target], prefix, events)
69
+ }
70
+ });
71
+
72
+ if (events.includes('observer')) {
73
+ observer.init({
74
+ name: 'observerAttributes',
75
+ observe: ['attributes'],
76
+ attributeName: [`${prefix}-key`, `${prefix}-value`, `${prefix}-target`, `${prefix}-closest`, `${prefix}-parent`, `${prefix}-next`, `${prefix}-previous`],
77
+ callback: function (mutation) {
78
+ // remove previous observer
79
+ self.initElements([mutation.target], prefix, events)
80
+ }
81
+ });
82
+ }
83
+
84
+ let elements = document.querySelectorAll(selector)
85
+ this.initElements(elements, prefix, events);
86
+ },
87
+
88
+ elements: new Map(),
89
+ initElements: function (elements, prefix, events = []) {
90
+ const self = this
91
+ for (const el of elements) {
92
+ let isEventable = true
93
+ let prefixes = this.elements.get(el)
94
+ if (!prefixes) {
95
+ prefixes = { [prefix]: { events } }
96
+ this.elements.set(el, prefixes)
97
+ } else if (!prefixes[prefix]) {
98
+ prefixes[prefix] = { events }
99
+ } else {
100
+ isEventable = false
101
+ // events = //prefixes[prefix].events
102
+ }
103
+
104
+ let customEvents = el.getAttribute(`${prefix}-events`)
105
+ if (customEvents) {
106
+ customEvents = customEvents.split(',')
107
+ for (let i = 0; i < customEvents.length; i++)
108
+ customEvents[i] = customEvents[i].trim()
109
+
110
+ for (let i = 0; i < events.length; i++)
111
+ el.removeEventListener(events[i], eventFunction)
112
+
113
+ events = customEvents
114
+ prefixes[prefix].events = events
115
+ isEventable = true
116
+ }
117
+ if (!events || !isEventable)
118
+ continue
119
+ if (events.includes('onload'))
120
+ this.__updateElements(el, prefix);
121
+
122
+ if (events.includes('observer')) {
123
+ let target;
124
+ for (let attribute of el.attributes) {
125
+ if ([`${prefix}-target`, `${prefix}-closest`, `${prefix}-parent`, `${prefix}-next`, `${prefix}-previous`].includes(attribute.name)) {
126
+ target = attribute.value
127
+ break;
128
+ }
129
+ }
130
+ if (target)
131
+ observer.init({
132
+ observe: ['addedNodes'],
133
+ target,
134
+ callback: function (mutation) {
135
+ self.__updateElements(el, prefix, mutation.target);
136
+ }
137
+ });
138
+ }
139
+
140
+ for (let i = 0; i < events.length; i++) {
141
+ if (events[i] !== 'onload' && events[i] !== 'observer') {
142
+ el.removeEventListener(events[i], eventFunction)
143
+ el.addEventListener(events[i], eventFunction);
144
+ }
145
+ }
146
+
147
+ function eventFunction(event) {
148
+ // TODO: apply debounce
149
+ // let debounce;
150
+ // clearTimeout(debounce);
151
+ // debounce = setTimeout(function() {
152
+ const target = event.currentTarget
153
+ if (target) {
154
+ let prefixes = self.elements.get(target)
155
+ if (prefixes[prefix].prev === event.type && ['mouseover', 'mouseout'].includes(event.type))
156
+ return
157
+ else
158
+ prefixes[prefix].prev = event.type
159
+
160
+ let attribute = target.getAttribute('actions') || ""
161
+ if (attribute.includes(prefix))
162
+ return;
163
+ // if (target.closest(`[actions*="${prefix}"]`))
164
+ // return;
165
+ self.__updateElements(target, prefix);
166
+
167
+ let selector = `[${prefix}], [${prefix}-key], [${prefix}-value], [${prefix}-target], [${prefix}-closest], [${prefix}-parent], [${prefix}-next], [${prefix}-previous]`
168
+
169
+ let parentElement = target.parentElement;
170
+ if (parentElement) {
171
+ do {
172
+ parentElement = parentElement.closest(selector)
173
+ if (parentElement) {
174
+ self.__updateElements(parentElement, prefix);
175
+ parentElement = parentElement.parentElement
176
+ }
177
+ }
178
+ while (parentElement)
179
+
180
+ }
181
+
182
+ }
183
+ // }, 500);
184
+ }
185
+
186
+
187
+ }
188
+ },
189
+
190
+ __updateElements: function (element, prefix, target) {
191
+ const self = this;
192
+ // TODO: support empty value when prefix-attribute defined, add and remove the attribute
193
+
194
+ let values
195
+ if (prefix === 'localstorage') {
196
+ let key = element.getAttribute('localstorage-get')
197
+ if (key)
198
+ values = localStorage.getItem(key)
199
+ else
200
+ return
201
+ } else
202
+ values = element.getAttribute(`${prefix}-value`) || element.getAttribute(prefix);
203
+ if (values)
204
+ values = values.split(',');
205
+ else {
206
+ values = element.getValue()
207
+ if (!Array.isArray(values))
208
+ values = [values]
209
+ }
210
+
211
+ if (!values || values.length == 0)
212
+ return;
213
+
214
+ let targetAttribute = element.getAttribute(`${prefix}-attribute`) || 'class';
215
+ let targetText = element.getAttribute(`${prefix}-text`);
216
+ let targetHtml = element.getAttribute(`${prefix}-html`);
217
+ let targetSelector = element.getAttribute(`${prefix}-target`);
218
+ let targetClosest = element.getAttribute(`${prefix}-closest`);
219
+ let targetParent = element.getAttribute(`${prefix}-parent`);
220
+ let targetNext = element.getAttribute(`${prefix}-next`);
221
+ let targetPrevious = element.getAttribute(`${prefix}-previous`);
222
+
223
+ let targetKey = element.getAttribute(`${prefix}-key`);
224
+
225
+ let targetGroup = element.getAttribute(`${prefix}-group`);
226
+ if (targetGroup) {
227
+ document.querySelectorAll(`[${prefix}-group="${targetGroup}"]`).forEach((el) => {
228
+ let groupValue = el.getAttribute(`${prefix}-value`) || el.getAttribute(prefix);
229
+ let groupValues = groupValue.split(',');
230
+ if (!groupValues || groupValues.length == 0) {
231
+ return;
232
+ }
233
+
234
+ groupValues = groupValues.map(x => x.trim());
235
+
236
+ let groupTarget = el.getAttribute(`${prefix}-target`);
237
+ let groupClosest = el.getAttribute(`${prefix}-closest`);
238
+ let groupParent = el.getAttribute(`${prefix}-parent`);
239
+ let groupNext = el.getAttribute(`${prefix}-next`);
240
+ let groupPrevious = el.getAttribute(`${prefix}-previous`);
241
+ let groupAttribute = el.getAttribute(`${prefix}-attribute`) || 'class';
242
+ let groupKey = el.getAttribute(`${prefix}-key`)
243
+
244
+ // el.removeAttribute(prefix)
245
+ self.setValue(prefix, el, groupAttribute, groupValues, groupKey, 'deactivate')
246
+ if (groupTarget)
247
+ document.querySelectorAll(groupTarget).forEach((el) =>
248
+ self.setValue(prefix, el, groupAttribute, groupValues, groupKey, 'deactivate')
249
+ );
250
+ else if (groupClosest) {
251
+ let element = el.closest(groupClosest)
252
+ if (element)
253
+ self.setValue(prefix, element, groupAttribute, groupValues, groupKey, 'deactivate');
254
+ }
255
+ else if (groupParent)
256
+ el.parentElement.querySelectorAll(groupParent).forEach((el) =>
257
+ self.setValue(prefix, el, groupAttribute, groupValues, groupKey, 'deactivate')
258
+ );
259
+ else if (groupNext)
260
+ el.nextElementSibling.querySelectorAll(groupNext).forEach((el) =>
261
+ self.setValue(prefix, el, groupAttribute, groupValues, groupKey, 'deactivate')
262
+ );
263
+ else if (groupPrevious)
264
+ el.previousElementSibling.querySelectorAll(groupPrevious).forEach((el) =>
265
+ self.setValue(prefix, el, groupAttribute, groupValues, groupKey, 'deactivate')
266
+ );
267
+
268
+ });
269
+ }
270
+
271
+ values = values.map(x => x.trim());
272
+ let targetElements = [element];
273
+ if (target) {
274
+ self.setValue(prefix, target, targetAttribute, values, targetKey);
275
+ } else if (targetSelector) {
276
+ if (/{{\s*([\w\W]+)\s*}}/g.test(targetSelector)) return;
277
+ targetElements = queryDocumentSelectorAll(targetSelector);
278
+ targetElements.forEach((el) => self.setValue(prefix, el, targetAttribute, values, targetKey));
279
+ } else if (targetClosest) {
280
+ element = element.closest(targetClosest);
281
+ self.setValue(prefix, element, targetAttribute, values, targetKey);
282
+ } else if (targetParent) {
283
+ element.parentElement.querySelectorAll(targetParent).forEach((el) =>
284
+ self.setValue(prefix, el, targetAttribute, values, targetKey)
285
+ );
286
+ } else if (targetNext) {
287
+ element.nextElementSibling.querySelectorAll(targetNext).forEach((el) =>
288
+ self.setValue(prefix, el, targetAttribute, values, targetKey)
289
+ );
290
+ } else if (targetPrevious) {
291
+ element.previousElementSibling.querySelectorAll(targetPrevious).forEach((el) =>
292
+ self.setValue(prefix, el, targetAttribute, values, targetKey)
293
+ );
294
+ } else
295
+ self.setValue(prefix, element, targetAttribute, values, targetKey);
296
+
297
+ document.dispatchEvent(new CustomEvent(`${prefix}End`, {
298
+ detail: {}
299
+ }))
300
+
301
+ },
302
+
303
+ setValue: function (prefix, element, attrName, values, key, deactivate) {
304
+ let attrValues, oldValue;
305
+ if (key) {
306
+ key = `{{${key}}}`;
307
+ // let value = values[0]
308
+ replaceKey(prefix, element, key, values)
309
+ } else {
310
+ if (attrName === 'style') {
311
+ if (element.getAttribute(attrName)) {
312
+ attrValues = element.getAttribute(attrName).split(';').map(x => x.trim());
313
+ attrValues = attrValues.map(function (item, index) {
314
+ return item.replace(' ', '');
315
+ });
316
+ oldValue = values.filter(x => attrValues.includes(x))[0] || '';
317
+ }
318
+ let newValue = this.__getNextValue(values, oldValue);
319
+
320
+ if (oldValue) {
321
+ let [property, value] = oldValue.split(":");
322
+ element.style[property] = '';
323
+ }
324
+
325
+ if (newValue != '') {
326
+ newValue = newValue.split(';').map(x => x.trim())
327
+ for (let style of newValue) {
328
+ let [property, value] = style.split(":");
329
+ element.style[property] = value;
330
+ }
331
+ }
332
+ } else {
333
+ if (attrName === 'value') {
334
+ oldValue = element.getValue()
335
+ } else if (attrName === 'text') {
336
+ attrValues = element.getAttribute(attrName).split(' ').map(x => x.trim());
337
+ oldValue = values.filter(x => attrValues.includes(x))[0] || '';
338
+ } else if (attrName === 'html') {
339
+ attrValues = element.getAttribute(attrName).split(' ').map(x => x.trim());
340
+ oldValue = values.filter(x => attrValues.includes(x))[0] || '';
341
+ } else if (element.getAttribute(attrName)) {
342
+ attrValues = element.getAttribute(attrName).split(' ').map(x => x.trim());
343
+ oldValue = values.filter(x => attrValues.includes(x))[0] || '';
344
+ }
345
+
346
+ let newValue = this.__getNextValue(values, oldValue);
347
+ if (deactivate)
348
+ newValue = ""
349
+
350
+ if (attrName === 'class') {
351
+ if (oldValue) {
352
+ element.classList.remove(oldValue);
353
+ if (values.length === 1) {
354
+ return;
355
+ }
356
+ }
357
+
358
+ if (newValue) {
359
+ element.classList.add(newValue);
360
+ }
361
+ } else if (attrName === 'value') {
362
+ element.setValue(newValue);
363
+ } else {
364
+ element.setAttribute(attrName, newValue);
365
+ }
366
+ }
367
+ }
368
+ },
369
+
370
+ __getNextValue: function (values, val) {
371
+ let size = values.length;
372
+ let nn = values.indexOf(val);
373
+ if (nn == -1) {
374
+ return values[0];
375
+ } else {
376
+ return values[(nn + 1) % size];
377
+ }
378
+ }
379
379
  };
380
380
 
381
381
  const eventElements = new Map();
@@ -383,99 +383,99 @@ const eventKeys = new Map();
383
383
  const elementAttributes = new Map();
384
384
 
385
385
  function replaceKey(prefix, element, key, values) {
386
- let currentValue = key
387
-
388
- if (eventElements.has(element)) {
389
- currentValue = eventElements.get(element).get(key);
390
- }
391
- let value = CoCreateEvents.__getNextValue(values, currentValue);
392
- eventKeys.set(key, value)
393
- eventElements.set(element, eventKeys)
394
-
395
- let attributes = elementAttributes.get(element)
396
- if (!attributes) {
397
- attributes = {}
398
- elementAttributes.set(element, attributes)
399
- }
400
-
401
-
402
- for (let attribute of element.attributes){
403
- let newName = attribute.name;
404
- let newValue = attribute.value;
405
- let attrName = attribute.name;
406
- let attrValue = attribute.value;
407
- let setAttr = false;
408
-
409
- if(attrName === 'clone-data')
410
- console.log('clone-data')
411
- if (attrValue.includes(currentValue) || attributes[attrName] && attributes[attrName].valueKeys && attributes[attrName].valueKeys[key]){
412
- if (!attributes[attrName])
413
- attributes[attrName] = { originalValue: attrValue }
414
- else if (!attributes[attrName].originalValue)
415
- attributes[attrName].originalValue = attrValue
416
- if (!attributes[attrName].valueKeys)
417
- attributes[attrName].valueKeys = {[key]: value}
418
- else
419
- attributes[attrName].valueKeys[key] = value;
420
-
421
- newValue = attributes[attrName].originalValue
422
- for (let valueKey of Object.keys(attributes[attrName].valueKeys)) {
423
- const valueKeyRegex = new RegExp(valueKey, "g");
424
- newValue = newValue.replace(valueKeyRegex, value);
425
- }
426
- setAttr = true;
427
- }
428
- // if (attrName.includes(currentValue) || attributes[attrName] && attributes[attrName].nameKeys && attributes[attrName].nameKeys[key]){
429
- // if (!attributes[attrName])
430
- // attributes[attrName] = { originalName: attrName }
431
- // else if (!attributes[attrName].originalName)
432
- // attributes[attrName].originalName = attrName
433
-
434
- // if (!attributes[attrName].nameKeys)
435
- // attributes[attrName].nameKeys = {[key]: value}
436
-
437
- // newName = attributes[attrName].originalName
438
- // for (let nameKey of Object.keys(attributes[attrName].nameKeys)) {
439
- // let r
440
- // if (attrName === nameKey)
441
- // r = nameKey
442
- // else
443
- // r = attributes[attrName].nameKeys[nameKey]
444
-
445
- // const nameKeyRegex = new RegExp(r, "g");
446
- // newName = newName.replace(nameKeyRegex, value);
447
- // }
448
-
449
- // attributes[attrName].nameKeys[key] = value;
450
-
451
-
452
- // element.removeAttribute(attrName);
453
- // setAttr = true;
454
-
455
- // }
456
- if (setAttr)
457
- element.setAttribute(newName, newValue);
458
- }
459
- let html = element.innerHTML;
460
- if (html.indexOf(currentValue) !== -1 || element.htmlKeys && element.htmlKeys[key]) {
461
- if (!element.originalHtml)
462
- element.originalHtml = html
463
- if (!element.htmlKeys)
464
- element.htmlKeys = {[key]: value}
465
- else
466
- element.htmlKeys[key] = value;
467
-
468
- let newHTML = element.originalHtml
469
- if (newHTML) {
470
- for (let elementKey of Object.keys(element.htmlKeys)) {
471
- const htmlKeyRegex = new RegExp(elementKey, "g");
472
- newHTML = newHTML.replace(htmlKeyRegex, value);
473
- }
474
-
475
- element.innerHTML = newHTML;
476
- }
477
- }
478
-
386
+ let currentValue = key
387
+
388
+ if (eventElements.has(element)) {
389
+ currentValue = eventElements.get(element).get(key);
390
+ }
391
+ let value = CoCreateEvents.__getNextValue(values, currentValue);
392
+ eventKeys.set(key, value)
393
+ eventElements.set(element, eventKeys)
394
+
395
+ let attributes = elementAttributes.get(element)
396
+ if (!attributes) {
397
+ attributes = {}
398
+ elementAttributes.set(element, attributes)
399
+ }
400
+
401
+
402
+ for (let attribute of element.attributes) {
403
+ let newName = attribute.name;
404
+ let newValue = attribute.value;
405
+ let attrName = attribute.name;
406
+ let attrValue = attribute.value;
407
+ let setAttr = false;
408
+
409
+ if (attrName === 'clone-data')
410
+ console.log('clone-data')
411
+ if (attrValue.includes(currentValue) || attributes[attrName] && attributes[attrName].valueKeys && attributes[attrName].valueKeys[key]) {
412
+ if (!attributes[attrName])
413
+ attributes[attrName] = { originalValue: attrValue }
414
+ else if (!attributes[attrName].originalValue)
415
+ attributes[attrName].originalValue = attrValue
416
+ if (!attributes[attrName].valueKeys)
417
+ attributes[attrName].valueKeys = { [key]: value }
418
+ else
419
+ attributes[attrName].valueKeys[key] = value;
420
+
421
+ newValue = attributes[attrName].originalValue
422
+ for (let valueKey of Object.keys(attributes[attrName].valueKeys)) {
423
+ const valueKeyRegex = new RegExp(valueKey, "g");
424
+ newValue = newValue.replace(valueKeyRegex, value);
425
+ }
426
+ setAttr = true;
427
+ }
428
+ // if (attrName.includes(currentValue) || attributes[attrName] && attributes[attrName].nameKeys && attributes[attrName].nameKeys[key]){
429
+ // if (!attributes[attrName])
430
+ // attributes[attrName] = { originalName: attrName }
431
+ // else if (!attributes[attrName].originalName)
432
+ // attributes[attrName].originalName = attrName
433
+
434
+ // if (!attributes[attrName].nameKeys)
435
+ // attributes[attrName].nameKeys = {[key]: value}
436
+
437
+ // newName = attributes[attrName].originalName
438
+ // for (let nameKey of Object.keys(attributes[attrName].nameKeys)) {
439
+ // let r
440
+ // if (attrName === nameKey)
441
+ // r = nameKey
442
+ // else
443
+ // r = attributes[attrName].nameKeys[nameKey]
444
+
445
+ // const nameKeyRegex = new RegExp(r, "g");
446
+ // newName = newName.replace(nameKeyRegex, value);
447
+ // }
448
+
449
+ // attributes[attrName].nameKeys[key] = value;
450
+
451
+
452
+ // element.removeAttribute(attrName);
453
+ // setAttr = true;
454
+
455
+ // }
456
+ if (setAttr)
457
+ element.setAttribute(newName, newValue);
458
+ }
459
+ let html = element.innerHTML;
460
+ if (html.indexOf(currentValue) !== -1 || element.htmlKeys && element.htmlKeys[key]) {
461
+ if (!element.originalHtml)
462
+ element.originalHtml = html
463
+ if (!element.htmlKeys)
464
+ element.htmlKeys = { [key]: value }
465
+ else
466
+ element.htmlKeys[key] = value;
467
+
468
+ let newHTML = element.originalHtml
469
+ if (newHTML) {
470
+ for (let elementKey of Object.keys(element.htmlKeys)) {
471
+ const htmlKeyRegex = new RegExp(elementKey, "g");
472
+ newHTML = newHTML.replace(htmlKeyRegex, value);
473
+ }
474
+
475
+ element.innerHTML = newHTML;
476
+ }
477
+ }
478
+
479
479
  }
480
480
 
481
481
  CoCreateEvents.init();