HTML templates
<template id="keyValue">
<div class="csle-property">
<span class="csle-key"></span>:
<span class="csle-value"></span>
</div>
</template>
<template id="folder">
<summary>
<div>
<div class="csle-key"></div>:
<div class="csle-preview"></div>
</div>
</summary>
</template>
JavaScript code:
/**
* Shows all the object's properties with a depth of 1
* @params {Object} object, its first level properties are shown
* {HTMLElement} parent the element in which are displayed the properties
* @return {undefined}
*/
const showObject = (object, parent = document.body) => {
const template = {
keyValue: document.querySelector('template#keyValue'),
folder: document.querySelector('template#folder')
}
Object.entries(object).forEach(([key, value]) => {
const objectClass = (value && value.constructor) ? value.constructor : undefined;
const isContainer = (objectClass == Object) || (objectClass == Array);
if (isContainer) { // !better naming for (objects, arrays, maps, sets)?
const element = document.importNode(template.folder.content, true);
const children = {
key: element.querySelector('.csle-key'),
preview: element.querySelector('.csle-preview')
}
children.key.textContent = key;
children.preview.classList.add('csle-' + objectClass.name);
// show four properties maximum per preview
Object.entries(value).some(([k, v], i) => {
type = (v && v.constructor) ? v.constructor : undefined;
const keyValue = document.importNode(template.keyValue.content, true);
const keyValueElement = {
key: keyValue.querySelector('.csle-key'),
value: keyValue.querySelector('.csle-value')
}
// all types need different formatting
switch (type) {
case Object:
keyValueElement.value.textContent = `{...}`;
break;
case Array:
keyValueElement.value.textContent = `Array(${v.length})`;
break
default:
keyValueElement.value.textContent = `${v}`;
}
keyValueElement.key.textContent = k;
keyValueElement.value.setAttribute('class', 'csle-' + typeof v);
children.preview.appendChild(keyValue);
return i == 4;
});
const wrapper = document.createElement('details'); // !couldn't add event listener on <details>
wrapper.appendChild(element)
wrapper.addEventListener('toggle', () => {
showObject(value, wrapper)
}, { once: true });
parent.appendChild(wrapper);
} else {
const element = document.importNode(template.keyValue.content, true);
const children = {
key: element.querySelector('.csle-key'),
value: element.querySelector('.csle-value')
}
children.key.textContent = key;
children.value.textContent = value; // !undefined and null won't be parsed
children.value.setAttribute('class', 'csle-' + typeof value);
parent.appendChild(element);
}
});
};
Full code:
HTML templates
<template id="keyValue">
<div class="csle-property">
<span class="csle-key"></span>:
<span class="csle-value"></span>
</div>
</template>
<template id="folder">
<summary>
<div>
<div class="csle-key"></div>:
<div class="csle-preview"></div>
</div>
</summary>
</template>
JavaScript codeIssues:
/**
* Shows all the object's properties with a depth of 1
* @params {Object} object, its first level properties are shown
* {HTMLElement} parent the element in which are displayed the properties
* @return {undefined}
*/
const showObject = (object, parent = document.body) => {
const template = {
keyValue: document.querySelector('template#keyValue'),
folder: document.querySelector('template#folder')
}
Object.entries(object).forEach(([key, value]) => {
const objectClass = (value && value.constructor) ? value.constructor : undefined;
const isContainer = (objectClass == Object) || (objectClass == Array);
if (isContainer) { // !better naming for (objects, arrays, maps, sets)?
const element = document.importNode(template.folder.content, true);
const children = {
key: element.querySelector('.csle-key'),
preview: element.querySelector('.csle-preview')
}
children.key.textContent = key;
children.preview.classList.add('csle-' + objectClass.name);
// show four properties maximum per preview
Object.entries(value).some(([k, v], i) => {
type = (v && v.constructor) ? v.constructor : undefined;
const keyValue = document.importNode(template.keyValue.content, true);
const keyValueElement = {
key: keyValue.querySelector('.csle-key'),
value: keyValue.querySelector('.csle-value')
}
// all types need different formatting
switch (type) {
case Object:
keyValueElement.value.textContent = `{...}`;
break;
case Array:
keyValueElement.value.textContent = `Array(${v.length})`;
break
default:
keyValueElement.value.textContent = `${v}`;
}
keyValueElement.key.textContent = k;
keyValueElement.value.setAttribute('class', 'csle-' + typeof v);
children.preview.appendChild(keyValue);
return i == 4;
});
const wrapper = document.createElement('details'); // !couldn't add event listener on <details>
wrapper.appendChild(element)
wrapper.addEventListener('toggle', () => {
showObject(value, wrapper)
}, { once: true });
parent.appendChild(wrapper);
} else {
const element = document.importNode(template.keyValue.content, true);
const children = {
key: element.querySelector('.csle-key'),
value: element.querySelector('.csle-value')
}
children.key.textContent = key;
children.value.textContent = value; // !undefined and null won't be parsed
children.value.setAttribute('class', 'csle-' + typeof value);
parent.appendChild(element);
}
});
};
I have some issues:
by adding code I feel like I havemy function too much code in a single function. I am unsure I'm using ES6 properly..
showObjectseems to big.some of the naming bother me: Unsure if I'm using ECMAScript 6 properly
some of the variable names bother me (
element,childrenPreview,isContainer) as they aren't very clear to me.I can't attach an event listener on the imported template
<details>because it is aDocumentFragment. To fix that I had to (line 62of the snippet):
Overall the first two points are the most important at the moment.
I'm looking forward to reading your comments.I'm looking forward to reading your comments.
