Last active
January 16, 2022 16:32
-
-
Save vituchon/a34291cfe6a3ce46c57d8b049eac088a to your computer and use it in GitHub Desktop.
This file contains 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> | |
<head> | |
<style> | |
table, th, td { | |
border: 1px solid black; | |
border-collapse: collapse; | |
} | |
</style> | |
<script> | |
class TreeNode { | |
constructor(valor, parent) { | |
this.valor = valor; | |
this.descendants = []; | |
this.parent = parent; | |
} | |
agregarHijo(hijo){ | |
this.descendants.push(hijo); | |
} | |
agregarValorExtra(valorExtra){ | |
this.valorExtra = valorExtra; | |
} | |
sumarHijosProfundidadInfinita(){ | |
let sumatoria = 0; | |
if(this.descendants.length === 0){ | |
return 1; | |
} else { | |
for (const descendant of this.descendants) { | |
sumatoria += descendant.sumarHijosProfundidadInfinita(); | |
} | |
} | |
return sumatoria; | |
} | |
dameElementos(){ | |
if(this.descendants.length === 0){ | |
const medico = document.createElement('td'); | |
medico.textContent = this.valor; | |
const medicoValor = document.createElement('td'); | |
medicoValor.textContent = this.valorExtra; | |
return [medico, medicoValor]; | |
} else { | |
let aux = this.descendants.map(descendant => descendant.dameElementos()); | |
if(Array.isArray(aux[0][0])){ | |
let aux2 = []; | |
for (const trs of aux) { | |
aux2.push(...trs); | |
} | |
aux = aux2; | |
} | |
const tdValor = document.createElement('td'); | |
tdValor.textContent = this.valor; | |
tdValor.rowSpan = this.sumarHijosProfundidadInfinita(); | |
tdValor.width = '25%'; | |
aux[0].unshift(tdValor); | |
return aux; | |
} | |
} | |
} | |
function llenarColumnas(table, columnas){ | |
const tr1 = document.createElement('tr'); | |
const columnsKeys = Object.keys(columnas); | |
columnsKeys.forEach(columnKey => { | |
const column = columnas[columnKey]; | |
const columnaElemento = document.createElement('th') ; | |
columnaElemento.textContent = column.label; | |
columnaElemento.width = column.size; | |
tr1.appendChild(columnaElemento); | |
}); | |
table.width = '100%'; | |
table.appendChild(tr1); | |
} | |
function dameLaData(){ | |
return { | |
'2018': { | |
'OSDE': { | |
'medico1': 1, | |
'medico2': 2 | |
}, | |
'UP': { | |
'medico1': 1, | |
'medico2': 2 | |
} | |
}, | |
'2019': { | |
'OSDE': { | |
'medico1': 1, | |
'medico2': 2 | |
}, | |
'UP': { | |
'medico1': 1, | |
'medico2': 2 | |
} | |
} | |
}; | |
} | |
function dameLaData2(){ | |
return { | |
'2018': { | |
'OSDE': { | |
'B2': { | |
'Juan Gonzalez': 1, | |
'María López': 2 | |
}, | |
'C5': { | |
'Pedro Picapiedras': 3, | |
'Sofía Fraga': 4 | |
} | |
}, | |
'UP': { | |
'B2': { | |
'Juan Gonzalez': 5, | |
'María López': 6 | |
}, | |
'C5': { | |
'Pedro Picapiedras': 7, | |
'Sofía Fraga': 8 | |
} | |
} | |
}, | |
'2019': { | |
'OSDE': { | |
'B2': { | |
'Juan Gonzalez': 9, | |
'María López': 10 | |
}, | |
'C5': { | |
'Pedro Picapiedras': 11, | |
'Sofía Fraga': 12 | |
} | |
}, | |
'UP': { | |
'B2': { | |
'Juan Gonzalez': 13, | |
'María López': 14 | |
}, | |
'C5': { | |
'Pedro Picapiedras': 15, | |
'Sofía Fraga': 16 | |
} | |
} | |
} | |
}; | |
} | |
function isObject(object){ | |
return typeof object === 'object' && | |
!Array.isArray(object) && | |
object !== null; | |
} | |
function armarNodo(data, nodo){ | |
const keys = Object.keys(data); | |
keys.forEach(key => { | |
const nodoKey = new TreeNode(key, nodo); | |
const dataKey = data[key]; | |
if(isObject(dataKey)){ | |
armarNodo(dataKey, nodoKey); | |
} else { | |
nodoKey.agregarValorExtra(data[key]); | |
} | |
nodo.agregarHijo(nodoKey); | |
}); | |
} | |
function dameTrs(nodo){ | |
const futurosTrs = nodo.dameElementos(); | |
const trs = futurosTrs.map(tds => { | |
const tr = document.createElement('tr'); | |
tds.forEach(td => { | |
tr.appendChild(td); | |
}); | |
return tr; | |
}); | |
return trs; | |
} | |
function buildHTMLTable() { | |
const columnas = { | |
anio: {label: 'Anio', size: '25%'}, | |
obraSocial: {label: 'Obra social', size: '25%'}, | |
doctor: {label: 'Doctor', size: '25%'}, | |
valor: {label: 'Valor', size: '25%'} | |
}; | |
const tabla = document.createElement('table'); | |
const columnas2 = { | |
anio: {label: 'Anio', size: '20%'}, | |
obraSocial: {label: 'Obra social', size: '20%'}, | |
consultorio: {label: 'Consultorio', size: '20%'}, | |
doctor: {label: 'Doctor', size: '20%'}, | |
valor: {label: 'Valor', size: '20%'} | |
}; | |
const tabla2 = document.createElement('table'); | |
llenarColumnas(tabla, columnas); | |
llenarColumnas(tabla2, columnas2); | |
const data = dameLaData(); | |
const arbol = new TreeNode('', null); | |
armarNodo(data, arbol); | |
const trs = arbol.descendants.flatMap(descendant => dameTrs(descendant)); | |
trs.forEach(tr => tabla.appendChild(tr)); | |
const mappedResults = document.getElementById('mapped-results'); | |
mappedResults.parentNode.replaceChild(tabla, mappedResults); | |
const data2 = dameLaData2(); | |
const arbol2 = new TreeNode('', null); | |
armarNodo(data2, arbol2); | |
const trs2 = arbol2.descendants.flatMap(descendant => dameTrs(descendant)); | |
trs2.forEach(tr => tabla2.appendChild(tr)); | |
const mappedResults2 = document.getElementById('mapped-results2'); | |
mappedResults2.parentNode.replaceChild(tabla2, mappedResults2); | |
console.log("ÉXITO"); | |
} | |
</script> | |
</head> | |
<body> | |
<!-- IDEAL: | |
<table width="100%"> | |
<tr> | |
<th width="25%">Anio</th> | |
<th width="25%">Obra social</th> | |
<th width="25%">Doctor</th> | |
<th width="25%">Valor</th> | |
</tr> | |
<tr> | |
<td width="25%" rowspan="4">2018</td> | |
<td width="25%" rowspan="2">OSDE</td> | |
<td>medico1</td> | |
<td>1</td> | |
</tr> | |
<tr> | |
<td>medico2</td> | |
<td>2</td> | |
</tr> | |
<tr> | |
<td width="25%" rowspan="2">UP</td> | |
<td>medico1</td> | |
<td>1</td> | |
</tr> | |
<tr> | |
<td>medico2</td> | |
<td>2</td> | |
</tr> | |
<tr> | |
<td width="25%" rowspan="4">2019</td> | |
<td width="25%" rowspan="2">OSDE</td> | |
<td>medico1</td> | |
<td>1</td> | |
</tr> | |
<tr> | |
<td>medico2</td> | |
<td>2</td> | |
</tr> | |
<tr> | |
<td width="25%" rowspan="2">UP</td> | |
<td>medico1</td> | |
<td>1</td> | |
</tr> | |
<tr> | |
<td>medico2</td> | |
<td>2</td> | |
</tr> | |
</table> | |
PRODUCTO: --> | |
TABLA ORIGINAL: | |
<div id="mapped-results"> | |
</div> | |
<hr> | |
TABLA CON UNA COLUMNA MÁS: | |
<div id="mapped-results2"> | |
</div> | |
<button onclick="buildHTMLTable({})">Construir</button> | |
</body> | |
</html> |
This file contains 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> | |
<head> | |
<title>A solution for building HTML table from map data</title> | |
<style> | |
.result-cell { | |
padding: 5px; | |
border: 1px solid black; | |
} | |
</style> | |
<script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.min.js"></script> | |
<script> | |
"use strict"; | |
// do note that html element manipulation is done via jquery routines, so it is need to include a jquery library in this script. | |
// pasting translated code from: https://www.typescriptlang.org/play?target=2&jsx=0#code/G4QwTgBAJAXCB2BPA3AWAFABdEAcCmEAUgIoCueYiEAvBAihhgGanwDGmAlgPbwRvdWmADJ4QwPAGcAFAFsQOCDDpIAlBADeGCDt2hIAoTQgAGNOl26m3SNIHxJmCAGs8VTn3k51Wi5d32jhCgADbkxl4A2q6IALra-jqBTpySALIKxtj43EzSoeTq1LQA5NwARgBWeBwlCYmcTBDSqRnemvWJ-ILwTgDUtIa9ouJS+SBheKqdlgC+EHghkgS+XQE9-bQAjDO6s7v7fpZgeJikYHxDmJ2HnSzsXLwQ5aScIQAmABIAKmnC3yByiE8HIFMp6D5dskIJhAcDjFBpCUADywoF4AB8JWmRysNma0JiEA8EC8kNxlmhYG4AHdJMYXm93gBBeAsnD4NkAJVpMhiABpSQpom5YoLESjMGAsaocWs0cCAHQKTnvaTUumqcyJQ6JaEKvCstgAC3xtAl704wAAxF58O8ALQnSSkEKYSTY7X+A1G01gRV4WQ4bDSVTKjl4NnSA1am6MXH3Dg8PiMj6s9mqnl0uznE69ADSbmUjjAHgA5oKvEoVIhBWxc5HMFnlCRyJRyXreEFgaNJABhDbGK4jCQyMm7RrNHujgdGYq0Ew+CAAemXQsUqTowQm5EFxpA9Pg3AgACJp1ITxB8ThqThJLskl2nCBMFK+4sQgikaj3jLle93j7EIDxkEpnVdTAHTYD9sUVTA8AAD0wHMwDzTBC0QOUumheBSFkd8Qk-c1v0wX9YJAACgJApFwLdKCYLDeCkOkZF6AxccKQCBteizcNVWkF83w-flcPwj8sMSE4zguCBInrVDGyzeJOPmRZlg6TjHwcJxoMIr9JTIsMKMA4DJFA2jIN0kJYKY5D5LQjCjNfMBpBPDVJBwBAT0Fc9+w2WNNP4bim1pPjIzVKyJP8KleRbMgKEQSJYmMJKvUSaxbEJNxiU8BQOzWbptIgF1yizelaFTFk2WZCNuV5aQBSiGIxXsxTaQCgqIHcxUcFISRjWkRUhpKsqor1YKs301FpWxB8IF1LopPOPh3LSvYbiAA | |
// functionallity is archieved by invoking `buildHTMLTable(map)` where `map` is a map that follow the given criteria (see * at bootom) | |
function countLeaves(map) { | |
var count = 0; | |
for (const key in map) { | |
const value = map[key]; | |
const isMap = typeof (value) == 'object'; | |
if (isMap) { | |
count += countLeaves(value); | |
} | |
else { | |
count += 1; | |
} | |
} | |
return count; | |
} | |
function buildHTMLTable(map) { | |
const table = $('<table>'); | |
for (const key in map) { | |
const rows = buildAndAppendRows(key, map[key], $('<tr>')); | |
table.append(rows); | |
} | |
const tableAnchor = $('div#mapped-results'); | |
tableAnchor.empty().append(table); | |
} | |
function buildAndAppendRows(currentKey, map, currentRow) { | |
const leavesCount = countLeaves(map); | |
if (leavesCount === 0) { // this means that "map" is a value (actually a leaf node!), has no "leaves" or props | |
const attrCell = $('<td>').addClass('result-cell').text(currentKey); | |
const numCell = $('<td>').addClass('result-cell').text(map); | |
currentRow.append(attrCell, numCell); | |
return [currentRow]; | |
} | |
else { | |
const cell = $('<td>').addClass('result-cell').text(currentKey).attr("rowspan", leavesCount); | |
currentRow.append(cell); | |
const rows = []; | |
for (const key in map) { | |
const subRows = buildAndAppendRows(key, map[key], currentRow); | |
rows.push(...subRows); | |
currentRow = $('<tr>'); | |
} | |
return rows; | |
} | |
} | |
var example_map = { | |
'2020': { | |
'Downtown': { | |
'person1': 1, | |
'person2': 2 | |
}, | |
'Uptown': { | |
'person1': 3, | |
'person2': 4 | |
} | |
}, | |
'2021': { | |
'Downtown': { | |
'person1': 5, | |
'person2': 6 | |
}, | |
'Uptown': { | |
'person1': 7, | |
'person2': 8 | |
} | |
} | |
} | |
</script> | |
</head> | |
<body> | |
<div id="mapped-results"> | |
</div> | |
<hr> | |
<button onclick="buildHTMLTable(example_map)">Construir</button> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Build HTML Table from JSON object (Facu Solution) comes from https://github.com/Kvothe838