@cocreate/render 1.9.2 → 1.12.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,35 @@
1
+ # [1.12.0](https://github.com/CoCreate-app/CoCreate-render/compare/v1.11.0...v1.12.0) (2022-07-29)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * replace attribute value if new and old value are not equal ([3dc25d8](https://github.com/CoCreate-app/CoCreate-render/commit/3dc25d884510a6ad14455b232d9068eb5e1302a8))
7
+
8
+
9
+ ### Features
10
+
11
+ * if oldValues same as new value will not update text, html or attributes ([9cfe3f0](https://github.com/CoCreate-app/CoCreate-render/commit/9cfe3f017e706a5a7211449c294158d60fa2098c))
12
+
13
+ # [1.11.0](https://github.com/CoCreate-app/CoCreate-render/compare/v1.10.0...v1.11.0) (2022-07-25)
14
+
15
+
16
+ ### Bug Fixes
17
+
18
+ * if templateId setAttribute ([41e30b3](https://github.com/CoCreate-app/CoCreate-render/commit/41e30b3a748aa8900d9f9397584f14052d637197))
19
+
20
+
21
+ ### Features
22
+
23
+ * getValueFromObject supports deeply nested array and objects ([db7fefd](https://github.com/CoCreate-app/CoCreate-render/commit/db7fefd81a908ba6f68dbf4c43d62639aa73e3f8))
24
+ * observe new elements with atrribute render, if elements detected replace placholders with values ([90d7d98](https://github.com/CoCreate-app/CoCreate-render/commit/90d7d982eedf83b194cfae0704d06e110914ca52))
25
+
26
+ # [1.10.0](https://github.com/CoCreate-app/CoCreate-render/compare/v1.9.2...v1.10.0) (2022-07-14)
27
+
28
+
29
+ ### Features
30
+
31
+ * renderMap function to apply map containing placeholder to node object in order to render new values ([7afffa0](https://github.com/CoCreate-app/CoCreate-render/commit/7afffa07b2cc1dd562e96d1ee558433d3f6d043a))
32
+
1
33
  ## [1.9.2](https://github.com/CoCreate-app/CoCreate-render/compare/v1.9.1...v1.9.2) (2022-07-10)
2
34
 
3
35
 
@@ -0,0 +1,42 @@
1
+ <html>
2
+ <head>
3
+ <title>Render | CoCreateJS</title>
4
+
5
+ <!-- CoCreate Favicon -->
6
+ <link rel="icon" href="https://cdn.cocreate.app/favicon.ico" type="image/ico" sizes="16x16">
7
+ </head>
8
+ <style>
9
+ .template{display:none}
10
+ </style>
11
+ <body>
12
+
13
+ <body>
14
+
15
+ <div class="template" template_id="abc1">
16
+ <h3>{{collection}}</h3>
17
+ <h3>{{data._id}}</h3>
18
+ </div>
19
+
20
+ <pre>
21
+ <h1>Paste in your browser console</h1>
22
+
23
+ /** Example **/
24
+ CoCreate.render.data({
25
+ selector: '[template_id=abc1]',
26
+ data: {
27
+ collection: 'dededede',
28
+ data: {
29
+ _id : '123kijfhgfkel45',
30
+ current_org: ['test1', 'test2', 'test31', 'test3'],
31
+ current: [{name: 'test1w'}, {name: 'test2'}, {name: 'test31'}, {name: 'test3'}]
32
+ }
33
+ }
34
+
35
+ })
36
+
37
+ </pre>
38
+
39
+ <!-- CoCreate JS CDN -->
40
+ <script src="../../../CoCreateJS/dist/CoCreate.js" ></script>
41
+ </body>
42
+ </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cocreate/render",
3
- "version": "1.9.2",
3
+ "version": "1.12.0",
4
4
  "description": "A simple render component in vanilla javascript. Easily configured using HTML5 attributes and/or JavaScript API.",
5
5
  "keywords": [
6
6
  "render",
package/src/index.js CHANGED
@@ -1,17 +1,26 @@
1
1
  /*globals CustomEvent*/
2
2
  import action from '@cocreate/actions';
3
+ import observer from '@cocreate/observer';
4
+ import uuid from '@cocreate/uuid';
3
5
  import { queryDocumentSelector } from '@cocreate/utils';
4
6
  // import { getValue } from '../../CoCreate-elements/src/getValue';
5
7
  // import api from '@cocreate/api';
6
8
 
7
9
  const CoCreateRender = {
8
-
10
+ // Can be called from crud getObjectValueByPath
9
11
  __getValueFromObject : function(json, path) {
10
12
  try {
11
13
  if(typeof json == 'undefined' || !path)
12
14
  return false;
13
15
  if (path.indexOf('.') == -1 && path.includes('collection'))
14
16
  json = this.dataOriginal
17
+ if (/\[([0-9]*)\]/g.test(path)) {
18
+ path = path.replace(/\[/g, '.');
19
+ if (path.endsWith(']'))
20
+ path = path.slice(0, -1)
21
+ path = path.replace(/\]./g, '.');
22
+ path = path.replace(/\]/g, '.');
23
+ }
15
24
  let jsonData = json, subpath = path.split('.');
16
25
 
17
26
  for (let i = 0; i < subpath.length; i++) {
@@ -52,7 +61,7 @@ const CoCreateRender = {
52
61
  }
53
62
  },
54
63
 
55
- __replaceValue: function(data, inputValue, renderKey) {
64
+ __replaceValue: function(data, inputValue, renderKey, valueType) {
56
65
  let isPass = false;
57
66
  let self = this;
58
67
  let resultValue = null;
@@ -103,32 +112,33 @@ const CoCreateRender = {
103
112
  },
104
113
 
105
114
  render: function(template, data) {
106
- let type = template.getAttribute('render-array') || "data";
107
- const renderKey = template.getAttribute('render-key') || type;
108
115
  const self = this;
109
-
116
+ let type = '';
110
117
  let arrayData = data;
111
118
 
112
119
  const isRenderObject = template.hasAttribute('render-object');
113
120
  if (isRenderObject){
114
- const renderObject = template.getAttribute('render-object');
115
- type = renderObject || 'data'
121
+ const renderObject = template.getAttribute('render-object');
122
+ type = renderObject || ''
116
123
  }
117
124
 
118
125
  const isRenderArray = template.hasAttribute('render-array');
119
126
  if (isRenderArray){
120
- const renderArray = template.getAttribute('render-array');
127
+ var renderArray = template.getAttribute('render-array');
121
128
  if (renderArray)
122
129
  arrayData = data[renderArray];
123
- type = renderArray || 'data';
130
+ type = renderArray || '';
124
131
  }
132
+
133
+ let renderKey = template.getAttribute('render-key') || type;
134
+
125
135
  if (isRenderObject && type) {
126
- let r_data = self.isRenderObject(arrayData[type], renderKey)
127
- for (let sdata of r_data) {
136
+ let Data = self.__getValueFromObject(arrayData, type);
137
+ let array = self.isRenderObject(Data, renderKey)
138
+ for (let item of array) {
128
139
  let cloneEl = this.cloneEl(template);
129
- cloneEl.classList.add('clone_' + type);
130
- self.setValue([cloneEl], sdata, renderKey);
131
- template.insertAdjacentHTML('beforebegin', cloneEl.outerHTML);
140
+ self.setValue([cloneEl], item, renderArray, renderKey);
141
+ template.insertAdjacentElement('beforebegin', cloneEl);
132
142
  }
133
143
  } else {
134
144
 
@@ -137,18 +147,16 @@ const CoCreateRender = {
137
147
 
138
148
  if (!arrayData) {
139
149
  let cloneEl = this.cloneEl(template);
140
- cloneEl.classList.add('cloned');
141
- self.setValue([cloneEl], data, renderKey);
142
- template.insertAdjacentHTML('beforebegin', cloneEl.outerHTML);
150
+ self.setValue([cloneEl], data, renderArray, renderKey);
151
+ template.insertAdjacentElement('beforebegin', cloneEl);
143
152
  }
144
153
 
145
154
  if(type && Array.isArray(arrayData)) {
146
155
  arrayData.forEach((item) => {
147
156
  let cloneEl = this.cloneEl(template);
148
- cloneEl.classList.add('clone_' + type);
149
- let r_data = self.__createObject(item, renderKey);
150
- self.setValue([cloneEl], r_data, renderKey);
151
- template.insertAdjacentHTML('beforebegin', cloneEl.outerHTML);
157
+ let object = self.__createObject(item, renderKey);
158
+ self.setValue([cloneEl], object, renderArray, renderKey);
159
+ template.insertAdjacentElement('beforebegin', cloneEl);
152
160
  });
153
161
  }
154
162
  }
@@ -156,6 +164,8 @@ const CoCreateRender = {
156
164
 
157
165
  isRenderObject: function(data, renderKey) {
158
166
  let array = []
167
+ if (!data)
168
+ return array
159
169
  for (const [key, value] of Object.entries(data)) {
160
170
  let type = 'string';
161
171
  if (typeof(value) == "object")
@@ -170,68 +180,167 @@ const CoCreateRender = {
170
180
 
171
181
  cloneEl: function(template) {
172
182
  let cloneEl = template.cloneNode(true);
173
- cloneEl.classList.remove('template');
183
+
174
184
  let templateId = cloneEl.getAttribute('template_id');
185
+ if (templateId)
186
+ cloneEl.setAttribute('templateId', templateId);
187
+
175
188
  cloneEl.removeAttribute('template_id');
176
- cloneEl.setAttribute('templateId', templateId);
189
+ cloneEl.setAttribute('render-clone', '');
190
+ cloneEl.classList.remove('template');
191
+
192
+ if (template.dataOriginal)
193
+ cloneEl.dataOriginal = template.dataOriginal
194
+
177
195
  return cloneEl;
178
196
  },
179
197
 
180
- setValue: function(els, data, renderKey){
198
+ setValue: function(els, data, renderArray, renderKey){
181
199
  if (!data) return;
182
200
  const that = this;
183
201
  Array.from(els).forEach(el => {
202
+ let updateData;
203
+
184
204
  if (el.nodeType == 1) {
205
+ if (el.hasAttribute('render-clone')) {
206
+ el.renderData = {...data}
207
+ }
208
+ if (el.renderMap) {
209
+ let placeholder = el.renderMap.get(el)
210
+ if (placeholder){
211
+ let valueType = el.getAttribute('value-type')
212
+ renderKey = placeholder.renderKey
213
+ renderArray = placeholder.renderArray
214
+ if (renderArray)
215
+ updateData = data[renderArray][0]
216
+ if (renderKey)
217
+ updateData = {[renderKey]: updateData}
218
+ let textContent = placeholder.placeholder
219
+ let text = that.__replaceValue(updateData, textContent, renderKey, valueType);
220
+ if (text && text != el.renderedValue)
221
+ el.innerHTML = placeholder.placeholder
222
+ }
223
+ }
224
+
185
225
  Array.from(el.attributes).forEach(attr=>{
186
226
  let attr_name = attr.name.toLowerCase();
187
227
  let attrValue = attr.value;
188
- attrValue = that.__replaceValue(data, attrValue, renderKey);
228
+
229
+ let placeholder
230
+ if (attr.renderMap)
231
+ placeholder = attr.renderMap.get(attr)
232
+ else
233
+ that.renderMap(attr, attr.value, renderArray, renderKey)
234
+
235
+ if(placeholder){
236
+ let updateData = data;
237
+ // let oldValue = attrValue
238
+ let temp = placeholder.placeholder;
239
+ renderKey = placeholder.renderKey
240
+ renderArray = placeholder.renderArray
241
+ if (renderArray)
242
+ updateData = data[renderArray][0]
243
+ if (renderKey)
244
+ updateData = {[renderKey]: updateData}
245
+
246
+ attrValue = that.__replaceValue(updateData, temp, renderKey);
247
+ if (attrValue == attr.value)
248
+ attrValue = undefined
249
+ }
250
+ else
251
+ attrValue = that.__replaceValue(data, attrValue, renderKey);
189
252
 
253
+ // ToDo support attibute name replace if has {{}}
254
+ // attr_name = that.__replaceValue(data, attr_name, renderKey);
255
+
190
256
  if (attrValue || attrValue == "") {
191
257
  el.setAttribute(attr_name, attrValue);
192
258
  }
193
259
  });
194
260
 
195
- if(el.childNodes.length > 0) {
196
- that.setValue(el.childNodes, data, renderKey);
261
+ if(el.childNodes.length > 0) {
262
+ that.setValue(el.childNodes, updateData || data, renderArray, renderKey);
197
263
  }
198
264
  if (el.classList.contains('template') && !el.hasAttribute('template_id')) {
199
265
  that.render(el, data);
200
266
  }
201
267
  }
202
-
268
+
203
269
  if (el.nodeType == 3) {
204
270
  let valueType = el.parentElement.getAttribute('value-type')
205
- let textContent = el.textContent;
206
- let text = that.__replaceValue(data, textContent, renderKey);
271
+
272
+ let textContent, placeholder, text;
273
+ if (el.renderMap)
274
+ placeholder = el.renderMap.get(el)
275
+ if (placeholder) {
276
+ let updateData = data;
277
+ textContent = placeholder.placeholder
278
+ renderKey = placeholder.renderKey
279
+ renderArray = placeholder.renderArray
280
+ if (renderArray)
281
+ updateData = data[renderArray][0]
282
+ if (renderKey)
283
+ updateData = {[renderKey]: updateData}
284
+ text = that.__replaceValue(updateData, textContent, renderKey, valueType);
285
+ }
286
+ if (!placeholder && !text) {
287
+ textContent = el.textContent;
288
+ that.renderMap(el, textContent, renderArray, renderKey)
289
+ text = that.__replaceValue(data, textContent, renderKey, valueType);
290
+ }
291
+
207
292
  if (text || text == "") {
208
- if (valueType == 'text' || valueType == 'string'){
209
- el.textContent = text;
210
- } else {
211
- const newNode = document.createElement('div');
212
- newNode.innerHTML = text;
213
- el.replaceWith(...newNode.childNodes)
293
+ if (text != el.renderedValue) {
294
+ el.renderedValue = text
295
+ if (valueType == 'text' || valueType == 'string'){
296
+ el.renderedValue = text
297
+ el.textContent = text;
298
+ } else {
299
+ const newNode = document.createElement('div');
300
+ newNode.innerHTML = text;
301
+ let parentElement = el.parentElement
302
+ parentElement.renderedValue = text
303
+ if (!parentElement.renderMap) {
304
+ that.renderMap(parentElement, textContent, renderArray, renderKey)
305
+ } else if (!parentElement['renderMap'].has(parentElement))
306
+ that.renderMap(parentElement, textContent, renderArray, renderKey)
307
+ el.replaceWith(...newNode.childNodes)
308
+ }
214
309
  }
215
310
  }
216
311
  }
217
-
218
312
  });
219
313
  },
314
+
315
+ renderMap: function(node, placeholder, renderArray, renderKey) {
316
+ if (!node.renderMap) {
317
+ node['renderMap'] = new Map();
318
+ }
319
+ if (placeholder && renderKey)
320
+ node['renderMap'].set(node, {placeholder, renderArray, renderKey})
321
+ },
220
322
 
221
323
  dataOriginal: {},
222
324
  data: function({selector, data, elements}) {
223
- this.dataOriginal = data;
325
+ this.dataOriginal = {...data};
326
+ delete this.dataOriginal.data
327
+
328
+ for (let element of elements)
329
+ element.dataOriginal = {...this.dataOriginal};
330
+
224
331
  if (selector) {
225
332
  let template = queryDocumentSelector(selector);
226
333
  if (!template) return;
334
+ template.dataOriginal = {...data}
227
335
  if (template.classList.contains('template')) {
228
336
  this.render(template, data);
229
337
  }
230
338
  else
231
339
  this.setValue([template], data);
232
340
  } else if (elements) {
233
- if (elements.length == 1 && elements[0].classList.contains('template'))
341
+ if (elements.length == 1 && elements[0].classList.contains('template')){
234
342
  this.render(elements[0], data);
343
+ }
235
344
  else
236
345
  this.setValue(elements, data);
237
346
  }
@@ -262,4 +371,79 @@ action.init({
262
371
  }
263
372
  });
264
373
 
374
+ observer.init({
375
+ name: 'render',
376
+ observe: ['addedNodes'],
377
+ target: '[render]',
378
+ callback: function(mutation) {
379
+ let element = mutation.target
380
+ element.removeAttribute('render')
381
+
382
+ let parentElement = element.parentElement
383
+ if (parentElement) {
384
+ let el = element
385
+ let parentKeys = [];
386
+ let renderData = new Map();
387
+ do {
388
+ let data;
389
+ el = el.parentElement
390
+ if (el) {
391
+ if (el.dataOriginal)
392
+ renderData.set(el.dataOriginal, '')
393
+ if (el.hasAttribute('render-clone'))
394
+ data = el.renderData
395
+ if (data)
396
+ renderData.set(data, '')
397
+
398
+ let parentKey = el.getAttribute('parentKey')
399
+ if(parentKey && parentKey != null) {
400
+ if (/^\d+$/.test(parentKey))
401
+ parentKey = `[${parentKey}]`
402
+ parentKeys.push(parentKey)
403
+ }
404
+ }
405
+ } while (el)
406
+
407
+ let renderKey = element.getAttribute('render-key')
408
+
409
+ let parentKey;
410
+ parentKey = parentElement.getAttribute('parentKey')
411
+ if(renderKey == '$auto' || parentKey || parentKeys) {
412
+ let template = element.outerHTML
413
+ if (renderKey) {
414
+ template = template.replace(/\$auto/g, uuid.generate(6));
415
+ }
416
+ if (parentKeys.length > 0) {
417
+ let string = ''
418
+ if (parentKeys.length == 1){
419
+ string = parentKeys[0]
420
+ }
421
+ else
422
+ string = parentKeys.reverse().join('.')
423
+ string = string.replace(/.\[/g, '[');
424
+ template = template.replace(/\$parents/g, string);
425
+ }
426
+ if (parentKey) {
427
+ template = template.replace(/\$parent/g, parentKey);
428
+ }
429
+
430
+ parentElement.innerHTML = template
431
+
432
+ }
433
+
434
+ element = parentElement.firstElementChild
435
+ let obj = {}
436
+ let array = Array.from(renderData.keys())
437
+ for (let data of array.reverse()){
438
+ obj = {...obj, ...data}
439
+ }
440
+
441
+ CoCreateRender.data({
442
+ elements: [element],
443
+ data: obj
444
+ });
445
+ }
446
+ }
447
+ });
448
+
265
449
  export default CoCreateRender;