Skip to content

Instantly share code, notes, and snippets.

@mosherbrian
Last active February 5, 2022 18:12
Show Gist options
  • Save mosherbrian/8cac651831d980cacb3c435696b7bf7a to your computer and use it in GitHub Desktop.
Save mosherbrian/8cac651831d980cacb3c435696b7bf7a to your computer and use it in GitHub Desktop.
Gist for Vanilla JS Academy Week 4 projects
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Dragon Trainer Monthly</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style type="text/css">
body {
margin: 0 auto;
}
.table-header {
font-weight: bold;
}
tr:nth-of-type(odd) {
background-color:#ccc;
}
</style>
</head>
<body>
<h1>Dragon Trainer Monthly</h1>
<div id="app"></div>
<script>
"use strict;"
/**
* Encode the HTML in a user-submitted string
* https://portswigger.net/web-security/cross-site-scripting/preventing
* @param {String} str The user-submitted string
* @return {String} str The sanitized string
*/
function encodeHTML(str) {
return str
.replace(/data:/gi, '')
.replace(/javascript:/gi, '')
.replace(/[^\w-_. ]/gi, function (c) {
return `&#${c.charCodeAt(0)};`;
});
}
async function GetDragonTrainerEndpoints(endpoint)
{
try
{
let response = await fetch(endpoint);
if (!response.ok)
throw response.status;
// Get JSON data from the resonse
let data = await response.json();
if (!data)
throw 'No data';
return data;
}
catch (error)
{
return error;
}
}
async function formatArticleTable()
{
let data = await GetDragonTrainerEndpoints("https://vanillajsacademy.com/api/dragons.json");
if (data.publication !== "Dragon Trainer Monthly")
{
return "<h2>Dragon Trainer Monthly articles not available. Please try again later.</h2>";
}
let table =
`<table>
<tr class="table-header">
<td>Title</td><td>Author</td><td>Author Bio</td><td>Article</td><td>Date Published</td>
</tr>
${data.articles.map(
function (article)
{
return `<tr><td><a href="${encodeHTML(article.url)}">${encodeHTML(article.title)}</a></td><td>${encodeHTML(article.author)}</td><td data-authorname="${encodeHTML(article.author)}"></td><td>${encodeHTML(article.article)}</td><td>${encodeHTML(article.pubdate)}</td></tr>`
}).join("")}
</table>`;
return table;
}
async function getAuthorBios()
{
let data = await GetDragonTrainerEndpoints("https://vanillajsacademy.com/api/dragons-authors.json");
if (data.publication !== "Dragon Trainer Monthly")
{
console.warn("Dragon Trainer Author Bios not available at this time");
return "";
}
data.authors.map(
function (authorEntry)
{
let authorBioTDs = document.querySelectorAll(`[data-authorname="${encodeHTML(authorEntry.author)}"]`);
for (authorBioTD of authorBioTDs)
authorBioTD.innerText = authorEntry.bio;
}
);
}
let mainDiv = document.querySelector("#app");
formatArticleTable().then(function (table){
mainDiv.innerHTML = table;
getAuthorBios();
});
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Character & Word Count</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style type="text/css">
body {
margin: 0 auto;
max-width: 40em;
width: 88%;
}
label {
display: block;
width: 100%;
}
textarea {
min-height: 24em;
width: 100%;
}
</style>
</head>
<body>
<h1>VanillaJS Academy - Week 4 Projects</h1>
<script>
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment