Created blog post page and updated a few things here and there to work with the blog post page. Has comments and a sidebar.
Signed-off-by: rodude123 <rodude123@gmail.com>
This commit is contained in:
+347
-11
@@ -1,3 +1,5 @@
|
||||
// nav bar scroll effect
|
||||
const scrollLimit = 150;
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () =>
|
||||
{
|
||||
@@ -9,6 +11,14 @@ window.addEventListener('popstate', _ =>
|
||||
goToURL(window.history.state);
|
||||
});
|
||||
|
||||
window.onscroll = () => {
|
||||
// check if scrolled past limit if so add scrolled class to change background of nav
|
||||
if (document.body.scrollTop >= scrollLimit || document.documentElement.scrollTop >= scrollLimit) {
|
||||
document.querySelector("nav").classList.add("scrolled");
|
||||
} else {
|
||||
document.querySelector("nav").classList.remove("scrolled");
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* goToURL tries to go to the specified URL if not shows the error page (not yet implemented)
|
||||
@@ -19,23 +29,349 @@ function goToURL(url)
|
||||
// Get the current URL and split it into an array
|
||||
let urlArray = url.split('/');
|
||||
|
||||
let newUrl = "";
|
||||
|
||||
if (urlArray.includes('blog'))
|
||||
if (url === "/blog/" || url === "/blog")
|
||||
{
|
||||
newUrl = url;
|
||||
loadHomeContent();
|
||||
// window.history.pushState(null, null, url);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the URL is a post page
|
||||
if (urlArray[0] === 'post')
|
||||
if (urlArray[2] === 'post')
|
||||
{
|
||||
// Create a new URL with the dynamic part
|
||||
newUrl = "/blog/" + url;
|
||||
// window.history.pushState(null, null, url);
|
||||
loadIndividualPost(urlArray[urlArray.length - 1]).catch(err => console.log(err));
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the URL in the browser without reloading the page
|
||||
window.history.pushState(null, null, newUrl);
|
||||
if (urlArray[2] === 'category') {
|
||||
// Create a new URL with the dynamic part
|
||||
// window.history.pushState(null, null, url);
|
||||
if (urlArray[3]) {
|
||||
loadPostsByCategory(urlArray[urlArray.length - 1]);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the dynamic part of the URL
|
||||
document.querySelector("#url").innerHTML = decodeURI(urlArray[urlArray.length - 1]);
|
||||
}
|
||||
loadAllCategories();
|
||||
return;
|
||||
}
|
||||
|
||||
show404();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a large post element
|
||||
* @param post the post object
|
||||
* @returns {HTMLDivElement} the outer content of the post
|
||||
*/
|
||||
function createLargePost(post) {
|
||||
let outerContent = document.createElement("div");
|
||||
outerContent.classList.add("outerContent");
|
||||
let img = document.createElement("img");
|
||||
img.className = "banner";
|
||||
img.src = post.headerImg;
|
||||
img.alt = post.title;
|
||||
outerContent.appendChild(img);
|
||||
let content = document.createElement("div");
|
||||
content.classList.add("content");
|
||||
let postContent = document.createElement("div");
|
||||
postContent.classList.add("postContent");
|
||||
let categories = "";
|
||||
post.categories.split(", ").forEach(category => {
|
||||
categories += `<a href="/blog/category/${category}" class="link">${category}</a>`
|
||||
if (post.categories.split(", ").length > 1) {
|
||||
categories += ", ";
|
||||
}
|
||||
});
|
||||
|
||||
window.categories = categories;
|
||||
|
||||
postContent.innerHTML = `
|
||||
<h2>${post.title}</h2>
|
||||
<h3>Last updated: ${post.dateModified} | ${categories}</h3>
|
||||
<p>${post.abstract}</p>
|
||||
<a href="/blog/post/${post.title}#disqus_thread" class="btn btnPrimary">See Post</a>
|
||||
`;
|
||||
content.appendChild(postContent);
|
||||
outerContent.appendChild(content);
|
||||
return outerContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the home content
|
||||
*/
|
||||
function loadHomeContent() {
|
||||
fetch("/api/blog/post").then(res => res.json().then(json => {
|
||||
for (let i = 0; i < json.length; i++) {
|
||||
if (json[i].featured === 1) {
|
||||
let featuredPost = document.createElement("section");
|
||||
featuredPost.classList.add("largePost");
|
||||
featuredPost.id = "featuredPost";
|
||||
let h1 = document.createElement("h1");
|
||||
h1.innerHTML = "featured post";
|
||||
featuredPost.appendChild(h1);
|
||||
let outerContent = createLargePost(json[i]);
|
||||
featuredPost.appendChild(outerContent);
|
||||
document.querySelector("#main").prepend(featuredPost);
|
||||
}
|
||||
|
||||
if (i === 0) {
|
||||
let latestPost = document.createElement("section");
|
||||
latestPost.classList.add("largePost");
|
||||
latestPost.id = "latestPost";
|
||||
let h1 = document.createElement("h1");
|
||||
h1.innerHTML = "latest post";
|
||||
latestPost.appendChild(h1);
|
||||
let outerContent = createLargePost(json[i]);
|
||||
latestPost.appendChild(outerContent);
|
||||
document.querySelector("#main").prepend(latestPost);
|
||||
}
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the latest and featured posts
|
||||
* @returns {Promise<any[]>} the latest and featured posts
|
||||
*/
|
||||
async function getLatestAndFeaturedPosts() {
|
||||
let latestPost = await fetch("/api/blog/post/latest").then(res => res.json());
|
||||
let featuredPost = await fetch("/api/blog/post/featured").then(res => res.json());
|
||||
return [latestPost, featuredPost];
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a csv to an array
|
||||
* @param text the csv text
|
||||
* @returns {string[]} the array
|
||||
*/
|
||||
function csvToArray(text) {
|
||||
let p = '';
|
||||
let arr = [''];
|
||||
let i = 0;
|
||||
let s = true;
|
||||
let l = null;
|
||||
for (l of text) {
|
||||
if ('"' === l) {
|
||||
if (s && l === p) {
|
||||
arr[i] += l;
|
||||
}
|
||||
s = !s;
|
||||
} else if (',' === l && s) {
|
||||
l = arr[++i] = '';
|
||||
} else if ('\n' === l && s) {
|
||||
if ('\r' === p) row[i] = row[i].slice(0, -1);
|
||||
arr = arr[++r] = [l = ''];
|
||||
i = 0;
|
||||
} else {
|
||||
arr[i] += l;
|
||||
}
|
||||
p = l;
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the categories
|
||||
* @returns {Promise<*[]>} the categories
|
||||
*/
|
||||
async function getCategories() {
|
||||
let categories = await fetch("/api/blog/categories").then(res => res.json());
|
||||
let modifiedCategories = [];
|
||||
categories.forEach(category => modifiedCategories.push(csvToArray(category.categories)));
|
||||
return modifiedCategories;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the categories
|
||||
* @param {*[]} categoriesList the categories
|
||||
*/
|
||||
function createCategories(categoriesList) {
|
||||
let categories = "";
|
||||
categoriesList.forEach(lst => lst.forEach(category => categories += `<a href="/blog/category/${category}" class="link">${category}</a>`));
|
||||
return categories;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates the button categories
|
||||
* @param {string[][]} categoriesList - the categories
|
||||
*/
|
||||
function createButtonCategories(categoriesList) {
|
||||
let categories = "";
|
||||
categoriesList.forEach(lst => lst.forEach(category => categories += `<a href="/blog/category/${category}" class="btn btnOutline">${category}</a>`));
|
||||
return categories;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the side content
|
||||
* @returns {HTMLElement} the aside element
|
||||
*/
|
||||
async function createSideContent() {
|
||||
|
||||
let posts = await getLatestAndFeaturedPosts();
|
||||
let latestPost = posts[0];
|
||||
let featuredPost = posts[1];
|
||||
let categoriesList = await getCategories();
|
||||
let categories = createCategories(categoriesList);
|
||||
|
||||
let sideContent = document.createElement("aside");
|
||||
sideContent.classList.add("sideContent");
|
||||
sideContent.innerHTML = `
|
||||
<div class="authorInfo">
|
||||
<div class="picture">
|
||||
<img src="/imgs/profile.jpg"
|
||||
alt="My professional picture taken in brighton near
|
||||
north street at night wearing a beige jacket and checkered shirt"
|
||||
class="profile">
|
||||
<p>Rohit Pai</p>
|
||||
</div>
|
||||
|
||||
<a href="https://linkedin.com/in/rohitpai98">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path d="M12 0c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm-2 16h-2v-6h2v6zm-1-6.891c-.607 0-1.1-.496-1.1-1.109 0-.612.492-1.109 1.1-1.109s1.1.497 1.1 1.109c0 .613-.493 1.109-1.1 1.109zm8 6.891h-1.998v-2.861c0-1.881-2.002-1.722-2.002 0v2.861h-2v-6h2v1.093c.872-1.616 4-1.736 4 1.548v3.359z"/>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
<a href="mailto:rohit@rohitpai.co.uk">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
<path d="M13.718 10.528c0 .792-.268 1.829-.684 2.642-1.009 1.98-3.063 1.967-3.063-.14 0-.786.27-1.799.687-2.58 1.021-1.925 3.06-1.624 3.06.078zm10.282 1.472c0 6.627-5.373 12-12 12s-12-5.373-12-12 5.373-12 12-12 12 5.373 12 12zm-5-1.194c0-3.246-2.631-5.601-6.256-5.601-4.967 0-7.744 3.149-7.744 7.073 0 3.672 2.467 6.517 7.024 6.517 2.52 0 4.124-.726 5.122-1.288l-.687-.991c-1.022.593-2.251 1.136-4.256 1.136-3.429 0-5.733-2.199-5.733-5.473 0-5.714 6.401-6.758 9.214-5.071 2.624 1.642 2.524 5.578.582 7.083-1.034.826-2.199.799-1.821-.756 0 0 1.212-4.489 1.354-4.975h-1.364l-.271.952c-.278-.785-.943-1.295-1.911-1.295-2.018 0-3.722 2.19-3.722 4.783 0 1.73.913 2.804 2.38 2.804 1.283 0 1.95-.726 2.364-1.373-.3 2.898 5.725 1.557 5.725-3.525z"/>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
<a href="https://gitea.rohitpai.co.uk/rodude123">
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
x="0px" y="0px" viewBox="0 0 1024 1024"
|
||||
style="enable-background:new -1 0 1024 1024;" xml:space="preserve">
|
||||
<style type="text/css">.st1 {fill: #FFFFFF;}</style>
|
||||
<g id="Guides"></g>
|
||||
<g id="Icon"><circle class="st0" cx="512" cy="512" r="512"/>
|
||||
<g><path class="st1" d="M762.2,350.3c-100.9,5.3-160.7,8-212,8.5v114.1l-16-7.9l-0.1-106.1c-58.9,0-110.7-3.1-209.1-8.6 c-12.3-0.1-29.5-2.4-47.9-2.5c-47.1-0.1-110.2,33.5-106.7,118C175.8,597.6,296,609.9,344,610.9c5.3,24.7,61.8,110.1,103.6,114.6 H631C740.9,717.3,823.3,351.7,762.2,350.3z M216.2,467.6c-4.7-36.6,11.8-74.8,73.2-73.2C296.1,462,307,501.5,329,561.9 C272.8,554.5,225,536.2,216.2,467.6z M631.8,551.1l-51.3,105.6c-6.5,13.4-22.7,19-36.2,12.5l-105.6-51.3 c-13.4-6.5-19-22.7-12.5-36.2l51.3-105.6c6.5-13.4,22.7-19,36.2-12.5l105.6,51.3C632.7,521.5,638.3,537.7,631.8,551.1z"/>
|
||||
<path class="st1"
|
||||
d="M555,609.9c0.1-0.2,0.2-0.3,0.2-0.5c17.2-35.2,24.3-49.8,19.8-62.4c-3.9-11.1-15.5-16.6-36.7-26.6 c-0.8-0.4-1.7-0.8-2.5-1.2c0.2-2.3-0.1-4.7-1-7c-0.8-2.3-2.1-4.3-3.7-6l13.6-27.8l-11.9-5.8L519.1,501c-2,0-4.1,0.3-6.2,1 c-8.9,3.2-13.5,13-10.3,21.9c0.7,1.9,1.7,3.5,2.8,5l-23.6,48.4c-1.9,0-3.8,0.3-5.7,1c-8.9,3.2-13.5,13-10.3,21.9 c3.2,8.9,13,13.5,21.9,10.3c8.9-3.2,13.5-13,10.3-21.9c-0.9-2.5-2.3-4.6-4-6.3l23-47.2c2.5,0.2,5,0,7.5-0.9 c2.1-0.8,3.9-1.9,5.5-3.3c0.9,0.4,1.9,0.9,2.7,1.3c17.4,8.2,27.9,13.2,30,19.1c2.6,7.5-5.1,23.4-19.3,52.3 c-0.1,0.2-0.2,0.5-0.4,0.7c-2.2-0.1-4.4,0.2-6.5,1c-8.9,3.2-13.5,13-10.3,21.9c3.2,8.9,13,13.5,21.9,10.3 c8.9-3.2,13.5-13,10.3-21.9C557.8,613.6,556.5,611.6,555,609.9z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</a>
|
||||
<h3>Avid Full Stack Dev | Uni of Notts Grad | Amateur Blogger</h3>
|
||||
|
||||
</div>
|
||||
<div class="otherPosts">
|
||||
<h2>latest post</h2>
|
||||
<h3>${latestPost.title}</h3>
|
||||
<p>${latestPost.abstract}</p>
|
||||
<a href="/blog/post/${latestPost.title}" class="btn btnPrimary boxShadowIn boxShadowOut">See Post</a>
|
||||
</div>
|
||||
<div class="otherPosts">
|
||||
<h2>featured post</h2>
|
||||
<h3>${featuredPost.title}</h3>
|
||||
<p>${featuredPost.abstract}</p>
|
||||
<a href="/blog/post/${featuredPost.title}" class="btn btnPrimary boxShadowIn boxShadowOut">See Post</a>
|
||||
</div>
|
||||
<div class="categories">
|
||||
<h2>categories</h2>
|
||||
${categories}
|
||||
</div>
|
||||
`;
|
||||
return sideContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trys to load the individual post if not runs the 404 function
|
||||
* @param title
|
||||
*/
|
||||
async function loadIndividualPost(title) {
|
||||
document.title = "Rohit Pai - " + decodeURI(title);
|
||||
await fetch(`/api/blog/post/${title}`).then(async res => {
|
||||
if (!res.ok) {
|
||||
show404();
|
||||
return;
|
||||
}
|
||||
|
||||
await res.json().then(async json => {
|
||||
// create the post
|
||||
let post = document.createElement("section");
|
||||
post.classList.add("post");
|
||||
post.id = "individualPost";
|
||||
let mainContent = document.createElement("div");
|
||||
mainContent.classList.add("mainContent");
|
||||
let article = document.createElement("article");
|
||||
article.innerHTML = `
|
||||
<h1>${json.title}</h1>
|
||||
<div class="byLine">
|
||||
<h3>Last updated: ${json.dateModified}</h3>
|
||||
<h3>${createButtonCategories([csvToArray(json.categories)])}</h3>
|
||||
</div>
|
||||
<div class="cover" style="background-image: url('${json.headerImg}')"></div>
|
||||
${json.body}
|
||||
`;
|
||||
let comments = document.createElement("section");
|
||||
comments.classList.add("comments");
|
||||
comments.innerHTML = `<h2>Comments</h2>
|
||||
<div id="disqus_thread"></div>
|
||||
`;
|
||||
|
||||
mainContent.appendChild(article);
|
||||
mainContent.appendChild(comments);
|
||||
let sideContent = await createSideContent();
|
||||
post.appendChild(mainContent);
|
||||
post.appendChild(sideContent);
|
||||
|
||||
document.querySelector("#main").appendChild(post);
|
||||
|
||||
let disqus_config = _ => {
|
||||
this.page.url = window.location.href; // Replace PAGE_URL with your page's canonical URL variable
|
||||
this.page.identifier = window.location.href.substring(window.location.href.lastIndexOf("/") + 1); // Replace PAGE_IDENTIFIER with your page's unique identifier variable
|
||||
};
|
||||
|
||||
(function () { // DON'T EDIT BELOW THIS LINE
|
||||
var d = document, s = d.createElement('script');
|
||||
s.src = 'https://rohitpaiportfolio.disqus.com/embed.js';
|
||||
s.setAttribute('data-timestamp', +new Date());
|
||||
d.body.appendChild(s);
|
||||
})();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function loadAllCategories() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the posts by category
|
||||
* @param category the category
|
||||
*/
|
||||
function loadPostsByCategory(category) {
|
||||
document.title = "Rohit Pai - " + decodeURI(category);
|
||||
fetch(`/api/blog/post/category/${category}`).then(res => res.json().then(json => {
|
||||
let posts = document.createElement("section");
|
||||
posts.classList.add("posts");
|
||||
posts.id = "postsByCategory";
|
||||
let h1 = document.createElement("h1");
|
||||
h1.innerHTML = category;
|
||||
posts.appendChild(h1);
|
||||
for (let i = 0; i < json.length; i++) {
|
||||
let outerContent = createLargePost(json[i]);
|
||||
posts.appendChild(outerContent);
|
||||
}
|
||||
document.querySelector("#main").appendChild(posts);
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the 404 page
|
||||
*/
|
||||
function show404() {
|
||||
document.querySelector("#main").innerHTML = `
|
||||
<div class="error">
|
||||
<div class="fof">
|
||||
<h1>Blog post, Category or page not found</h1>
|
||||
<a href="/blog/" class="btn btnPrimary">See all blog posts</a>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user