Last active
January 22, 2025 02:35
-
-
Save fabioyamate/3f31b5e97bf48ea3697fe5b005504762 to your computer and use it in GitHub Desktop.
A way to build a HTML rendering for JSON data.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Advanced JSON Viewer</title> | |
<style> | |
#dropzone { | |
width: 100%; | |
height: 150px; | |
border: 2px dashed #ccc; | |
display: flex; | |
align-items: center; | |
justify-content: center; | |
color: #888; | |
margin-bottom: 20px; | |
} | |
#dropzone.dragover { | |
border-color: #666; | |
color: #333; | |
} | |
.collapsible { | |
margin-bottom: 10px; | |
} | |
.collapsible-header { | |
background-color: #f0f0f0; | |
padding: 10px; | |
cursor: pointer; | |
font-weight: bold; | |
border: 1px solid #ccc; | |
} | |
.collapsible-content { | |
border: 1px solid #ccc; | |
border-top: none; | |
padding: 10px; | |
display: none; | |
} | |
.collapsible-content.show { | |
display: block; | |
} | |
.key { | |
font-weight: bold; | |
} | |
ul { | |
padding-left: 20px; | |
} | |
li { | |
margin-bottom: 5px; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="dropzone">Drag and drop a JSON file here</div> | |
<div id="output"></div> | |
<!-- Handlebars Template --> | |
<script id="template" type="text/x-handlebars-template"> | |
<h1>{{title}}</h1> | |
<p>{{content}}</p> | |
<div class="collapsible"> | |
<div class="collapsible-header">Items</div> | |
<div class="collapsible-content"> | |
<ul> | |
{{#each items}} | |
<li> | |
{{#if (isObject this)}} | |
<ul> | |
{{#each this}} | |
<li><span class="key">{{@key}}:</span> {{renderValue this}}</li> | |
{{/each}} | |
</ul> | |
{{else}} | |
{{renderValue this}} | |
{{/if}} | |
</li> | |
{{/each}} | |
</ul> | |
</div> | |
</div> | |
<div class="collapsible"> | |
<div class="collapsible-header">Details</div> | |
<div class="collapsible-content"> | |
{{renderValue details}} | |
</div> | |
</div> | |
</script> | |
<!-- Handlebars.js Library --> | |
<script src="https://cdn.jsdelivr.net/npm/handlebars@latest/dist/handlebars.min.js"></script> | |
<script> | |
// Register Handlebars Helpers | |
Handlebars.registerHelper('isObject', function (value) { | |
return typeof value === 'object' && !Array.isArray(value) && value !== null; | |
}); | |
Handlebars.registerHelper('renderValue', function (value) { | |
if (Array.isArray(value)) { | |
return new Handlebars.SafeString('<ul>' + | |
value.map(item => `<li>${Handlebars.helpers.renderValue(item)}</li>`).join('') + | |
'</ul>'); | |
} else if (typeof value === 'object' && value !== null) { | |
return new Handlebars.SafeString('<ul>' + | |
Object.entries(value).map(([key, val]) => | |
`<li><span class="key">${key}:</span> ${Handlebars.helpers.renderValue(val)}</li>` | |
).join('') + | |
'</ul>'); | |
} else if (typeof value === 'boolean') { | |
return value ? 'True' : 'False'; | |
} else if (typeof value === 'number') { | |
return value.toString(); | |
} else if (value === null) { | |
return 'Null'; | |
} else { | |
return value; | |
} | |
}); | |
const dropzone = document.getElementById('dropzone'); | |
const output = document.getElementById('output'); | |
// Compile Handlebars template | |
const templateSource = document.getElementById('template').innerHTML; | |
const template = Handlebars.compile(templateSource); | |
// Handle drag-and-drop events | |
dropzone.addEventListener('dragover', (e) => { | |
e.preventDefault(); | |
dropzone.classList.add('dragover'); | |
}); | |
dropzone.addEventListener('dragleave', () => { | |
dropzone.classList.remove('dragover'); | |
}); | |
dropzone.addEventListener('drop', (e) => { | |
e.preventDefault(); | |
dropzone.classList.remove('dragover'); | |
const file = e.dataTransfer.files[0]; | |
if (file && file.type === "application/json") { | |
const reader = new FileReader(); | |
reader.onload = (event) => { | |
try { | |
const data = JSON.parse(event.target.result); | |
renderContent(data); | |
} catch (err) { | |
alert("Invalid JSON file."); | |
} | |
}; | |
reader.readAsText(file); | |
} else { | |
alert("Please drop a valid JSON file."); | |
} | |
}); | |
// Function to render JSON content using Handlebars | |
function renderContent(data) { | |
const html = template(data); | |
output.innerHTML = html; | |
attachCollapsibleHandlers(); | |
} | |
// Attach click event to collapsible headers | |
function attachCollapsibleHandlers() { | |
const headers = document.querySelectorAll('.collapsible-header'); | |
headers.forEach(header => { | |
header.addEventListener('click', () => { | |
const content = header.nextElementSibling; | |
content.classList.toggle('show'); | |
}); | |
}); | |
} | |
</script> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"title": "My Dynamic Page", | |
"content": "This is content loaded from a JSON file.", | |
"items": ["Item 1", "Item 2", "Item 3"] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment