This website is meant to be a showcase of some of the work I've done, including some of the schoolwork I've completed during my time at my university.
Additionally, I'm able to use it to host projects that are meant for the web, like the chess game. Not only that, but it gives me a chance to strengthen my web developer skills as I've been primarily back-end focused during my time at school.
I also get a chance to practice my creativity in creating a web UI and enhancing the end user experience.
View the repository for the site here.
The site was created using HTML5, CSS3, and JavaScript, with help from
Bootstrap and
JQuery. In addition, FontAwesome 5 was used for icons, as well as some Google Fonts.
For code higlighting on pages, highlight.js was used. To achieve the line numbering on the code display, I used highlightjs-line-numbers.js.
It was built by hand, using no templates or layouts, and is primarily built for modern browsers. However, I'm working to extend the functionality to legacy browsers as well.
I've included links to my resume, which is hosted on the site itself, in addition to links to my GitHub and LinkedIn. There's also a method of contacting me easily with any comments or questions.
The majority of the work has went into hosting some of my work from my GitHub page. This was achieved by contacting GitHub's API using JavaScript, and pulling the code straight from the repositories. This was also done for some images, like the screenshots found on my Flight Picker page. A code snippet demonstrating this is displayed below:
var language;
var loadingIcon;
function display_source(repo, filePath, inputLanguage, inputLoadingIcon)
{
language = inputLanguage;
loadingIcon = inputLoadingIcon;
var request = new XMLHttpRequest();
var fn = get_content;
request.onload = fn;
request.open('get', 'https://api.github.com/repos/44ghz/' + repo + '/contents' + filePath, true)
request.send();
}
function get_content()
{
var responseObj = JSON.parse(this.responseText);
var content = responseObj.content;
content = atob(content); // Decoding the content of the file
content = pad_content(content); // Add spaces to beginning of each line to offset the line numbering
// Creating element for code display
$(document.body).append(
` <div class="wrapper"><pre><code class="hljs `+ language + ` border-left">` + content + `</code></pre></div>
<div class="wrapper" id="ghlogo" style="pointer-events: none; user-select: none; user-interaction: none; disabled">
<div style="text-align: center; padding-bottom: 40px;">
<img draggable="false" src="img/ghmark32.png" alt="GitHub Mark" style="opacity: 0.2;"></img><span style="font-size: 12px; opacity: 0.4;"> API</span>
</div>
</div>`);
// Remove the loading circle when the content is loaded
var removeLoading = document.getElementById(loadingIcon);
removeLoading.parentNode.removeChild(removeLoading);
// Adding code highlighting for each <pre><code> block
document.querySelectorAll('pre code').forEach((block) => {
hljs.highlightBlock(block);
});
// Add the ability to toggle line numbers
var script = document.createElement("script");
script.src = "js/lineswitch.js";
document.head.appendChild(script);
};
The code is generalized to take in parameters of the repository, the filepath for the file, the type of language the file is, and the loading icon that is in place of the code while it loads.
It creates a new XMLHttpRequest, which loads the function get_content() before accessing GitHub's API with the request.open() function.
get_content() parses the return string and converts it to JSON, then decodes it (as the content from the return object is Base64 encoded).
Then, the DOM is accessed using JQuery and the body is appended to include the content from the HTTP request.
Once this is done, the loading icon is removed, and the code is highlighted using hightlightjs. There is a toggle for the line numbers, the script for which is loaded into the <head> afterwards.
The navbar is built using Bootstrap's navbar, and is designed to stay sticky to the top of the page while scrolling. It's got links for everything relevant about my work, and has a button for nightmode.
It stays persistent across the site by being contained in js/common.js, which is called in the <head> of every page.
The bar also reflects the time of day change, changing the gradient based on the current time. Not only that, but when the site is in day mode, there is a random cloud image chosen from a set of three. When the site is in nightmode, a background image of a starry sky is chosen instead.
Everything's gotta have a nightmode, right?
This was primarily added in for fun, and also because it's not necessarily easy to see a blinding white screen at night (or day if that's your thing).
Nightmode is activated by clicking the or on the navbar, and can be reverted by clicking the icon again. The effect is a transitioned change of colors from off-white to a purplish dark color, with matching accents.
In addition, when the icon is clicked, it performs a small animation, which is made using JQuery.
The effect is achieved through use of CSS variables and JavaScript / JQuery. When the icon is clicked, js/nightmode.js does a few things:
This doesn't just happen when the icon is clicked. When the page is loaded, it uses js/common.js to check the local storage for the current color scheme.
Depending on the mode selected, it performs the same functionality as clicking the button, but does so before the page finishes loading.
Check out the source code for the toggle below:
function toggleNightMode()
{
var date = new Date(); // Getting current date and time for use in deciding which day mode to display
var currentHour = date.getHours();
var cloudImageNumber = Math.floor(Math.random() * 3); // Random cloud image selection
var page = document.getElementsByTagName("html")[0]; // Get the entire html page as an object
if(localStorage["mode"] === "dark") // If the site is in dark mode, make it light
{
page.style.cssText = "--mydark: #414345";
page.style.cssText += "--mylight: #f9f9f9";
page.style.cssText += "--mygray: #e8e8e8";
page.style.cssText += "--mylight-gray: #f2f2f2";
page.style.cssText += "--mydark-gray: #e0e0e0";
if(currentHour <= MORNING && currentHour > SUNRISE) // Orange-yellow theme
{
page.style.cssText += "--nav-hover: rgba(255, 234, 199, 0.5)";
page.style.cssText += "--nav-gradient-1: #fcd8bb";
page.style.cssText += "--nav-gradient-2: #ff9b54";
}
else if(currentHour <= AFTERNOON && currentHour > MORNING) // Light blue theme
{
page.style.cssText += "--nav-hover: rgba(89, 200, 255, 0.5)";
page.style.cssText += "--nav-gradient-1: #adcdff";
page.style.cssText += "--nav-gradient-2: #5e9dff";
}
else if(currentHour <= EVENING && currentHour > AFTERNOON) // Darker orange, reversed
{
page.style.cssText += "--nav-hover: rgb(179, 86, 16, 0.5)";
page.style.cssText += "--nav-gradient-1: #ff8b38";
page.style.cssText += "--nav-gradient-2: #ffbd87";
}
else // Darker orange / lavender
{
page.style.cssText += "--nav-hover: rgba(140, 61, 0, 0.5)";
page.style.cssText += "--nav-gradient-1: #de6910";
page.style.cssText += "--nav-gradient-2: #85759c";
}
page.style.cssText += "--nav-background-img: url(../img/clouds" + cloudImageNumber + ".png)";
page.style.cssText += "--display-light: #ffffff";
page.style.cssText += "--white: #ffffff";
page.style.cssText += "--black: #000000";
// Replacing the stylesheets for code display
$("link[rel=stylesheet][href~='./highlight/styles/atom-one-dark.css']").remove();
$("head").append("<link rel='stylesheet' href='highlight/styles/atom-one-light.css'>");
localStorage["mode"] = "light"; // Updating local storage
// Animation for changing icon once the moon has set
window.setTimeout(function(){
$("#moonIcon").removeClass("fas fa-moon"); // Swapping moon icon
$("#moonIcon").addClass("fas fa-sun");
}, 200);
}
else
{
page.style.cssText = "--mydark: #ced0d9";
page.style.cssText += "--mylight: #282c34";
page.style.cssText += "--mygray: #1f2329";
page.style.cssText += "--mylight-gray: #343b45"
page.style.cssText += "--mydark-gray: #21242b";
page.style.cssText += "--nav-hover: rgba(59, 54, 69, 0.5)";
page.style.cssText += "--nav-gradient-1: #33303d";
page.style.cssText += "--nav-gradient-2: #1c1e24";
page.style.cssText += "--display-light: #1a191f"
page.style.cssText += "--white: #000000";
page.style.cssText += "--black: #ffffff";
page.style.cssText += "--nav-background-img: url(../img/stars.png)";
// Replacing the stylesheets for code display
$("link[rel=stylesheet][href~='./highlight/styles/atom-one-light.css']").remove();
$("head").append("<link rel='stylesheet' href='highlight/styles/atom-one-dark.css'>");
localStorage["mode"] = "dark"; // Updating local storage
// Animation for changing icon once the moon has set
window.setTimeout(function(){
$("#moonIcon").removeClass("fas fa-sun"); // Swapping moon icon
$("#moonIcon").addClass("fas fa-moon");
}, 200);
}
};
$(document).ready(function(){$("#moon")
.click(function(){
$("#moonIcon").slideUp("fast"); $("#moonIcon").slideDown("fast")})});
The first step is determining what mode the site is already in. If it's in day mode and the mode is toggled, change it to night and vice versa. To change the variables themselves, the entire HTML page is retrieved as an object using document.getElementsByTagName("html")[0].
Then, once the state of the site is determined, the page's CSS is accessed using page.style.cssText. We can overwrite the text that's already there by assigning the first value to the variable --mydark.
After that, it's just a matter of adding the subsequent variables onto the page.
Once the colors are finished, the background image for the navbar is changed, which is just the filepath used in styles/site.css. Afterwards, the stylesheet for the code highlighting is changed. This is done by selecting the current stylesheet and removing it using JQuery's .remove(); the new stylesheet is appended to the <head> using JQuery's .append() function.
The local storage is changed to reflect the current mode so the pages stay consistent across the site. The icon for nightmode on the navbar is changed, then the animation plays for the swap.