<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"> | |
<html> | |
<head> | |
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> | |
<title>Responses</title> | |
</head> | |
<body> | |
<input type="file" id="file-upload" /> | |
<script type="module"> | |
function generateTable(title, rows) { | |
let buffer = []; | |
buffer.push(` | |
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8" /> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
<title>${title}</title> | |
<link | |
rel="stylesheet" | |
href="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.css" | |
/> | |
</head> | |
<body> | |
<div class="mdc-data-table"> | |
<div class="mdc-data-table__table-container"> | |
<table class="mdc-data-table__table" aria-label="${title}">`); | |
// Header | |
buffer.push(`<thead><tr class="mdc-data-table__header-row">`); | |
for (const key of Object.keys(rows[0])) { | |
buffer.push(` | |
<th | |
class="mdc-data-table__header-cell" | |
role="columnheader" | |
scope="col" | |
> | |
${key} | |
</th> | |
`); | |
} | |
buffer.push(`</tr></thead>`); | |
// Rows | |
buffer.push(`<tbody class="mdc-data-table__content">`); | |
for (let i = 0; i < rows.length; i++) { | |
const row = rows[i]; | |
buffer.push(`<tr class="mdc-data-table__row">`); | |
const keys = Object.keys(row); | |
for (let r = 0; r < keys.length; r++) { | |
const key = keys[r]; | |
const value = row[key]; | |
if (r === 0) { | |
buffer.push( | |
`<th class="mdc-data-table__cell" scope="row">${value}</th>` | |
); | |
} else { | |
buffer.push(`<td class="mdc-data-table__cell">${value}</td>`); | |
} | |
// else if (isNaN(value)) { | |
// buffer.push(`<td class="mdc-data-table__cell mdc-data-table__cell--numeric">${value}</td>`); | |
// } | |
} | |
buffer.push(`</tr>`); | |
} | |
buffer.push(`</tbody>`); | |
buffer.push('</table></div></div><script src="'); | |
buffer.push( | |
"https://unpkg.com/material-components-web@latest/dist/material-components-web.min.js" | |
); | |
buffer.push('"><'); | |
buffer.push("/script"); | |
buffer.push("></body"); | |
buffer.push("></html"); | |
buffer.push(">"); | |
return buffer.join("\n"); | |
} | |
const uploadBtn = document.querySelector("#file-upload"); | |
uploadBtn.addEventListener( | |
"change", | |
(e) => { | |
const files = e.target.files; | |
const file = files[0]; | |
const reader = new FileReader(); | |
reader.onload = (event) => { | |
parseResult(event.target.result); | |
}; | |
reader.readAsText(file); | |
}, | |
false | |
); | |
function parseResult(data) { | |
const result = CSVToArray(data); | |
console.log("file", result); | |
const header = result[0]; | |
const headerMap = {}; | |
for (let i = 0; i < header.length; i++) { | |
const label = header[i]; | |
headerMap[i] = label; | |
} | |
const rowsMap = []; | |
for (let r = 1; r < result.length; r++) { | |
const row = result[r]; | |
const _result = {}; | |
for (let c = 0; c < row.length; c++) { | |
const col = row[c]; | |
_result[header[c]] = row[c]; | |
} | |
rowsMap.push(_result); | |
} | |
download("results.html", generateTable("Material X", rowsMap)); | |
} | |
// ref: http://stackoverflow.com/a/1293163/2343 | |
// This will parse a delimited string into an array of | |
// arrays. The default delimiter is the comma, but this | |
// can be overriden in the second argument. | |
function CSVToArray(strData, strDelimiter) { | |
// Check to see if the delimiter is defined. If not, | |
// then default to comma. | |
strDelimiter = strDelimiter || ","; | |
// Create a regular expression to parse the CSV values. | |
var objPattern = new RegExp( | |
// Delimiters. | |
"(\\" + | |
strDelimiter + | |
"|\\r?\\n|\\r|^)" + | |
// Quoted fields. | |
'(?:"([^"]*(?:""[^"]*)*)"|' + | |
// Standard fields. | |
'([^"\\' + | |
strDelimiter + | |
"\\r\\n]*))", | |
"gi" | |
); | |
// Create an array to hold our data. Give the array | |
// a default empty first row. | |
var arrData = [[]]; | |
// Create an array to hold our individual pattern | |
// matching groups. | |
var arrMatches = null; | |
// Keep looping over the regular expression matches | |
// until we can no longer find a match. | |
while ((arrMatches = objPattern.exec(strData))) { | |
// Get the delimiter that was found. | |
var strMatchedDelimiter = arrMatches[1]; | |
// Check to see if the given delimiter has a length | |
// (is not the start of string) and if it matches | |
// field delimiter. If id does not, then we know | |
// that this delimiter is a row delimiter. | |
if ( | |
strMatchedDelimiter.length && | |
strMatchedDelimiter !== strDelimiter | |
) { | |
// Since we have reached a new row of data, | |
// add an empty row to our data array. | |
arrData.push([]); | |
} | |
var strMatchedValue; | |
// Now that we have our delimiter out of the way, | |
// let's check to see which kind of value we | |
// captured (quoted or unquoted). | |
if (arrMatches[2]) { | |
// We found a quoted value. When we capture | |
// this value, unescape any double quotes. | |
strMatchedValue = arrMatches[2].replace(new RegExp('""', "g"), '"'); | |
} else { | |
// We found a non-quoted value. | |
strMatchedValue = arrMatches[3]; | |
} | |
// Now that we have our value string, let's add | |
// it to the data array. | |
arrData[arrData.length - 1].push(strMatchedValue); | |
} | |
// Return the parsed data. | |
return arrData; | |
} | |
function download(filename, text) { | |
var element = document.createElement("a"); | |
element.setAttribute( | |
"href", | |
"data:application/json;charset=utf-8," + encodeURIComponent(text) | |
); | |
element.setAttribute("download", filename); | |
element.style.display = "none"; | |
document.body.appendChild(element); | |
element.click(); | |
document.body.removeChild(element); | |
} | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment