rewrite of js files (#19)

This commit is contained in:
Gerome Matilla 2020-06-09 10:02:03 +08:00 committed by GitHub
parent a9b176a483
commit 581cdea730
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 2290 additions and 1945 deletions

View File

@ -64,7 +64,7 @@
#### Adding more buttons on the web menu
Add more buttons or web shortcuts in web menu by editing the `webSites` array in `js/sites-list.js`. Make sure to put an icon with `svg` format for the shortcut in `assets/webcons/` folder.
Add more buttons or web shortcuts in web menu by editing the `webSites` array in `js/config.js`. Make sure to put an icon with `svg` format for the shortcut in `assets/webcons/` folder.
```js
let webSites = [
@ -80,7 +80,7 @@ let webSites = [
#### Adding more buttons on the dock
To add more web shortcuts/buttons in the dock, you have to edit the `dockSites` array in `js/sites-list.js`. Make sure to put an icon with `svg` format for the shortcut in `assets/webcons/` folder.
To add more web shortcuts/buttons in the dock, you have to edit the `dockSites` array in `js/config.js`. Make sure to put an icon with `svg` format for the shortcut in `assets/webcons/` folder.
```js
let dockSites = [
@ -121,6 +121,13 @@ Google is the default search engine of the search bar, if you want to change it
+ Replace the `user.png` image file in `/assets/`.
#### Changing the background image
The background image changes based on time.
+ Change the background images in `assets/backgrounds/`.
+ Make sure that it is in `webp` format.
+ A lower resolution of each images are also required.
#### Keybindings

View File

@ -67,6 +67,7 @@
<li id='phrase'>
<button type='button' class='phraseButton'>suggestion 4</button>
</li>
<!-- The list above will be deleted and will be replaced by a list generated by javascript -->
</ul>
</div>
@ -230,24 +231,33 @@
</div>
<script src='js/config.js'></script>
<script src='js/body-background-set.js'></script>
<script src='js/clock.js'></script>
<script src='js/sites-list.js'></script>
<script src='js/dock-buttons.js'></script>
<script src='js/keybindings.js'></script>
<script src='js/auto-suggest.js'></script>
<script src='js/animate-profile-image.js'></script>
<script src='js/show-search-box.js'></script>
<script src='js/animate-dashboard.js'></script>
<script src='js/greeter-date-message.js'></script>
<script src='js/profile-image.js'></script>
<script src='js/search-engine-settings.js'></script>
<script src='js/search-query-send.js'></script>
<script src='js/show-search-box.js'></script>
<script src='js/centered-box.js'></script>
<script src='js/greeter-date-message.js'></script>
<script src='js/theme-engine.js'></script>
<script src='js/dashboard.js'></script>
<script src='js/web-menu.js'></script>
<script src='js/weather-screen.js'></script>
<script src='js/weather-settings.js'></script>
<script src='js/web-menu.js'></script>
<script src='js/centered-box.js'></script>
<script src='js/auto-suggestion.js'></script>
<script src='js/keybindings.js'></script>
<script src='js/mobile-swipe-event.js'></script>
<script src='js/mobile-swipe-callback.js'></script>
<script src='js/script.js'></script>
</body>
</html>

View File

@ -1,96 +0,0 @@
const dashboard = document.getElementById("rightDashboard");
const dashboardOverlay = document.getElementById("dashboardOverlay");
let rightDashboardVisibility = false;
// Disable/Enable inputs
const disableDashboardInputs = (status) => {
const elems = dashboard.getElementsByTagName('input');
const len = elems.length;
for (let i = 0; i < len; i++) {
elems[i].disabled = status;
}
}
const showDashboard = () => {
dashboard.classList.add('showRightDashboard');
// Show overlay
dashboardOverlay.classList.add('showDashboardOverlay');
// Enable Inputs
disableDashboardInputs(false);
rightDashboardVisibility = !rightDashboardVisibility;
}
const hideDashboard = () => {
dashboard.classList.remove('showRightDashboard');
dashboard.scrollTop = 0;
// Disable Inputs
disableDashboardInputs(true);
// Hide overlay
dashboardOverlay.classList.remove('showDashboardOverlay');
rightDashboardVisibility = !rightDashboardVisibility;
}
const toggleDashboard = () => {
console.log('toggle dashboard');
if (rightDashboardVisibility) {
// Hide dashboard
hideDashboard();
} else {
// Show dashboard
showDashboard();
// If centered box is hidden, open it
if (centeredBox.classList.contains('hiddenBox')) {
console.log('centered box is hidden, reopening...');
// Rotate profile container
rotateProfile();
// Toggle center box
toggleCenteredBox();
}
}
// Check if any of these are open, if yes, close it
if (weatherScreen.classList.contains('showWeatherScreen')) {
console.log('weather screen is open, closing...');
hideWeatherScreen();
return;
} else if (searchBoxContainer.classList.contains('showSearchBox')) {
console.log('searchbox is open, closing...');
hideSearchBox();
} else if (webMenu.classList.contains('showWebMenu')) {
console.log('web menu is open, closing...');
hideWebMenu();
return;
}
}
dashboardOverlay.addEventListener(
"mouseup",
() => {
if (rightDashboardVisibility) {
toggleDashboard();
}
}
);
// Disable dashboard inputs on startup
window.onload = disableDashboardInputs(true);

View File

@ -1,43 +0,0 @@
const profileContainer = document.getElementById("profileImageContainer");
let profileAnimRunning = false;
// Don't run animation on startup
profileContainer.style.webkitAnimationPlayState = "paused";
// Rotate profile
const rotateProfile = () => {
event.preventDefault;
// Remove anim class
profileContainer.classList.remove('rotateProfileAnim');
// Triggering reflow
void profileContainer.offsetWidth;
// Re-add animation class
profileContainer.classList.add('rotateProfileAnim');
// Start rotation animation
profileContainer.style.webkitAnimationPlayState = "running";
profileAnimRunning = true;
}
// Re-enable animation after death
profileContainer.addEventListener(
"animationend",
(event) => {
profileAnimRunning = false;
}
);
// Animate/Show searchbox if profile container was clicked
profileContainer.onclick = () => {
if (profileAnimRunning) return;
// Rotate profile
// rotateProfile();
// Toggle search box
toggleSearchBox();
};

View File

@ -1,123 +0,0 @@
var searchBox = document.getElementById('searchBox');
var suggestionsUL = document.getElementById('suggestions');
var suggestionsContainer = document.getElementById('suggestionsContainer');
const hideSuggestions = () => {
// Hide suggestions
suggestionsContainer.classList.remove('suggestionsShow');
}
const showSuggestions = () => {
// Show suggestions
suggestionsContainer.classList.add('suggestionsShow');
}
// Create input events
const phraseEvents = button => {
// Update searchbox on enter key and mouse click
button.onkeyup = event => {
if (event.key === 'Enter') {
searchBox.value = button.innerText;
searchBox.focus();
} else if (event.key === 'Backspace') {
searchBox.focus();
} else if ((event.key == 'ArrowDown') || event.key == 'ArrowRight') {
event.preventDefault();
const phraseButtons = Array.prototype.slice.call(document.querySelectorAll('button'));
const phraseIndex = (phraseButtons.indexOf(document.activeElement) + 1) % phraseButtons.length;
const phraseButton = phraseButtons[phraseIndex];
phraseButton.focus();
} else if ((event.key == 'ArrowUp') || event.key == 'ArrowLeft') {
event.preventDefault();
const phraseButtons = Array.prototype.slice.call(document.querySelectorAll('button'));
const phraseIndex = (phraseButtons.indexOf(document.activeElement) - 1) % phraseButtons.length;
if (phraseIndex < 0) {
phraseIndex = phraseButtons.length - 1;
};
const phraseButton = phraseButtons[phraseIndex];
phraseButton.focus();
}
}
// Onmouseup event
button.onmouseup = event => {
searchBox.value = button.innerText;
searchBox.focus();
}
}
// Generate and parse suggestions
const autocompleteCallback = phrase => {
// Filter/parse the object
const suggestion = phrase.map(i => i.phrase)
.filter(s => !(s.toLowerCase() === String(searchBox.value).toLowerCase()))
.slice(0, 4);
// Empty ul on every callback to refresh list
suggestionsUL.innerHTML = '';
// Generate list elements
for (let phrases of suggestion ) {
// Create html elements
const li = document.createElement('li');
li.id = 'phrase';
const button = document.createElement('button');
button.type = 'button';
button.className = 'phraseButton';
button.innerHTML = phrases;
// Create input events
phraseEvents(button);
// Appent to ul
li.appendChild(button);
suggestionsUL.appendChild(li);
}
// Show suggestions
showSuggestions();
}
// Update every keyup
searchBox.onkeyup = event => {
if (event.key === 'Tab') return;
if (searchBox.value < 1) {
// Hide suggestions
hideSuggestions();
return;
}
// Fetch from duckduckgo
const script = document.createElement('script');
script.type = "text/javascript";
script.src = "https://duckduckgo.com/ac/?callback=autocompleteCallback&q="+String(searchBox.value);
document.querySelector('head').appendChild(script);
}

137
js/auto-suggestion.js Normal file
View File

@ -0,0 +1,137 @@
class AutoSuggestion {
constructor() {
this._searchBox = document.querySelector('#searchBox');
this._suggestionsUL = document.querySelector('#suggestions');
this._suggestionsContainer = document.querySelector('#suggestionsContainer');
this._registerSearchBoxOnKeyUpEvent();
}
_hideSuggestions = () => {
// Hide suggestions
this._suggestionsContainer.classList.remove('suggestionsShow');
}
_showSuggestions = () => {
// Show suggestions
this._suggestionsContainer.classList.add('suggestionsShow');
}
// Create input events
_phraseEvents = button => {
// Update searchbox on enter key and mouse click
button.onkeyup = e => {
if (e.key === 'Enter') {
this._searchBox.value = button.innerText;
this._searchBox.focus();
} else if (e.key === 'Backspace') {
this._searchBox.focus();
} else if ((e.key == 'ArrowDown') || e.key == 'ArrowRight') {
e.preventDefault();
const phraseButtons = Array.prototype.slice.call(document.querySelectorAll('button'));
const phraseIndex = (phraseButtons.indexOf(document.activeElement) + 1) % phraseButtons.length;
const phraseButton = phraseButtons[phraseIndex];
phraseButton.focus();
} else if ((e.key == 'ArrowUp') || e.key == 'ArrowLeft') {
e.preventDefault();
const phraseButtons = Array.prototype.slice.call(document.querySelectorAll('button'));
const phraseIndex = (phraseButtons.indexOf(document.activeElement) - 1) % phraseButtons.length;
if (phraseIndex < 0) {
phraseIndex = phraseButtons.length - 1;
};
const phraseButton = phraseButtons[phraseIndex];
phraseButton.focus();
}
}
// Onmouseup event
button.onmouseup = e => {
this._searchBox.value = button.innerText;
this._searchBox.focus();
}
}
// Generate and parse suggestions
_autocompleteCallback = phrase => {
// Filter/parse the objectgerome matil
const suggestion = phrase.map(i => i.phrase)
.filter(s => !(s.toLowerCase() === String(this._searchBox.value).toLowerCase()))
.slice(0, 4);
// Empty ul on every callback to refresh list
this._suggestionsUL.innerHTML = '';
// Generate list elements
for (let phrases of suggestion) {
// Create html elements
const li = document.createElement('li');
li.id = 'phrase';
const button = document.createElement('button');
button.type = 'button';
button.className = 'phraseButton';
button.innerHTML = phrases;
// Create input events
this._phraseEvents(button);
// Appent to ul
li.appendChild(button);
this._suggestionsUL.appendChild(li);
}
// Show suggestions
this._showSuggestions();
}
_fetchSuggestion = () => {
const endpoint = 'https://duckduckgo.com/ac/';
const callback = 'autocompleteCallback'
window[callback] = res => {
// Passed the suggestion object to process it
this._autocompleteCallback(res);
}
// Fetch from duckduckgo
const script = document.createElement('script');
script.type = 'text/javascript';
script.src = `${endpoint}?callback=${callback}&q=` + String(this._searchBox.value);
document.querySelector('head').appendChild(script);
}
_searchBoxOnKeyUpEvent = e => {
if (e.key === 'Tab') return;
if (this._searchBox.value < 1) {
// Hide suggestions
this._hideSuggestions();
return;
}
// Fetch suggestion/phrases
this._fetchSuggestion();
}
_registerSearchBoxOnKeyUpEvent = () => {
this._searchBox.onkeyup = this._searchBoxOnKeyUpEvent;
}
}

View File

@ -1,63 +1,58 @@
const backgroundBody = document.getElementById('bodyBackground')
class BodyBackground {
// High quality background, we'll lazy load this
const hqBackground = document.createElement("img");
constructor() {
this._bodyBackground = document.querySelector('#bodyBackground');
this._hqBackground = document.createElement('img');
this._bodyBackgroundStyle = this._bodyBackground.style;
this._startLazyLoad();
}
// Style body background
const styleBodyBackground = (bgBodyStyle) => {
bgBodyStyle.backgroundSize = 'cover';
bgBodyStyle.backgroundRepeat = "no-repeat";
bgBodyStyle.backgroundPosition = "center";
bgBodyStyle.backgroundAttachment = "fixed";
}
_setBodyBackgrond = urlStr => {
this._bodyBackgroundStyle.background = urlStr;
this._bodyBackgroundStyle.backgroundSize = 'cover';
this._bodyBackgroundStyle.backgroundRepeat = 'no-repeat';
this._bodyBackgroundStyle.backgroundPosition = 'center';
this._bodyBackgroundStyle.backgroundAttachment = 'fixed';
}
const lazyLoadBackground = (fileName) => {
_lazyLoadBackground = fileName => {
// Shorten backgroundBody.style or alias it
const bgBodyStyle = backgroundBody.style;
// Set a low quality background image
bgBodyStyle.background = "url('assets/backgrounds/" +
fileName + "-low" + ".webp')";
styleBodyBackground(bgBodyStyle);
// Add a class to blur it
backgroundBody.classList.add("blurFiltered");
hqBackground.onload = () => {
// Set a low quality background image
this._setBodyBackgrond(`url('assets/backgrounds/${fileName}-low.webp')`);
// After downloading the HQ image, set it as bg
backgroundBody.style.background = "url("+ hqBackground.src; + ")";
styleBodyBackground(bgBodyStyle);
// Add a class to blur it
this._bodyBackground.classList.add('blurFiltered');
// Remove class to unblur
backgroundBody.classList.remove("blurFiltered");
this._hqBackground.onload = () => {
// After downloading the HQ image, set it as bg
this._setBodyBackgrond(`url('${this._hqBackground.src}')`);
// Remove class to unblur
this._bodyBackground.classList.remove('blurFiltered');
}
// Add a delay when to fetch background
setTimeout(
() => {
this._hqBackground.src = `assets/backgrounds/${fileName}.webp`;
},
50
);
}
_startLazyLoad = () => {
const date = new Date();
const hour = date.getHours();
// Add a delay when to fetch background
setTimeout(
() => {
hqBackground.src = "assets/backgrounds/" +
fileName + ".webp";
},
50
);
}
if (hour >= 6 && hour < 12) {
this._lazyLoadBackground('morning');
const initLazyLoad = () => {
const date = new Date();
const hour = date.getHours();
} else if (hour >= 12 && hour < 18 ) {
this._lazyLoadBackground('noon');
if (hour >= 6 && hour < 12) {
lazyLoadBackground("morning");
} else if (hour >= 12 && hour < 18 ) {
lazyLoadBackground("noon");
} else {
lazyLoadBackground("evening");
} else {
this._lazyLoadBackground('evening');
}
}
}
// Initialize
window.onload = initLazyLoad();
}

View File

@ -1,25 +1,33 @@
const centeredBox = document.getElementById("centeredBox");
class CenteredBox {
constructor() {
this._centeredBox = document.querySelector('#centeredBox');
let centeredBoxVisibility = true;
this._centeredBoxVisibility = true;
const showCenteredBox = () => {
centeredBox.classList.remove('hiddenBox');
centeredBoxVisibility = !centeredBoxVisibility;
}
this.showCenteredBox = this.showCenteredBox.bind(this);
this.hideCenteredBox = this.hideCenteredBox.bind(this);
this.toggleCenteredBox = this.toggleCenteredBox.bind(this);
}
const hideCenteredBox = () => {
centeredBox.classList.add('hiddenBox');
centeredBoxVisibility = !centeredBoxVisibility;
}
showCenteredBox = () => {
this._centeredBox.classList.remove('hiddenBox');
this._centeredBoxVisibility = !this._centeredBoxVisibility;
}
const toggleCenteredBox = () => {
hideCenteredBox = () => {
this._centeredBox.classList.add('hiddenBox');
this._centeredBoxVisibility = !this._centeredBoxVisibility;
}
if (centeredBoxVisibility) {
// Hide web menu
hideCenteredBox();
toggleCenteredBox = () => {
} else {
// Show Web menu
showCenteredBox();
if (this._centeredBoxVisibility) {
// hide centered box
this.hideCenteredBox();
} else {
// Show centered box
this.showCenteredBox();
}
}
}

View File

@ -1,39 +1,42 @@
const clock = document.getElementById("clock")
class Clock {
// Append 0 before time elements if less hour's than 10
const appendZero = (k) => {
if (k < 10) {
return "0" + k;
} else {
return k;
constructor() {
this._clockEl = document.querySelector('#clock');
this._setTime = this._setTime.bind(this);
this._startClock();
}
}
// Update/Set clock
const currentTime = () => {
// Date object
const date = new Date();
// Append 0 before time elements if less hour's than 10
_appendZero = k => {
if (k < 10) {
return '0' + k;
} else {
return k;
}
}
// Set hour, minute
let hour = date.getHours();
let min = date.getMinutes();
let midDay = "AM";
// Assigning
midDay = (hour >= 12) ? "PM" : "AM";
hour = (hour == 0) ? 12 : ((hour > 12) ? (hour - 12): hour);
hour = appendZero(hour);
min = appendZero(min);
_setTime = () => {
// Date object
const date = new Date();
// Update clock id element
clock.innerText = hour + ":" + min + " " + midDay;
// Recursion
// Call itself if 1 second has passed.
// TOKIWO TOMAREEEE!
const t = setTimeout(currentTime, 1000);
}
// Set hour, minute
let hour = date.getHours();
let min = date.getMinutes();
let midDay = 'AM';
// Assigning
midDay = (hour >= 12) ? 'PM' : 'AM';
hour = (hour == 0) ? 12 : ((hour > 12) ? (hour - 12) : hour);
hour = this._appendZero(hour);
min = this._appendZero(min);
// Start clock
window.onload = currentTime();
// Update clock id element
this._clockEl.innerHTML = `${hour}:${min}${midDay}` ;
}
_startClock = () => {
this._setTime();
setTimeout(this._setTime, 1000);
}
}

323
js/config.js Normal file
View File

@ -0,0 +1,323 @@
class Config {
constructor() {
this.getWebSites = this.getWebSites.bind(this);
this.getDockSites = this.getDockSites.bind(this);
}
getWebSites = () => {
// Web menu
// A list of websites that will be generated and put on the web menu
const webSites = [
{
site: 'Reddit',
icon: 'reddit',
url: 'https://reddit.com/',
category: 'social'
},
{
site: 'Github',
icon: 'github',
url: 'https://github.com/',
category: 'development'
},
{
site: 'Facebook',
icon: 'facebook',
url: 'https://facebook.com/',
category: 'social'
},
{
site: 'Gmail',
icon: 'gmail',
url: 'https://mail.google.com/',
category: 'social'
},
{
site: 'Youtube',
icon: 'youtube',
url: 'https://youtube.com/',
category: 'media'
},
{
site: 'GDrive',
icon: 'gdrive',
url: 'https://drive.google.com/',
category: 'cloud'
},
{
site: 'Twitter',
icon: 'twitter',
url: 'https://twitter.com/',
category: 'social'
},
{
site: 'Instagram',
icon: 'instagram',
url: 'https://instagram.com/',
category: 'social'
},
{
site: 'Bitbucket',
icon: 'bitbucket',
url: 'https://bitbucket.org/',
category: 'development'
},
{
site: 'Gitlab',
icon: 'gitlab',
url: 'https://gitlab.com/',
category: 'development'
},
{
site: 'Deviantart',
icon: 'deviantart',
url: 'https://deviantart.com/',
category: 'design'
},
{
site: 'Duckduckgo',
icon: 'duckduckgo',
url: 'https://duckduckgo.com/',
category: 'development'
},
{
site: 'Ecosia',
icon: 'ecosia',
url: 'https://ecosia.org/',
category: 'search engine'
},
{
site: 'Google',
icon: 'google',
url: 'https://google.com/',
category: 'search engine'
},
{
site: 'Wikipedia',
icon: 'wikipedia',
url: 'https://wikipedia.org/',
category: 'information'
},
{
site: 'Unsplash',
icon: 'unsplash',
url: 'https://unsplash.com/',
category: 'design'
},
{
site: 'Twitch',
icon: 'twitch',
url: 'https://twitch.tv/',
category: 'media'
},
{
site: 'Yahoo',
icon: 'yahoo',
url: 'https://mail.yahoo.com/',
category: 'social'
},
{
site: 'Material.io',
icon: 'materialio',
url: 'https://material.io/',
category: 'design'
},
{
site: 'Netflix',
icon: 'netflix',
url: 'https://netflix.com/',
category: 'media'
},
{
site: 'Office 365',
icon: 'office365',
url: 'https://office.com/',
category: 'information'
},
{
site: '4chan',
icon: '4chan',
url: 'https://4chan.org/',
category: 'social'
},
{
site: 'Discord',
icon: 'discord',
url: 'https://discord.com/',
category: 'social'
},
{
site: 'Spotify',
icon: 'spotify',
url: 'https://spotify.com/',
category: 'media'
},
{
site: 'Ebay',
icon: 'ebay',
url: 'https://ebay.com/',
category: 'shop'
},
{
site: 'JSFiddle',
icon: 'jsfiddle',
url: 'https://jsfiddle.net/',
category: 'development'
},
{
site: 'ArchWiki',
icon: 'archwiki',
url: 'https://wiki.archlinux.org/',
category: 'information'
},
{
site: 'Figma',
icon: 'figma',
url: 'https://figma.com/',
category: 'design'
},
{
site: 'Stackoverflow',
icon: 'stackoverflow',
url: 'https://stackoverflow.com/',
category: 'development'
},
{
site: 'Stackexchange',
icon: 'stackexchange',
url: 'https://stackexchange.com/',
category: 'development'
},
{
site: 'Superuser',
icon: 'superuser',
url: 'https://superuser.com/',
category: 'development'
},
{
site: 'Calendar',
icon: 'calendar',
url: 'https://calendar.google.com/',
category: 'social'
},
{
site: 'Messenger',
icon: 'messenger',
url: 'https://messenger.com/',
category: 'social'
},
{
site: 'Icons8',
icon: 'icons8',
url: 'https://icons8.com/',
category: 'design'
},
{
site: 'Markdown Cheatsheet',
icon: 'markdown',
url: 'https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet/',
category: 'development'
},
{
site: 'Interneting is Hard',
icon: 'interneting-is-hard',
url: 'https://internetingishard.com/',
category: 'development'
},
{
site: 'Keycode',
icon: 'keycode',
url: 'https://keycode.info/',
category: 'development'
},
{
site: 'Soundcloud',
icon: 'soundcloud',
url: 'https://soundcloud.com/',
category: 'media'
},
{
site: 'Amazon',
icon: 'amazon',
url: 'https://amazon.com/',
category: 'shop'
},
{
site: 'Flaticon',
icon: 'flaticon',
url: 'https://flaticon.com/',
category: 'design'
},
{
site: 'Wikimedia Commons',
icon: 'commons',
url: 'https://commons.wikimedia.org/',
category: 'design'
},
{
site: 'MEGA',
icon: 'mega',
url: 'https://mega.nz/',
category: 'cloud'
},
{
site: 'MDN Web Docs',
icon: 'mdn',
url: 'https://developer.mozilla.org/',
category: 'development'
}
];
return webSites;
}
getDockSites = () => {
// Dock
// A list of websites that will be generated and put on the dock
const dockSites = [
{
site: 'Reddit',
icon: 'reddit',
url: 'https://reddit.com/'
},
{
site: 'Github',
icon: 'github',
url: 'https://github.com/'
},
{
site: 'Facebook',
icon: 'facebook',
url: 'https://facebook.com/'
},
{
site: 'Gmail',
icon: 'gmail',
url: 'https://mail.google.com/'
},
{
site: 'Youtube',
icon: 'youtube',
url: 'https://youtube.com/'
},
{
site: 'GDrive',
icon: 'gdrive',
url: 'https://drive.google.com/'
},
{
site: 'Twitter',
icon: 'twitter',
url: 'https://twitter.com/'
},
{
site: 'Material.io',
icon: 'materialio',
url: 'https://material.io/'
}
];
return dockSites;
}
}

114
js/dashboard.js Normal file
View File

@ -0,0 +1,114 @@
class Dashboard {
constructor() {
this._dashboard = document.querySelector('#rightDashboard');
this._dashboardOverlay = document.querySelector('#dashboardOverlay');
this.rightDashboardVisibility = false;
this._dashboardOverlayMouseUpEvent = this._dashboardOverlayMouseUpEvent.bind(this);
this._centeredBox = document.querySelector('#centeredBox');
this._webMenu = document.querySelector('#webMenu');
this._searchBoxContainer = document.querySelector('#searchBoxContainer');
this._weatherScreen = document.querySelector('#weatherScreen');
this._registerOverlayMouseUpEvent();
}
_disableDashboardInputs = (status) => {
const elems = this._dashboard.getElementsByTagName('input');
const len = elems.length;
for (let i = 0; i < len; i++) {
elems[i].disabled = status;
}
}
getRightDashboardVisibility = () => {
return this.rightDashboardVisibility;
}
showDashboard = () => {
this._dashboard.classList.add('showRightDashboard');
// Show overlay
this._dashboardOverlay.classList.add('showDashboardOverlay');
// Enable Inputs
this._disableDashboardInputs(false);
this.rightDashboardVisibility = !this.rightDashboardVisibility;
}
hideDashboard = () => {
this._dashboard.classList.remove('showRightDashboard');
this._dashboard.scrollTop = 0;
// Disable Inputs
this._disableDashboardInputs(true);
// Hide overlay
this._dashboardOverlay.classList.remove('showDashboardOverlay');
this.rightDashboardVisibility = !this.rightDashboardVisibility;
}
toggleDashboard = () => {
console.log('toggle dashboard');
if (this.rightDashboardVisibility) {
// Hide dashboard
this.hideDashboard();
} else {
// Show dashboard
this.showDashboard();
// If centered box is hidden, open it
if (this._centeredBox.classList.contains('hiddenBox')) {
console.log('centered box is hidden, reopening...');
// Rotate profile container
profileImage.rotateProfile();
// Toggle center box
centeredBox.toggleCenteredBox();
}
}
// Check if any of these are open, if yes, close it
if (this._searchBoxContainer.classList.contains('showSearchBox')) {
console.log('searchbox is open, closing...');
searchBoxShow.hideSearchBox();
} else if (this._webMenu.classList.contains('showWebMenu')) {
console.log('web menu is open, closing...');
webMenu.hideWebMenu();
return;
} else if (this._weatherScreen.classList.contains('showWeatherScreen')) {
console.log('weather screen is open, closing...');
weatherScreen.hideWeatherScreen();
return;
}
}
_dashboardOverlayMouseUpEvent = e => {
if (this.rightDashboardVisibility) {
this.toggleDashboard();
}
console.log('dashboard overlay clicked...');
}
_registerOverlayMouseUpEvent = () => {
this._dashboardOverlay.addEventListener('mouseup', this._dashboardOverlayMouseUpEvent);
}
}

View File

@ -1,97 +1,124 @@
let dock = document.getElementById('dock');
// Generate button from user
const generateFromManual = (id, icon, callback) => {
let customButtonCallback;
const dockButton = document.createElement('div');
dockButton.id = 'button' + id;
dockButton.className = 'dockButton';
class DockButtons {
dockButton.onmouseup = callback;
const buttonImage = document.createElement('div');
buttonImage.id = 'buttonImage' + id;
buttonImage.className = 'dockButtonImage';
buttonImage.style.background = "url('assets/buttons/" + icon + ".svg')";
buttonImage.style.backgroundSize = 'cover';
constructor() {
this._dock = document.querySelector('#dock');
// Retrieve dockSites object from Config instance
this.dockSites = config.getDockSites();
// Populate dock
this._populateDock();
}
dockButton.appendChild(buttonImage);
dock.appendChild(dockButton);
}
_buildDockButton = (id, className, callback = null) => {
// Generate buttons from array
const generateFromList = () => {
for (let i = 0; i < (dockSites.length); i++) {
const site = dockSites[i].site;
const icon = dockSites[i].icon;
const url = dockSites[i].url;
// Create a href
const aDock = document.createElement('a');
aDock.className = 'dockLink';
aDock.href = url;
// Create div container
const dockButton = document.createElement('div');
dockButton.id = 'button' + i;
dockButton.id = `button${id}`;
dockButton.className = 'dockButton';
dockButton.onmouseup = callback;
return dockButton;
}
_buildDockButtonImage = (id, className, background) => {
// Create div container for button icon
const buttonImage = document.createElement('div');
buttonImage.id = 'buttonImage' + i;
buttonImage.className = 'dockButtonImage';
buttonImage.style.background = "url('assets/webcons/" + icon + ".svg')";
buttonImage.id = id;
buttonImage.className = className;
buttonImage.style.background = background;
buttonImage.style.backgroundSize = 'cover';
// Append divs
dockButton.appendChild(buttonImage);
aDock.appendChild(dockButton);
dock.appendChild(aDock);
};
}
const populateDock = () => {
// Create launcher button
generateFromManual(
'Launch',
'launch',
() => {
// Toggle web menu
toggleWebMenu();
}
);
return buttonImage;
}
// Create dock buttons fetched from sites-list.js
generateFromList();
_generateFromManual = (id, icon, callback) => {
// Create weather button
generateFromManual(
'Weather',
'weather',
() => {
// Toggle weather screen
toggleWeatherScreen();
}
);
const dockButton = this._buildDockButton(
`button${id}`,
'dockButton',
callback
);
// Create menu button
generateFromManual(
'Dashboard',
'dashboard',
() => {
// Toggle dashboard
toggleDashboard();
}
);
const buttonImage = this._buildDockButtonImage(
`buttonImage${id}`,
'dockButtonImage',
`url('assets/buttons/${icon}.svg')`
);
dockButton.appendChild(buttonImage);
this._dock.appendChild(dockButton);
}
_generateFromList = () => {
for (let i = 0; i < (this.dockSites.length); i++) {
const site = this.dockSites[i].site;
const icon = this.dockSites[i].icon;
const url = this.dockSites[i].url;
// Create a href
const aDock = document.createElement('a');
aDock.className = 'dockLink';
aDock.href = url;
// Create div container
const dockButton = this._buildDockButton(
site,
'dockButton'
);
// Create div container for button icon
const buttonImage = this._buildDockButtonImage(
`buttonImage${i}`,
'dockButtonImage',
`url('assets/webcons/${icon}.svg')`
);
// Append divs
dockButton.appendChild(buttonImage);
aDock.appendChild(dockButton);
this._dock.appendChild(aDock);
};
}
_populateDock = () => {
// Create launcher button
this._generateFromManual(
'Launch',
'launch',
() => {
// Toggle web menu
webMenu.toggleWebMenu();
}
);
// Create dock buttons fetched from sites-list.js
this._generateFromList();
// Create weather button
this._generateFromManual(
'Weather',
'weather',
() => {
// Toggle weather screen
weatherScreen.toggleWeatherScreen();
}
);
// Create menu button
this._generateFromManual(
'Dashboard',
'dashboard',
() => {
// Toggle dashboard
dashboard.toggleDashboard();
}
);
}
}
// Populate dock
window.onload = populateDock();

View File

@ -1,53 +1,67 @@
const greeterMessage = document.getElementById("greeterMessage");
const dateMessage = document.getElementById("dateMessage");
const date = new Date();
const hour = date.getHours();
let greeterSuffix;
class GreeterDateMessage {
constructor() {
this._greeterMessage = document.querySelector('#greeterMessage');
this._dateMessage = document.querySelector('#dateMessage');
const monthsArr = [
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
];
const daysArr = [
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday"
]
const getDayOrdinal = (day) => {
return day + (day > 0 ? ['th', 'st', 'nd', 'rd'][(day > 3 && day < 21) ||
day % 10 > 3 ? 0 : day % 10] : '');
}
const updateGreeterDateMessage = () => {
if (hour >= 6 && hour < 12) {
greeterSuffix = "Morning";
} else if (hour >= 12 && hour < 18) {
greeterSuffix = "Afternoon";
} else {
greeterSuffix = "Evening";
this._updateGreeterDateMessage();
}
greeterMessage.innerHTML = "Good" + "<br>" + greeterSuffix + "!";
_getMonths = () => {
const monthsArr = [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December'
];
return monthsArr;
}
dateMessage.innerHTML = "Today is the " + getDayOrdinal(date.getDate()) +
" of " + monthsArr[date.getMonth()] + ", and it's " + daysArr[date.getDay()] + ".";
}
_getDays = () => {
const _daysArr = [
'Sunday',
'Monday',
'Tuesday',
'Wednesday',
'Thursday',
'Friday',
'Saturday'
];
return _daysArr;
}
window.onload = updateGreeterDateMessage();
_getDayOrdinal = (day) => {
return day + (day > 0 ? ['th', 'st', 'nd', 'rd'][(day > 3 && day < 21) ||
day % 10 > 3 ? 0 : day % 10] : '');
}
_updateGreeterDateMessage = () => {
const date = new Date();
const hour = date.getHours();
let greeterSuffix = '';
if (hour >= 6 && hour < 12) {
greeterSuffix = 'Morning';
} else if (hour >= 12 && hour < 18) {
greeterSuffix = 'Afternoon';
} else {
greeterSuffix = 'Evening';
}
this._greeterMessage.innerHTML = `Good<br>${greeterSuffix}!`;
this._dateMessage.innerHTML = `Today's the ${this._getDayOrdinal(date.getDate())} of ` +
`${this._getMonths()[date.getMonth()]}, and it's ${this._getDays()[date.getDay()]}.`;
}
}

View File

@ -1,81 +1,109 @@
let keysPressed = {};
class KeyBinding {
document.addEventListener(
'keydown',
(event) => {
keysPressed[event.key] = true;
constructor() {
// Open dashboard
if (keysPressed['Alt'] && event.key === 's') {
event.preventDefault();
toggleDashboard();
this._searchBox = document.querySelector('#searchBox');
this._keysPressed = {};
this._documentAddKeyDownEvent = this._documentAddKeyDownEvent.bind(this);
this._documentAddKeyUpEvent = this._documentAddKeyUpEvent.bind(this);
this._registerDocumentAddKeyDownEvent();
this._registerDocumentAddKeyUpEvent();
}
_documentAddKeyDownEvent = e => {
const searchBoxVisibility = searchBoxShow.getSearchBoxVisibility();
this._keysPressed[e.key] = true;
if (this._keysPressed['Alt'] && e.key === 's') {
e.preventDefault();
dashboard.toggleDashboard();
return;
} else if (keysPressed['Alt'] && event.key === 'e') {
event.preventDefault();
toggleWebMenu();
} else if (this._keysPressed['Alt'] && e.key === 'e') {
e.preventDefault();
webMenu.toggleWebMenu();
return;
} else if (keysPressed['Alt'] && event.key === 'x') {
event.preventDefault();
toggleWeatherScreen();
} else if (this._keysPressed['Alt'] && e.key === 'x') {
e.preventDefault();
weatherScreen.toggleWeatherScreen();
return;
}
if (event.key === 'Escape') {
if (e.key === 'Escape') {
event.preventDefault();
e.preventDefault();
// If any of this are open, close it
if (searchBoxVisility) {
if (searchBoxVisibility) {
// Hide searchbox
toggleSearchBox();
searchBox.value = '';
searchBoxShow.toggleSearchBox();
this._searchBox.value = '';
return;
} else if (weatherScreenVisibility) {
} else if (dashboard.getRightDashboardVisibility()) {
toggleWeatherScreen();
// Hide dashboard
dashboard.toggleDashboard();
return;
} else if (weatherScreen.getWeatherScreenVisiblity()) {
// Hide weather
weatherScreen.toggleWeatherScreen();
return;
} else if (rightDashboardVisibility) {
toggleDashboard();
return;
}
// Show web menu
toggleWebMenu();
webMenu.toggleWebMenu();
return;
}
if (searchBoxVisility === false) {
if (searchBoxVisibility === false) {
// Don't show searchbox when web menu, dashboard
// and weather screen is open
if (webMenuVisibility || weatherScreenVisibility ||
rightDashboardVisibility) return;
if (dashboard.getRightDashboardVisibility() ||
webMenu.getwebMenuVisibility() ||
weatherScreen.getWeatherScreenVisiblity()) return;
// Only accept single charactered key and backspace to open search box
if ((event.key.length > 1) && (event.key !== 'Backspace')) return;
if ((e.key.length > 1) && (e.key !== 'Backspace')) return;
// Open searchbox
toggleSearchBox();
searchBoxShow.toggleSearchBox();
} else {
// Backspacing while there's no search query will hide searhbox
// Will also hide if you hit enter
if ((event.key === 'Backspace' || event.key === 'Enter') &&
searchBox.value < 1) { toggleSearchBox(); return; };
if ((e.key === 'Backspace' || e.key === 'Enter') &&
this._searchBox.value < 1) { searchBoxShow.toggleSearchBox(); return; };
}
}
);
document.addEventListener(
'keyup',
(event) => {
delete keysPressed[event.key];
}
);
_documentAddKeyUpEvent = e => {
delete this._keysPressed[e.key];
}
_registerDocumentAddKeyDownEvent = () => {
document.addEventListener('keydown', this._documentAddKeyDownEvent);
}
_registerDocumentAddKeyUpEvent = () => {
document.addEventListener('keyup', this._documentAddKeyUpEvent);
}
}

View File

@ -1,65 +1,80 @@
// Swipe Callbacks
class SwipeEventCallbacks extends SwipeEventManager {
constructor() {
super();
this.swipeEvent = this.swipeEvent;
// Backgound body swipe callback
const bodyBackgroundSwipeEvent = (el, d) => {
this._createSwipeEvents();
}
// Swipe left will open dashboard
if (d === 'left') {
toggleDashboard();
} else if (d === 'down') {
// Swiping down will open search box
toggleSearchBox();
} else if (d == 'right') {
// Swiping right will open web menu
toggleWebMenu();
} else if (d == 'up') {
// Swiping up will open weather screen
toggleWeatherScreen();
// Backgound body swipe callback
_bodyBackgroundSwipeEvent = (el, d) => {
// Swipe left will open dashboard
if (d === 'left') {
dashboard.toggleDashboard();
} else if (d === 'down') {
// Swiping down will open search box
searchBoxShow.toggleSearchBox();
} else if (d == 'right') {
// Swiping right will open web menu
webMenu.toggleWebMenu();
} else if (d == 'up') {
// Swiping up will open weather screen
weatherScreen.toggleWeatherScreen();
}
}
// Dashboard swipe callback
_rightDashboardSwipeEvent = (el, d) => {
// Swipe right will close dashboard
if (d === "right") {
dashboard.toggleDashboard();
}
}
// Blur overlay swipe event
_centeredBoxOverlaySwipeEvent = (el, d) => {
// Swiping up will close search box
if (d === 'up') {
searchBoxShow.toggleSearchBox();
}
}
// Web menu swipe event
_webMenuSwipeEvent = (el, d) => {
// Swiping left will close web menu
if (d == 'left') {
webMenu.toggleWebMenu();
}
}
// Weather screen swipe event
_weatherScreenSwipeEvent = (el, d) => {
// Swiping left will the weather screem
if (d == 'left') {
weatherScreen.toggleWeatherScreen();
}
}
// Assign swipe callback for each IDs
_createSwipeEvents = () => {
this.swipeEvent('bodyBackground', this._bodyBackgroundSwipeEvent);
this.swipeEvent('rightDashboard', this._rightDashboardSwipeEvent);
this.swipeEvent('centeredBoxOverlay', this._centeredBoxOverlaySwipeEvent);
this.swipeEvent('webMenu', this._webMenuSwipeEvent);
this.swipeEvent('weatherScreen', this._weatherScreenSwipeEvent);
}
}
// Dashboard swipe callback
const rightDashboardSwipeEvent = (el, d) => {
// Swipe right will close dashboard
if (d === "right") {
toggleDashboard();
}
}
// Blur overlay swipe event
const centeredBoxOverlaySwipeEvent = (el, d) => {
// Swiping up will close search box
if (d === 'up') {
toggleSearchBox();
}
}
// Web menu swipe event
const webMenuSwipeEvent = (el, d) => {
// Swiping left will close web menu
if (d == 'left') {
toggleWebMenu();
}
}
// Weather screen swipe event
const weatherScreenSwipeEvent = (el, d) => {
// Swiping left will the weather screem
if (d == 'left') {
toggleWeatherScreen();
}
}
swipeEvent('bodyBackground', bodyBackgroundSwipeEvent);
swipeEvent('rightDashboard', rightDashboardSwipeEvent);
swipeEvent('centeredBoxOverlay', centeredBoxOverlaySwipeEvent);
swipeEvent('webMenu', webMenuSwipeEvent);
swipeEvent('weatherScreen', weatherScreenSwipeEvent);

View File

@ -1,61 +1,71 @@
const swipeEvent = (elementID, callback) => {
class SwipeEventManager {
const el = document.getElementById(elementID);
let dir;
constructor() {
this.swipeEvent = this.swipeEvent.bind(this);
el.addEventListener(
'touchstart',
(event) => {
// event.preventDefault();
xDown = event.touches[0].clientX;
yDown = event.touches[0].clientY;
},
{ passive: true }
);
this._xDown = null;
this._yDown = null;
}
el.addEventListener(
'touchmove',
(event) => {
// event.preventDefault();
if ( ! xDown || ! yDown ) {
return;
}
swipeEvent = (elementID, callback) => {
const xUp = event.touches[0].clientX;
const yUp = event.touches[0].clientY;
const xDiff = xDown - xUp;
const yDiff = yDown - yUp;
const el = document.getElementById(elementID);
let dir;
if ( Math.abs( xDiff ) > Math.abs( yDiff ) ) {
if ( xDiff > 0 ) {
// Left Swipe
dir = 'left'
} else {
// Right Swipe
dir = 'right';
}
} else {
el.addEventListener(
'touchstart',
(event) => {
// event.preventDefault();
this._xDown = event.touches[0].clientX;
this._yDown = event.touches[0].clientY;
},
{ passive: true }
);
if ( yDiff > 0 ) {
// Up Swipe
dir = 'up';
} else {
// Down Swipe
dir = 'down';
}
}
/* Reset values */
xDown = null;
yDown = null;
if (dir !== ""){
if (typeof callback == "function") {
callback(el, dir);
el.addEventListener(
'touchmove',
(event) => {
// event.preventDefault();
if ( ! this._xDown || ! this._yDown ) {
return;
}
}
},
{ passive: true }
);
}
const xUp = event.touches[0].clientX;
const yUp = event.touches[0].clientY;
const xDiff = this._xDown - xUp;
const yDiff = this._yDown - yUp;
if ( Math.abs( xDiff ) > Math.abs( yDiff ) ) {
if ( xDiff > 0 ) {
// Left Swipe
dir = 'left'
} else {
// Right Swipe
dir = 'right';
}
} else {
if ( yDiff > 0 ) {
// Up Swipe
dir = 'up';
} else {
// Down Swipe
dir = 'down';
}
}
/* Reset values */
this._xDown = null;
this._yDown = null;
if (dir !== ''){
if (typeof callback == 'function') {
callback(el, dir);
}
}
},
{ passive: true }
);
}
}

63
js/profile-image.js Normal file
View File

@ -0,0 +1,63 @@
class ProfileImage {
constructor() {
this._profileContainer = document.querySelector('#profileImageContainer')
this._profileAnimRunning = false;
// Don't run animation on startup
this._profileContainer.style.webkitAnimationPlayState = 'paused';
this.rotateProfile = this.rotateProfile.bind(this);
this._animationEndEvent = this._animationEndEvent.bind(this);
this._onClickEvent = this._onClickEvent.bind(this);
this.getProfileAnimationStatus = this.getProfileAnimationStatus.bind(this);
this._registerAnimationEndEvent();
this._registerOnClickEvent();
}
rotateProfile = () => {
event.preventDefault;
// Remove anim class
this._profileContainer.classList.remove('rotateProfileAnim');
// Triggering reflow
void this._profileContainer.offsetWidth;
// Re-add animation class
this._profileContainer.classList.add('rotateProfileAnim');
// Start rotation animation
this._profileContainer.style.webkitAnimationPlayState = 'running';
this._profileAnimRunning = true;
}
_animationEndEvent = e => {
this._profileAnimRunning = false;
}
// Re-enable animation after death
_registerAnimationEndEvent = () => {
this._profileContainer.addEventListener('animationend', this._animationEndEvent);
}
_onClickEvent = e => {
if (this._profileAnimRunning) return;
searchBoxShow.toggleSearchBox();
}
_registerOnClickEvent = () => {
this._profileContainer.onclick = this._onClickEvent;
}
getProfileAnimationStatus = () => {
return this._profileAnimRunning;
}
}

56
js/script.js Normal file
View File

@ -0,0 +1,56 @@
// Instantiate config
const config = new Config();
// Instantiate background setter
const bodyBackground = new BodyBackground();
// Instantiate a clock object
const clock = new Clock();
// Instantiate dock buttons
const dockButtons = new DockButtons();
// Instantiate profile image/animation
const profileImage = new ProfileImage();
// Instantiate searchbox events
const searchBoxShow = new SearchBoxShow();
// Instantiate autosuggestion
const autoSuggestion = new AutoSuggestion();
// Instantiate search engine settings
const searchEngineSettings = new SearchEngineSettings();
// Instantiate center box
const centeredBox = new CenteredBox();
// Instantiate web menu
const webMenu = new WebMenu();
// Instantiate weather screen
const weatherScreen = new WeatherScreen();
// Instantiate weather settings
const weatherSettings = new WeatherSettings();
// Instantiate greeter message
const greeter = new GreeterDateMessage();
// Instantiate search send
const searchQuerySend = new SearchQuerySend();
// Instantiate theme engine
const themeEngine = new ThemeEngine();
// Instantiate dasbhoard
const dashboard = new Dashboard();
// Instantiate keybindings
const keyBindings = new KeyBinding();
// Instantiate swipe event
const swipeEventManager = new SwipeEventManager();
// Intantiate swipe event callbacks
const swipeEventCallbacks = new SwipeEventCallbacks();

View File

@ -1,69 +1,90 @@
var localStorage = window.localStorage;
class SearchEngineSettings {
var searchBox = document.getElementById("searchBox");
const selectEngine = document.getElementById("searchEngineSelect");
const searchEngineAsDefault = document.getElementById("searchEngineAsDefault");
constructor() {
this._localStorage = window.localStorage;
// Get default search engine
let defaultEngine = localStorage.getItem('searchEngine') || 'google';
this._searchBox = document.querySelector('#searchBox');
this._selectSearchEngine = document.querySelector('#searchEngineSelect');
this._selectSearchEngineApply = document.querySelector('#searchEngineAsDefault');
this._defaultSearchEngine = this._localStorage.getItem('searchEngine') || 'google';
this._placeholderPrefix = ' Search with ';
this._searchQueryPrefix = 'http://www.google.com/search?q=';
let searchQueryPrefix;
this._onClickEvent = this._onClickEvent.bind(this);
this._onChangeEvent = this._onChangeEvent.bind(this);
const placeholderPrefix = " Search with ";
// Update query string and placeholder
const selectQueryString = () => {
if (defaultEngine === "google") {
searchQueryPrefix = 'http://www.google.com/search?q=';
searchBox.placeholder = placeholderPrefix + "Google";
} else if (defaultEngine === "duckduckgo") {
searchQueryPrefix = 'https://duckduckgo.com/?q=';
searchBox.placeholder = placeholderPrefix + "Duckduckgo";
} else if (defaultEngine === "ecosia") {
searchQueryPrefix = 'https://www.ecosia.org/search?q=';
searchBox.placeholder = placeholderPrefix + "Ecosia";
} else if (defaultEngine === "yahoo") {
searchQueryPrefix = 'http://search.yahoo.com/search?p=';
searchBox.placeholder = placeholderPrefix + "Yahoo";
} else if (defaultEngine === "bing") {
searchQueryPrefix = 'https://www.bing.com/search?q=';
searchBox.placeholder = placeholderPrefix + "Bing";
} else {
searchQueryPrefix = 'http://www.google.com/search?q=';
searchBox.placeholder = placeholderPrefix + "Google";
this._init();
}
}
_init = () => {
this._selectQueryString();
this._selectTheEngine();
this._registerOnChangeEvent();
this._registerOnClickEvent();
}
// Use this to select the default search engine on startup
const selectTheEngine = () => {
// Available values: google, duckduckgo, ecosia, etc.
selectEngine.value = defaultEngine;
selectQueryString();
}
// Update query string and placeholder
_selectQueryString = () => {
// Update settings if the value changes
selectEngine.onchange = () => {
// Get Value
const selectedEngine = selectEngine.options[selectEngine.selectedIndex].value;
defaultEngine = selectedEngine;
selectTheEngine()
}
if (this._defaultSearchEngine === 'google') {
this._searchQueryPrefix = 'http://www.google.com/search?q=';
this._searchBox.placeholder = this._placeholderPrefix + 'Google';
searchEngineAsDefault.onclick = () => {
const selectCurrentIndex = selectEngine.options[selectEngine.selectedIndex]
alert('Success! ' + selectCurrentIndex.text +
' is now your default search engine!');
} else if (this._defaultSearchEngine === 'duckduckgo') {
this._searchQueryPrefix = 'https://duckduckgo.com/?q=';
this._searchBox.placeholder = this._placeholderPrefix + 'Duckduckgo';
// Save search engine
localStorage.setItem('searchEngine', selectCurrentIndex.value);
}
} else if (this._defaultSearchEngine === 'ecosia') {
this._searchQueryPrefix = 'https://www.ecosia.org/search?q=';
this._searchBox.placeholder = this._placeholderPrefix + 'Ecosia';
// Initialize
window.onload = selectTheEngine();
} else if (this._defaultSearchEngine === 'yahoo') {
this._searchQueryPrefix = 'http://search.yahoo.com/search?p=';
this._searchBox.placeholder = this._placeholderPrefix + 'Yahoo';
} else if (this._defaultSearchEngine === 'bing') {
this._searchQueryPrefix = 'https://www.bing.com/search?q=';
this._searchBox.placeholder = this._placeholderPrefix + 'Bing';
} else {
this._searchQueryPrefix = 'http://www.google.com/search?q=';
this._searchBox.placeholder = this._placeholderPrefix + 'Google';
}
}
_getSearchQueryPrefix = () => {
return this._searchQueryPrefix;
}
// Use this to select the default search engine on startup
_selectTheEngine = () => {
// Available values: google, duckduckgo, ecosia, etc.
this._selectSearchEngine.value = this._defaultSearchEngine;
this._selectQueryString();
}
_onChangeEvent = e => {
const selectedEngine = this._selectSearchEngine.options[this._selectSearchEngine.selectedIndex].value;
this._defaultSearchEngine = selectedEngine;
this._selectTheEngine()
}
_registerOnChangeEvent = () => {
this._selectSearchEngine.onchange = this._onChangeEvent;
}
_onClickEvent = e => {
const selectCurrentIndex = this._selectSearchEngine.options[this._selectSearchEngine.selectedIndex]
alert('Success! ' + selectCurrentIndex.text +
' is now your default search engine!');
// Save search engine
this._localStorage.setItem('searchEngine', selectCurrentIndex.value);
}
_registerOnClickEvent = () => {
this._selectSearchEngineApply.onclick = this._onClickEvent;
}
}

View File

@ -1,17 +1,18 @@
// Search box
var searchBox = document.getElementById("searchBox");
class SearchQuerySend extends SearchEngineSettings {
// Web Search
const webSearch = () => {
// Search
window.location.href = encodeURI(searchQueryPrefix + searchBox.value);
};
constructor() {
super();
this._searchBox = document.querySelector('#searchBox');
this._keyUpEvent = this._keyUpEvent.bind(this);
this._registerKeyUpEvent();
}
// Key release event
searchBox.addEventListener(
"keyup",
(event) => {
_sendQuery = () => {
// Search
window.location.href = encodeURI(this._getSearchQueryPrefix() + this._searchBox.value);
};
_keyUpEvent = event => {
if (event.key === 'Tab') return;
// Number 13 is the "Enter" key on the keyboard
@ -26,8 +27,11 @@ searchBox.addEventListener(
event.preventDefault();
// Search the web
webSearch()
this._sendQuery()
};
}
);
_registerKeyUpEvent = () => {
this._searchBox.addEventListener('keyup', this._keyUpEvent);
}
}

View File

@ -1,52 +1,69 @@
var searchBox = document.getElementById('searchBox');
const searchBoxContainer = document.getElementById('searchBoxContainer');
const centeredBoxOverlay = document.getElementById('centeredBoxOverlay');
class SearchBoxShow {
constructor() {
let searchBoxVisility = false;
this._searchBox = document.querySelector('#searchBox');
this._searchBoxContainer = document.querySelector('#searchBoxContainer');
this._centeredBoxOverlay = document.querySelector('#centeredBoxOverlay');
const showSearchBox = () => {
searchBoxContainer.classList.add('showSearchBox');
this._searchBoxVisility = false;
// Focus
searchBox.focus();
searchBoxVisility = !searchBoxVisility;
// Toggle overlay
centeredBoxOverlay.classList.toggle('showOverlay');
}
const hideSearchBox = () => {
searchBoxContainer.classList.remove('showSearchBox');
// Toggle overlay
centeredBoxOverlay.classList.toggle('showOverlay');
searchBox.value = '';
// Hide suggestions
hideSuggestions();
searchBoxVisility = !searchBoxVisility;
}
const toggleSearchBox = () => {
// If profile anim is still running,
// Return to avoid spam
if (profileAnimRunning) return;
// Rotate profile
rotateProfile();
if (searchBoxVisility) {
// Hide search box
hideSearchBox();
} else {
// Show search box
showSearchBox();
this.showSearchBox = this.showSearchBox.bind(this);
this.hideSearchBox = this.hideSearchBox.bind(this);
this.toggleSearchBox = this.toggleSearchBox.bind(this);
}
console.log('toggle searchbox');
}
getSearchBoxVisibility = () => {
return this._searchBoxVisility;
}
showSearchBox = () => {
this._searchBoxContainer.classList.add('showSearchBox');
// Focus
this._searchBox.focus();
this._searchBoxVisility = !this._searchBoxVisility;
// Toggle overlay
this._centeredBoxOverlay.classList.toggle('showOverlay');
}
hideSearchBox = () => {
this._searchBoxContainer.classList.remove('showSearchBox');
// Toggle overlay
this._centeredBoxOverlay.classList.toggle('showOverlay');
this._searchBox.value = '';
// Hide suggestions
console.warn('hideSuggestions()');
this._searchBoxVisility = !this._searchBoxVisility;
}
toggleSearchBox = () => {
// If profile anim is still running,
// Return to avoid spam
if (profileImage.getProfileAnimationStatus()) return;
// Rotate profile
profileImage.rotateProfile();
if (this._searchBoxVisility) {
// Hide search box
this.hideSearchBox();
} else {
// Show search box
this.showSearchBox();
}
console.log('toggle searchbox');
}
}

View File

@ -1,309 +0,0 @@
// You can easily add data here and it will be auto generated
// Web menu
// A list of websites that will be generated and put on the web menu
const webSites = [
{
site: 'Reddit',
icon: 'reddit',
url: 'https://reddit.com/',
category: 'social'
},
{
site: 'Github',
icon: 'github',
url: 'https://github.com/',
category: 'development'
},
{
site: 'Facebook',
icon: 'facebook',
url: 'https://facebook.com/',
category: 'social'
},
{
site: 'Gmail',
icon: 'gmail',
url: 'https://mail.google.com/',
category: 'social'
},
{
site: 'Youtube',
icon: 'youtube',
url: 'https://youtube.com/',
category: 'media'
},
{
site: 'GDrive',
icon: 'gdrive',
url: 'https://drive.google.com/',
category: 'cloud'
},
{
site: 'Twitter',
icon: 'twitter',
url: 'https://twitter.com/',
category: 'social'
},
{
site: 'Instagram',
icon: 'instagram',
url: 'https://instagram.com/',
category: 'social'
},
{
site: 'Bitbucket',
icon: 'bitbucket',
url: 'https://bitbucket.org/',
category: 'development'
},
{
site: 'Gitlab',
icon: 'gitlab',
url: 'https://gitlab.com/',
category: 'development'
},
{
site: 'Deviantart',
icon: 'deviantart',
url: 'https://deviantart.com/',
category: 'design'
},
{
site: 'Duckduckgo',
icon: 'duckduckgo',
url: 'https://duckduckgo.com/',
category: 'development'
},
{
site: 'Ecosia',
icon: 'ecosia',
url: 'https://ecosia.org/',
category: 'search engine'
},
{
site: 'Google',
icon: 'google',
url: 'https://google.com/',
category: 'search engine'
},
{
site: 'Wikipedia',
icon: 'wikipedia',
url: 'https://wikipedia.org/',
category: 'information'
},
{
site: 'Unsplash',
icon: 'unsplash',
url: 'https://unsplash.com/',
category: 'design'
},
{
site: 'Twitch',
icon: 'twitch',
url: 'https://twitch.tv/',
category: 'media'
},
{
site: 'Yahoo',
icon: 'yahoo',
url: 'https://mail.yahoo.com/',
category: 'social'
},
{
site: 'Material.io',
icon: 'materialio',
url: 'https://material.io/',
category: 'design'
},
{
site: 'Netflix',
icon: 'netflix',
url: 'https://netflix.com/',
category: 'media'
},
{
site: 'Office 365',
icon: 'office365',
url: 'https://office.com/',
category: 'information'
},
{
site: '4chan',
icon: '4chan',
url: 'https://4chan.org/',
category: 'social'
},
{
site: 'Discord',
icon: 'discord',
url: 'https://discord.com/',
category: 'social'
},
{
site: 'Spotify',
icon: 'spotify',
url: 'https://spotify.com/',
category: 'media'
},
{
site: 'Ebay',
icon: 'ebay',
url: 'https://ebay.com/',
category: 'shop'
},
{
site: 'JSFiddle',
icon: 'jsfiddle',
url: 'https://jsfiddle.net/',
category: 'development'
},
{
site: 'ArchWiki',
icon: 'archwiki',
url: 'https://wiki.archlinux.org/',
category: 'information'
},
{
site: 'Figma',
icon: 'figma',
url: 'https://figma.com/',
category: 'design'
},
{
site: 'Stackoverflow',
icon: 'stackoverflow',
url: 'https://stackoverflow.com/',
category: 'development'
},
{
site: 'Stackexchange',
icon: 'stackexchange',
url: 'https://stackexchange.com/',
category: 'development'
},
{
site: 'Superuser',
icon: 'superuser',
url: 'https://superuser.com/',
category: 'development'
},
{
site: 'Calendar',
icon: 'calendar',
url: 'https://calendar.google.com/',
category: 'social'
},
{
site: 'Messenger',
icon: 'messenger',
url: 'https://messenger.com/',
category: 'social'
},
{
site: 'Icons8',
icon: 'icons8',
url: 'https://icons8.com/',
category: 'design'
},
{
site: 'Markdown Cheatsheet',
icon: 'markdown',
url: 'https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet/',
category: 'development'
},
{
site: 'Interneting is Hard',
icon: 'interneting-is-hard',
url: 'https://internetingishard.com/',
category: 'development'
},
{
site: 'Keycode',
icon: 'keycode',
url: 'https://keycode.info/',
category: 'development'
},
{
site: 'Soundcloud',
icon: 'soundcloud',
url: 'https://soundcloud.com/',
category: 'media'
},
{
site: 'Amazon',
icon: 'amazon',
url: 'https://amazon.com/',
category: 'shop'
},
{
site: 'Flaticon',
icon: 'flaticon',
url: 'https://flaticon.com/',
category: 'design'
},
{
site: 'Wikimedia Commons',
icon: 'commons',
url: 'https://commons.wikimedia.org/',
category: 'design'
},
{
site: 'MEGA',
icon: 'mega',
url: 'https://mega.nz/',
category: 'cloud'
},
{
site: 'MDN Web Docs',
icon: 'mdn',
url: 'https://developer.mozilla.org/',
category: 'development'
}
];
// Dock
// A list of websites that will be generated and put on the dock
const dockSites = [
{
site: 'Reddit',
icon: 'reddit',
url: 'https://reddit.com/'
},
{
site: 'Github',
icon: 'github',
url: 'https://github.com/'
},
{
site: 'Facebook',
icon: 'facebook',
url: 'https://facebook.com/'
},
{
site: 'Gmail',
icon: 'gmail',
url: 'https://mail.google.com/'
},
{
site: 'Youtube',
icon: 'youtube',
url: 'https://youtube.com/'
},
{
site: 'GDrive',
icon: 'gdrive',
url: 'https://drive.google.com/'
},
{
site: 'Twitter',
icon: 'twitter',
url: 'https://twitter.com/'
},
{
site: 'Material.io',
icon: 'materialio',
url: 'https://material.io/'
}
];

View File

@ -1,210 +1,213 @@
var localStorage = window.localStorage;
class ThemeEngine {
constructor() {
this._localStorage = window.localStorage;
const backgroundTextBox = document.getElementById('backgroundSet');
const backgroundOpacityTextBox = document.getElementById('backgroundOpacitySet');
const foregroundTextBox = document.getElementById('foregroundSet');
const foregroundOpacityTextBox = document.getElementById('foregroundOpacitySet');
this._backgroundTextBox = document.querySelector('#backgroundSet');
this._backgroundOpacityTextBox = document.querySelector('#backgroundOpacitySet');
this._foregroundTextBox = document.querySelector('#foregroundSet');
this._foregroundOpacityTextBox = document.querySelector('#foregroundOpacitySet');
const blurTextBox = document.getElementById('blurSet');
this._blurTextBox = document.querySelector('#blurSet');
this._applyTheme = document.querySelector('#themeEngineAsDefault');
this._resetTheme = document.querySelector('#themeEngineReset');
const applyTheme = document.getElementById('themeEngineAsDefault');
const resetTheme = document.getElementById('themeEngineReset');
// Save CSS color constiables default in localStorage
// Will only save if you visit the webpage for the very first time
const saveDefaultCSS = () => {
const origBaseBG = localStorage.getItem('origBaseBG');
const origBaseColor = localStorage.getItem('origBaseColor');
const origBlurStrength = localStorage.getItem('origBlurStrength');
if ((origBaseBG === null) || (origBaseColor === null) || (origBlurStrength) === null) {
localStorage.setItem(
'origBaseBG',
window.getComputedStyle(document.documentElement).getPropertyValue('--base-bg')
);
localStorage.setItem(
'origBaseColor',
window.getComputedStyle(document.documentElement).getPropertyValue('--base-color')
);
localStorage.setItem(
'origBlurStrength',
window.getComputedStyle(document.documentElement).getPropertyValue('--blur-strength')
);
this._init();
}
}
// Check color validity
const checkColorValidity = (colorStr) => {
_saveDefaultCSS = () => {
// Check if RGBA - (#RRGGBBAA)
const colorRGBA = /^#[0-9A-F]{8}$/i.test(colorStr);
// If not RGBA
if (!colorRGBA) {
// If RGB - (#RRGGBB)
if (/^#([0-9A-F]{3}){1,2}$/i.test(colorStr)) {
// Add completely opaque alpha
return colorStr + 'FF';
const origBaseBG = this._localStorage.getItem('origBaseBG');
const origBaseColor = this._localStorage.getItem('origBaseColor');
const origBlurStrength = this._localStorage.getItem('origBlurStrength');
// If three-charactered HEX color - (#RGB)
} else if (/^#([0-9A-F]{3}){1,2}$/i.test(colorStr)) {
if ((origBaseBG === null) || (origBaseColor === null) || (origBlurStrength) === null) {
// Convert it to RRGGBB
return colorStr.replace(/^#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])/, "#$1$1$2$2$3$3");
// If three-charactered HEX Color(#RGB) with AA - (#RGBAA)
} else if (colorStr.length == 6) {
const bg = colorStr.slice(0, -2);
const op = colorStr.slice(-2);
return bg.replace(/^#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])/, "#$1$1$2$2$3$3") + op;
} else {
alert('Invalid color');
this._localStorage.setItem(
'origBaseBG',
window.getComputedStyle(document.documentElement).getPropertyValue('--base-bg')
);
this._localStorage.setItem(
'origBaseColor',
window.getComputedStyle(document.documentElement).getPropertyValue('--base-color')
);
this._localStorage.setItem(
'origBlurStrength',
window.getComputedStyle(document.documentElement).getPropertyValue('--blur-strength')
);
}
}
// It's RGBA and a valid color so just return it
return colorStr;
}
_checkColorValidity = colorStr => {
// Update textboxes
const updateTextBoxValues = (bgColor, bgOpacity, fgColor, fgOpacity, blurPower) => {
// Set placeholders
backgroundTextBox.value = '';
backgroundTextBox.placeholder = bgColor;
// Check if RGBA - (#RRGGBBAA)
const colorRGBA = /^#[0-9A-F]{8}$/i.test(colorStr);
backgroundOpacityTextBox.value = '';
backgroundOpacityTextBox.placeholder = bgOpacity;
// If not RGBA
if (!colorRGBA) {
foregroundTextBox.value = '';
foregroundTextBox.placeholder = fgColor;
foregroundOpacityTextBox.value = '';
foregroundOpacityTextBox.placeholder = fgOpacity;
// If RGB - (#RRGGBB)
if (/^#([0-9A-F]{3}){1,2}$/i.test(colorStr)) {
// Add completely opaque alpha
return colorStr + 'FF';
// If three-charactered HEX color - (#RGB)
} else if (/^#([0-9A-F]{3}){1,2}$/i.test(colorStr)) {
blurTextBox.value = '';
blurTextBox.placeholder = blurPower;
}
// Convert it to RRGGBB
return colorStr.replace(/^#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])/, '#$1$1$2$2$3$3');
// Theme processing
const processTheme = () => {
// If three-charactered HEX Color(#RGB) with AA - (#RGBAA)
} else if (colorStr.length == 6) {
// Retrieve custom colors
let baseBG = localStorage.getItem('baseBG');
let baseColor = localStorage.getItem('baseColor');
let blurStrength = localStorage.getItem('blurStrength');
const bg = colorStr.slice(0, -2);
const op = colorStr.slice(-2);
// If custom color doesn't exist, use the value in CSS
if (baseBG === null) {
baseBG = localStorage.getItem('origBaseBG');
return bg.replace(/^#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])/, '#$1$1$2$2$3$3') + op;
} else {
alert('Invalid color');
}
}
// It's RGBA and a valid color so just return it
return colorStr;
}
if (baseColor === null) {
baseColor = localStorage.getItem('origBaseColor');
_updateTextBoxValues = (bgColor, bgOpacity, fgColor, fgOpacity, blurPower) => {
// Set placeholders
this._backgroundTextBox.value = '';
this._backgroundTextBox.placeholder = bgColor;
this._backgroundOpacityTextBox.value = '';
this._backgroundOpacityTextBox.placeholder = bgOpacity;
this._foregroundTextBox.value = '';
this._foregroundTextBox.placeholder = fgColor;
this._foregroundOpacityTextBox.value = '';
this._foregroundOpacityTextBox.placeholder = fgOpacity;
this._blurTextBox.value = '';
this._blurTextBox.placeholder = blurPower;
}
if (blurStrength === null) {
blurStrength = localStorage.getItem('origBlurStrength');
_processTheme = () => {
// Retrieve custom colors
let baseBG = this._localStorage.getItem('baseBG');
let baseColor = this._localStorage.getItem('baseColor');
let blurStrength = this._localStorage.getItem('blurStrength');
// If custom color doesn't exist, use the value in CSS
if (baseBG === null) {
baseBG = this._localStorage.getItem('origBaseBG');
}
if (baseColor === null) {
baseColor = this._localStorage.getItem('origBaseColor');
}
if (blurStrength === null) {
blurStrength = this._localStorage.getItem('origBlurStrength');
}
// Remove whitespace
baseBG = baseBG.replace(/ /g,'');
baseColor = baseColor.replace(/ /g,'');
blurStrength = blurStrength.replace(/ /g,'');
// Check validity
baseBG = this._checkColorValidity(baseBG);
baseColor = this._checkColorValidity(baseColor);
// Slice to separate RGB and A of background color
// Slice alpha out
const backgroundColor = baseBG.slice(0, -2);
// Get alpha
const backgroundOpacity = baseBG.slice(-2);
// Slice to separate RGB and A of foreground color
// Slice alpha out
const foregroundColor = baseColor.slice(0, -2);
// Get alpha
const foregroundOpacity = baseColor.slice(-2);
this._updateTextBoxValues(
backgroundColor,
backgroundOpacity,
foregroundColor,
foregroundOpacity,
blurStrength
)
}
// Remove whitespace
baseBG = baseBG.replace(/ /g,'');
baseColor = baseColor.replace(/ /g,'');
blurStrength = blurStrength.replace(/ /g,'');
_updateCSSconstiables = () => {
// Check validity
baseBG = checkColorValidity(baseBG);
baseColor = checkColorValidity(baseColor);
// Get value from input fields
const background = (this._backgroundTextBox.value || this._backgroundTextBox.placeholder) +
(this._backgroundOpacityTextBox.value || this._backgroundOpacityTextBox.placeholder);
// Slice to separate RGB and A of background color
// Slice alpha out
const backgroundColor = baseBG.slice(0, -2);
// Get alpha
const backgroundOpacity = baseBG.slice(-2);
const foreground = (this._foregroundTextBox.value || this._foregroundTextBox.placeholder) +
(this._foregroundOpacityTextBox.value || this._foregroundOpacityTextBox.placeholder);
const blurPower = (this._blurTextBox.value || this._blurTextBox.placeholder);
// Check color validity
const bgColor = this._checkColorValidity(background);
const fgColor = this._checkColorValidity(foreground);
// Slice to separate RGB and A of foreground color
// Slice alpha out
const foregroundColor = baseColor.slice(0, -2);
// Get alpha
const foregroundOpacity = baseColor.slice(-2);
// Change CSS colors
document.documentElement.style.setProperty('--base-bg', bgColor);
document.documentElement.style.setProperty('--base-color', fgColor);
document.documentElement.style.setProperty('--blur-strength', blurPower);
updateTextBoxValues(
backgroundColor,
backgroundOpacity,
foregroundColor,
foregroundOpacity,
blurStrength
)
}
// Save custom color
this._localStorage.setItem('baseBG', bgColor);
this._localStorage.setItem('baseColor', fgColor);
this._localStorage.setItem('blurStrength', blurPower);
// Update colors
const updateCSSconstiables = () => {
this._processTheme();
}
// Get value from input fields
const background = (backgroundTextBox.value || backgroundTextBox.placeholder) +
(backgroundOpacityTextBox.value || backgroundOpacityTextBox.placeholder);
_applyOnClickEvent = e => {
this._updateCSSconstiables();
alert('Success!');
}
const foreground = (foregroundTextBox.value || foregroundTextBox.placeholder) +
(foregroundOpacityTextBox.value || foregroundOpacityTextBox.placeholder);
const blurPower = (blurTextBox.value || blurTextBox.placeholder);
_registerApplyOnClickEvent = () => {
this._applyTheme.onclick = this._applyOnClickEvent;
}
// Check color validity
const bgColor = checkColorValidity(background);
const fgColor = checkColorValidity(foreground);
_resetOnClickEvent = e => {
this._localStorage.removeItem('baseBG');
this._localStorage.removeItem('baseColor');
this._localStorage.removeItem('blurStrength');
// Change CSS colors
document.documentElement.style.setProperty('--base-bg', bgColor);
document.documentElement.style.setProperty('--base-color', fgColor);
document.documentElement.style.setProperty('--blur-strength', blurPower);
this._saveDefaultCSS();
this._processTheme();
this._updateCSSconstiables();
alert('Success!');
}
// Save custom color
localStorage.setItem('baseBG', bgColor);
localStorage.setItem('baseColor', fgColor);
localStorage.setItem('blurStrength', blurPower);
_registerResetOnClickEvent = () => {
this._resetTheme.onclick = this._resetOnClickEvent;
}
processTheme();
}
_init = () => {
// Run on window onload
const updateOnStartUp = () => {
// Update
processTheme();
this._saveDefaultCSS();
// Update settings
updateCSSconstiables();
}
// Update
this._processTheme();
// Update settings
this._updateCSSconstiables();
// Apply button event handler
applyTheme.onclick = () => {
updateCSSconstiables();
alert('Success!');
}
this._registerApplyOnClickEvent();
this._registerResetOnClickEvent();
}
// Reset button event handler
resetTheme.onclick = () => {
localStorage.removeItem('baseBG');
localStorage.removeItem('baseColor');
localStorage.removeItem('blurStrength');
saveDefaultCSS();
processTheme();
updateCSSconstiables();
alert('Success!');
}
// Initialize
const onStartUp = () => {
saveDefaultCSS();
updateOnStartUp();
}
// Call Initialize
window.onload = onStartUp();
}

View File

@ -1,278 +1,288 @@
const weatherScreen = document.getElementById("weatherScreen");
class WeatherScreen {
let weatherScreenVisibility = false;
constructor() {
this._weatherScreenVisibility = false;
this._tempSymbol = '°C';
const weatherIcon = document.getElementById("weatherTodayIcon");
const weatherLocation = document.getElementById("weatherTodayLocation");
const weatherDescription = document.getElementById("weatherTodayDescription");
this._weatherScreen = document.querySelector('#weatherScreen');
this._weatherIcon = document.querySelector('#weatherTodayIcon');
this._weatherLocation = document.querySelector('#weatherTodayLocation');
this._weatherDescription = document.querySelector('#weatherTodayDescription');
this._sunriseHour = document.querySelector('#sunriseTodayHour');
this._sunsetHour = document.querySelector('#sunsetTodayHour');
this._updateHour = document.querySelector('#updateTodayHour');
this._weatherDockImageButton = document.querySelector('#buttonImageWeather');
this._forecastContainer = document.querySelector('#forecastContainer');
const sunriseHour = document.getElementById("sunriseTodayHour");
const sunsetHour = document.getElementById("sunsetTodayHour");
const updateHour = document.getElementById("updateTodayHour")
const weatherDockImageButton = document.getElementById("buttonImageWeather");
const forecastContainer = document.getElementById("forecastContainer");
const formatUnixTime = unix => {
const date = new Date(unix*1000);
const hour = date.getHours();
const minutes = "0" + date.getMinutes();
const formattedTime = hour + ':' + minutes.substr(-2);
return formattedTime;
}
const getWeatherIcon = code => {
const icon_tbl = {
'01d': 'sun_icon.svg',
'01n': 'moon_icon.svg',
'02d': 'dfew_clouds.svg',
'02n': 'nfew_clouds.svg',
'03d': 'dscattered_clouds.svg',
'03n': 'nscattered_clouds.svg',
'04d': 'dbroken_clouds.svg',
'04n': 'nbroken_clouds.svg',
'09d': 'dshower_rain.svg',
'09n': 'nshower_rain.svg',
'10d': 'd_rain.svg',
'10n': 'n_rain.svg',
'11d': 'dthunderstorm.svg',
'11n': 'nthunderstorm.svg',
'13d': 'snow.svg',
'13n': 'snow.svg',
'50d': 'dmist.svg',
'50n': 'nmist.svg'
};
return icon_tbl[code];
}
const updateWeatherDockButton = icon => {
weatherDockImageButton.style.background = "url('assets/weather-icons/" + icon + "')";
weatherDockImageButton.style.backgroundSize = "cover";
}
const setWeatherValue = (loc, desc, icon, sunr, suns, updt) => {
const temp_symbol = (units === "metric") ? "°C" : "°F";
weatherLocation.innerHTML = loc;
weatherDescription.innerHTML = desc + temp_symbol;
weatherIcon.style.background = "url('assets/weather-icons/" + icon + "')";
weatherIcon.style.backgroundSize = "cover";
sunriseHour.innerHTML = sunr;
sunsetHour.innerHTML = suns;
updateHour.innerHTML = updt;
// Update weather button on dock
updateWeatherDockButton(icon);
}
const createForecastBody = (fIcon, forecastTemp, foreDescription, fHour, fDate) => {
// Main Div
const forecastDay = document.createElement('div');
forecastDay.className = 'weatherForecastDay';
// Icon Container Div
const forecastIconContainer = document.createElement('div');
forecastIconContainer.className = 'weatherForecastDayIconContainer';
// Icon Div
const forecastIcon = document.createElement('div');
forecastIcon.className = 'weatherForecastDayIcon';
forecastIcon.style.background = "url('assets/weather-icons/" + fIcon + "')";
forecastIcon.style.backgroundSize = 'cover';
// Details Div
const forecastDetails = document.createElement('div');
forecastDetails.className = 'weatherForecastDayDetails';
const forecastTemperature = document.createElement('div');
forecastTemperature.className = 'weatherForecastDayDetailsTemperature';
forecastTemperature.innerHTML = forecastTemp;
const forecastDescription = document.createElement('div');
forecastDescription.className = 'weatherForecastDayDetailsDescription';
forecastDescription.innerHTML = foreDescription;
// Append details to div container
forecastDetails.appendChild(forecastTemperature);
forecastDetails.appendChild(forecastDescription);
// Date Div
const forecastDayDate = document.createElement('div');
forecastDayDate.className = 'weatherForecastDayDate';
const forecastHour = document.createElement('div');
forecastHour.className = 'weatherForecastDayDateHour';
forecastHour.innerHTML = fHour;
const forecastDate = document.createElement('div');
forecastDate.className = 'weatherForecastDayDateDate';
forecastDate.innerHTML = fDate;
// Append icon image to div container
forecastIconContainer.appendChild(forecastIcon);
// Append details to div container
forecastDayDate.appendChild(forecastHour);
forecastDayDate.appendChild(forecastDate);
// Append to main div
forecastDay.appendChild(forecastIconContainer);
forecastDay.appendChild(forecastDetails);
forecastDay.appendChild(forecastDayDate);
// Append to the main container
forecastContainer.appendChild(forecastDay);
}
const setErrValue = () => {
const wLoc = "Earth, Milky Way";
const wDesc = "dust & clouds, -1000";
const wIcon = "weather-error.svg";
const time = "00:00";
setWeatherValue(wLoc, wDesc, wIcon, time, time, time);
}
// Process weather data
const processWeatherData = (data) => {
const cityName = data.name;
const countryName = data.sys.country;
const weatherDescription = data.weather[0].description;
const weatherIcon = data.weather[0].icon;
const weatherTemp = Math.floor(data.main.temp);
const sunRise = data.sys.sunrise;
const sunSet = data.sys.sunset;
const update = data.dt;
const wLoc = cityName + ", " + countryName;
let wDesc = weatherDescription + ", " + weatherTemp;
// Capitalize first word
wDesc = wDesc && wDesc[0].toUpperCase() + wDesc.slice(1)
const wIcon = getWeatherIcon(weatherIcon);
const rise = formatUnixTime(sunRise);
const set = formatUnixTime(sunSet);
const upd = formatUnixTime(update);
setWeatherValue(wLoc, wDesc, wIcon, rise, set, upd);
}
// This will be called in weather-settings
const getWeatherData = (appID, cityID, units) => {
requestString = "https://api.openweathermap.org/data/2.5/weather?APPID=" + appID + "&id=" + cityID + "&units=" + units;
const request = new XMLHttpRequest();
request.open("GET", requestString, true);
request.onload = e => {
if (request.readyState === 4 && request.status === 200 && request.status < 400) {
processWeatherData(JSON.parse(request.response));
} else {
setErrValue();
};
};
request.send();
};
// Fetch forecast
const getForecastData = (appID, cityID, units) => {
requestString = "https://api.openweathermap.org/data/2.5/forecast?APPID=" + appID + "&id=" + cityID + "&units=" + units;
request = new XMLHttpRequest();
request.open("GET", requestString, true);
request.onload = e => {
if (request.readyState === 4 && request.status === 200 && request.status < 400) {
processForecastData(JSON.parse(request.response));
} else {
setErrValue();
};
};
request.send();
}
// Process forecast data
const processForecastData = data => {
// Empty forecast container to avoid duplication
forecastContainer.innerHTML = '';
const forecast = data.list;
for (let i = 8; i < forecast.length; i+=8) {
const temp_symbol = (units === "metric") ? "°C" : "°F";
const foreIcon = forecast[i].weather[0].icon;
const minimumTemp = forecast[i].main.temp_min;
const maximumTemp = forecast[i].main.temp_max;
const foreDescription = forecast[i].weather[0].description;
const dateTime = forecast[i].dt_txt;
const fIcon = getWeatherIcon(foreIcon);
const minTemp = Math.floor(minimumTemp);
const maxTemp = Math.floor(maximumTemp);
const forecastTemp = minTemp + ' ~ ' + maxTemp + temp_symbol;
const fHour = dateTime.substr(dateTime.indexOf(' ') + 1).slice(0, -3);;
const fDate = dateTime.substr(0, dateTime.indexOf(' '));
createForecastBody(fIcon, forecastTemp, foreDescription, fHour, fDate);
this._webMenu = document.querySelector('#webMenu');
this._dashboard = document.querySelector('#rightDashboard');
this._searchBoxContainer = document.querySelector('#searchBoxContainer');
}
}
const showWeatherScreen = () => {
weatherScreen.classList.add('showWeatherScreen');
weatherScreenVisibility = !weatherScreenVisibility;
}
_formatUnixTime = unix => {
const date = new Date(unix*1000);
const hour = date.getHours();
const minutes = '0' + date.getMinutes();
const formattedTime = hour + ':' + minutes.substr(-2);
const hideWeatherScreen = () => {
weatherScreen.classList.remove('showWeatherScreen');
weatherScreenVisibility = !weatherScreenVisibility;
}
return formattedTime;
}
const toggleWeatherScreen = () => {
getWeatherScreenVisiblity = () => {
return this._weatherScreenVisibility;
}
console.log('toggle weather screen');
_getWeatherIcon = code => {
const icon_tbl = {
'01d': 'sun_icon.svg',
'01n': 'moon_icon.svg',
'02d': 'dfew_clouds.svg',
'02n': 'nfew_clouds.svg',
'03d': 'dscattered_clouds.svg',
'03n': 'nscattered_clouds.svg',
'04d': 'dbroken_clouds.svg',
'04n': 'nbroken_clouds.svg',
'09d': 'dshower_rain.svg',
'09n': 'nshower_rain.svg',
'10d': 'd_rain.svg',
'10n': 'n_rain.svg',
'11d': 'dthunderstorm.svg',
'11n': 'nthunderstorm.svg',
'13d': 'snow.svg',
'13n': 'snow.svg',
'50d': 'dmist.svg',
'50n': 'nmist.svg'
};
// If profile anim is still running,
// Return to avoid spam
if (profileAnimRunning) return;
return icon_tbl[code];
}
// Rotate profile
rotateProfile();
_updateWeatherDockButton = icon => {
this._weatherDockImageButton.style.background = `url('assets/weather-icons/${icon}')`;
this._weatherDockImageButton.style.backgroundSize = 'cover';
}
if (weatherScreenVisibility) {
// Hide search box
hideWeatherScreen();
_setWeatherValue = (loc, desc, icon, sunr, suns, updt) => {
this._weatherLocation.innerHTML = loc;
this._weatherDescription.innerHTML = desc + this._tempSymbol;
} else {
// Show search box
showWeatherScreen();
}
this._weatherIcon.style.background = `url('assets/weather-icons/${icon}')`;
this._weatherIcon.style.backgroundSize = 'cover';
// Check if any of these are open, if yes, close it
if (webMenu.classList.contains('showWebMenu')) {
console.log('web menu is open, closing...');
hideWebMenu();
return;
this._sunriseHour.innerHTML = sunr;
this._sunsetHour.innerHTML = suns;
this._updateHour.innerHTML = updt;
} else if (searchBoxContainer.classList.contains('showSearchBox')) {
console.log('searchbox is open, closing...');
hideSearchBox();
} else if (dashboard.classList.contains('showRightDashboard')) {
console.log('dashboard is open, closing...');
hideDashboard();
// return;
}
// Update weather button on dock
this._updateWeatherDockButton(icon);
}
_createForecastBody = (fIcon, forecastTemp, foreDescription, fHour, fDate) => {
// Main Div
const forecastDay = document.createElement('div');
forecastDay.className = 'weatherForecastDay';
// Icon Container Div
const forecastIconContainer = document.createElement('div');
forecastIconContainer.className = 'weatherForecastDayIconContainer';
// Icon Div
const forecastIcon = document.createElement('div');
forecastIcon.className = 'weatherForecastDayIcon';
forecastIcon.style.background = `url('assets/weather-icons/${fIcon}')`;
forecastIcon.style.backgroundSize = 'cover';
// Details Div
const forecastDetails = document.createElement('div');
forecastDetails.className = 'weatherForecastDayDetails';
const forecastTemperature = document.createElement('div');
forecastTemperature.className = 'weatherForecastDayDetailsTemperature';
forecastTemperature.innerHTML = forecastTemp;
const forecastDescription = document.createElement('div');
forecastDescription.className = 'weatherForecastDayDetailsDescription';
forecastDescription.innerHTML = foreDescription;
// Append details to div container
forecastDetails.appendChild(forecastTemperature);
forecastDetails.appendChild(forecastDescription);
// Date Div
const forecastDayDate = document.createElement('div');
forecastDayDate.className = 'weatherForecastDayDate';
const forecastHour = document.createElement('div');
forecastHour.className = 'weatherForecastDayDateHour';
forecastHour.innerHTML = fHour;
const forecastDate = document.createElement('div');
forecastDate.className = 'weatherForecastDayDateDate';
forecastDate.innerHTML = fDate;
// Append icon image to div container
forecastIconContainer.appendChild(forecastIcon);
// Append details to div container
forecastDayDate.appendChild(forecastHour);
forecastDayDate.appendChild(forecastDate);
// Append to main div
forecastDay.appendChild(forecastIconContainer);
forecastDay.appendChild(forecastDetails);
forecastDay.appendChild(forecastDayDate);
// Append to the main container
this._forecastContainer.appendChild(forecastDay);
}
_setErrValue = () => {
const wLoc = 'Earth, Milky Way';
const wDesc = 'dust & clouds, -1000';
const wIcon = 'weather-error.svg';
const time = '00:00';
this._setWeatherValue(wLoc, wDesc, wIcon, time, time, time);
}
_processWeatherData = (data) => {
const cityName = data.name;
const countryName = data.sys.country;
const weatherDescription = data.weather[0].description;
const weatherIcon = data.weather[0].icon;
const weatherTemp = Math.floor(data.main.temp);
const sunRise = data.sys.sunrise;
const sunSet = data.sys.sunset;
const update = data.dt;
const wLoc = cityName + ', ' + countryName;
let wDesc = weatherDescription + ', ' + weatherTemp;
wDesc = wDesc && wDesc[0].toUpperCase() + wDesc.slice(1)
const wIcon = this._getWeatherIcon(weatherIcon);
const rise = this._formatUnixTime(sunRise);
const set = this._formatUnixTime(sunSet);
const upd = this._formatUnixTime(update);
this._setWeatherValue(wLoc, wDesc, wIcon, rise, set, upd);
}
getWeatherData = (appID, cityID, units) => {
const requestString = `https://api.openweathermap.org/data/2.5/weather?APPID=${appID}&id=${cityID}&units=${units}`;
const request = new XMLHttpRequest();
request.open('GET', requestString, true);
request.onload = e => {
if (request.readyState === 4 && request.status === 200 && request.status < 400) {
this._processWeatherData(JSON.parse(request.response));
this._tempSymbol = (units === 'metric') ? '°C' : '°F';
} else {
this._setErrValue();
};
};
request.send();
};
getForecastData = (appID, cityID, units) => {
const requestString = `https://api.openweathermap.org/data/2.5/forecast?APPID=${appID}&id=${cityID}&units=${units}`;
const request = new XMLHttpRequest();
request.open('GET', requestString, true);
request.onload = e => {
if (request.readyState === 4 && request.status === 200 && request.status < 400) {
this._processForecastData(JSON.parse(request.response));
this._tempSymbol = (units === 'metric') ? '°C' : '°F';
} else {
this._setErrValue();
};
};
request.send();
}
_processForecastData = data => {
// Empty forecast container to avoid duplication
this._forecastContainer.innerHTML = '';
const forecast = data.list;
for (let i = 8; i < forecast.length; i+=8) {
const foreIcon = forecast[i].weather[0].icon;
const minimumTemp = forecast[i].main.temp_min;
const maximumTemp = forecast[i].main.temp_max;
const foreDescription = forecast[i].weather[0].description;
const dateTime = forecast[i].dt_txt;
const fIcon = this._getWeatherIcon(foreIcon);
const minTemp = Math.floor(minimumTemp);
const maxTemp = Math.floor(maximumTemp);
const forecastTemp = minTemp + ' ~ ' + maxTemp + this._tempSymbol;
const fHour = dateTime.substr(dateTime.indexOf(' ') + 1).slice(0, -3);;
const fDate = dateTime.substr(0, dateTime.indexOf(' '));
this._createForecastBody(fIcon, forecastTemp, foreDescription, fHour, fDate);
}
}
showWeatherScreen = () => {
this._weatherScreen.classList.add('showWeatherScreen');
this._weatherScreenVisibility = !this._weatherScreenVisibility;
}
hideWeatherScreen = () => {
this._weatherScreen.classList.remove('showWeatherScreen');
this._weatherScreenVisibility = !this._weatherScreenVisibility;
}
toggleWeatherScreen = () => {
console.log('toggle weather screen');
// If profile anim is still running,
// Return to avoid spam
if (profileImage.getProfileAnimationStatus()) return;
// Rotate profile
profileImage.rotateProfile();
if (this._weatherScreenVisibility) {
// Hide weather screen
this.hideWeatherScreen();
} else {
// Show weather screen
this.showWeatherScreen();
}
// Check if any of these are open, if yes, close it
if (this._webMenu.classList.contains('showWebMenu')) {
console.log('web menu is open, closing...');
webMenu.hideWebMenu();
return;
} else if (this._searchBoxContainer.classList.contains('showSearchBox')) {
console.log('searchbox is open, closing...');
hideSearchBox();
} else if (this._dashboard.classList.contains('showRightDashboard')) {
console.log('dashboard is open, closing...');
dashboard.hideDashboard();
// return;
}
// Toggle center box
centeredBox.toggleCenteredBox();
}
// Toggle center box
toggleCenteredBox();
}

View File

@ -1,76 +1,97 @@
// Set constiable
let appID, cityID, units;
class WeatherSettings {
// Input elements
constructor() {
// Textboxes
const apiBox = document.getElementById("apiBox");
const cityBox = document.getElementById("cityBox");
this._localStorage = window.localStorage;
this._appID = '';
this._cityID = '';
this._units = '';
// Select menu
const weatherSelectUnits = document.getElementById("weatherSelectUnits");
this._apiBox = document.querySelector('#apiBox');
this._cityBox = document.querySelector('#cityBox');
// Div buttons
const weatherSettingsReset = document.getElementById("weatherSettingsReset");
const weatherSettingsApply = document.getElementById("weatherSettingsApply");
this._weatherSelectUnits = document.querySelector('#weatherSelectUnits');
// Apply credentials
const applyWeatherSettings = (key, city, units) => {
localStorage.setItem('apiKey', key);
localStorage.setItem('cityID', city);
localStorage.setItem('units', units);
}
this._weatherSettingsReset = document.querySelector('#weatherSettingsReset');
this._weatherSettingsApply = document.querySelector('#weatherSettingsApply');
// Clear credentials
const resetWeatherSettings = () => {
localStorage.removeItem('apiKey');
localStorage.removeItem('cityID');
localStorage.removeItem('units');
}
this.getWeatherData = weatherScreen.getWeatherData;
this.getForecastData = weatherScreen.getForecastData;
// Update functions
const deleteWeatherSettingsValue = () => {
apiBox.value = '';
cityBox.value = '';
weatherSelectUnits.value = "metric";
}
this._init();
}
const updateWeatherSettingsPlaceholder = () => {
apiBox.placeholder = String(appID) || "API Key";
cityBox.placeholder = String(cityID) || "City ID";
weatherSelectUnits.value = String(units) || "metric";
}
// Apply credentials
_applyWeatherSettings = (key, city, units) => {
this._localStorage.setItem('apiKey', key);
this._localStorage.setItem('cityID', city);
this._localStorage.setItem('units', units);
}
const updateWeatherSettings = () => {
appID = localStorage.getItem('apiKey') || "API Key";
cityID = localStorage.getItem('cityID') || "City ID";
units = localStorage.getItem('units') || "metric";
// Clear credentials
_resetWeatherSettings = () => {
this._localStorage.removeItem('apiKey');
this._localStorage.removeItem('cityID');
this._localStorage.removeItem('units');
}
// Update weather forecast elements
getWeatherData(appID, cityID, units);
getForecastData(appID, cityID, units);
// Reset textboxes
_deleteWeatherSettingsValue = () => {
this._apiBox.value = '';
this._cityBox.value = '';
this._weatherSelectUnits.value = 'metric';
}
deleteWeatherSettingsValue();
updateWeatherSettingsPlaceholder();
}
// Update textbox placeholders
_updateWeatherSettingsPlaceholder = () => {
this._apiBox.placeholder = String(this._appID) || 'API Key';
this._cityBox.placeholder = String(this._cityID) || 'City ID';
this._weatherSelectUnits.value = String(this._units) || 'metric';
}
// Reset button was pressed
weatherSettingsReset.onclick = () => {
// Reset keys
resetWeatherSettings();
updateWeatherSettings();
alert('Credentials deleted!');
}
// Update weather settings
_updateWeatherSettings = () => {
this._appID = localStorage.getItem('apiKey') || 'API Key';
this._cityID = localStorage.getItem('cityID') || 'City ID';
this._units = localStorage.getItem('units') || 'metric';
// Apply settings
weatherSettingsApply.onclick = () => {
applyWeatherSettings(
apiBox.value || apiBox.placeholder,
cityBox.value || cityBox.placeholder,
weatherSelectUnits.options[weatherSelectUnits.selectedIndex].value
);
updateWeatherSettings();
alert('Successfully updated!');
}
// Update weather forecast elements
this.getWeatherData(this._appID, this._cityID, this._units);
this.getForecastData(this._appID, this._cityID, this._units);
window.onload = updateWeatherSettings();
this._deleteWeatherSettingsValue();
this._updateWeatherSettingsPlaceholder();
}
_weatherResetOnClickEvent = e => {
// Reset keys
this._resetWeatherSettings();
this._updateWeatherSettings();
alert('Credentials deleted!');
}
_registerWeatherResetOnClickEvent = () => {
this._weatherSettingsReset.onclick = this._weatherResetOnClickEvent;
}
_weatherApplyOnClickEvent = e => {
this._applyWeatherSettings(
this._apiBox.value || this._apiBox.placeholder,
this._cityBox.value || this._cityBox.placeholder,
this._weatherSelectUnits.options[this._weatherSelectUnits.selectedIndex].value
);
this._updateWeatherSettings();
alert('Successfully updated!');
}
_registerWeatherApplyOnClickEvent = () => {
this._weatherSettingsApply.onclick = this._weatherApplyOnClickEvent;
}
_init = () => {
this._updateWeatherSettings();
this._registerWeatherResetOnClickEvent();
this._registerWeatherApplyOnClickEvent();
}
}

View File

@ -1,405 +1,435 @@
const webMenu = document.getElementById("webMenu");
const webMenuList = document.getElementById("webMenuList");
const webMenuListContainer = document.getElementById("webMenuListContainer");
const webMenuSearchBox = document.getElementById("webMenuSearchBox");
class WebMenu {
var webMenuVisibility = false;
constructor() {
this._dashboard = document.querySelector('#rightDashboard');
this._weatherScreen = document.querySelector('#weatherScreen');
this._webSites = config.getWebSites();
let webItemFocus;
let webListIndex = 0;
this._webMenu = document.querySelector('#webMenu');
this._webMenuList = document.querySelector('#webMenuList');
this._webMenuListContainer = document.querySelector('#webMenuListContainer');
this._webMenuSearchBox = document.querySelector('#webMenuSearchBox');
// Disable/Enable inputs
const disableWebMenuInputs = (status) => {
const elems = webMenu.getElementsByTagName('input');
const len = elems.length;
this._webMenuVisibility = false;
for (let i = 0; i < len; i++) {
elems[i].disabled = status;
}
}
this._webItemFocus;
this._webListIndex = 0;
// Create mouse event for passed li
const createCallback = (li, url) => {
// Create a callback property for the passed li
li.callback = () => {
window.location.href = encodeURI(url);
}
}
// Sort list alphabetically
const sortList = () => {
Array.from(webMenuList.getElementsByTagName("li"))
.sort((a, b) => a.textContent.localeCompare(b.textContent))
.forEach(li => webMenuList.appendChild(li));
}
// Populate web menu
const populateWebMenu = () => {
// Generate a list
for (let webData of webSites) {
const site = webData.site;
const icon = webData.icon;
const url = webData.url;
const li = document.createElement('li');
// Add mouseup event
createCallback(li, url);
// Create a href
const aWebLink = document.createElement('a');
aWebLink.className = 'webMenuLink';
aWebLink.href = url;
aWebLink.tabIndex = '-1';
// Create an outer div, child of li
let webItemDiv = document.createElement('div')
webItemDiv.className = 'webItem';
// webItemDiv.tabitemIndex = '1';
webItemDiv.id = "id" + site;
// Create a second div, webItemContainer
const webItemContainer = document.createElement('div');
webItemContainer.className = 'webItemContainer';
// Create the innermost div, contains icon and label
const webItemBody = document.createElement('div');
webItemBody.className = 'webItemBody';
// Create div for webItemIcon
const webItemIconContainer = document.createElement('div');
webItemIconContainer.className = 'webItemIconContainer';
const webItemIcon = document.createElement('div');
webItemIcon.className = 'webItemIcon';
webItemIcon.style.background = "url('assets/webcons/" + icon + ".svg')";
webItemIcon.style.backgroundSize = 'cover';
// Create webItemName
const webItemName = document.createElement('div');
webItemName.className = 'webItemName';
webItemName.innerHTML = site;
// Append divs with heirarchy
webItemDiv.appendChild(webItemContainer);
webItemContainer.appendChild(webItemBody);
webItemIconContainer.appendChild(webItemIcon);
webItemBody.appendChild(webItemIconContainer);
webItemBody.appendChild(webItemName);
aWebLink.appendChild(webItemDiv);
li.appendChild(aWebLink);
webMenuList.appendChild(li);
this._fuzzySearch();
this._init();
}
// Call to sort list
sortList();
}
// Return web menu status
getwebMenuVisibility = () => {
return this._webMenuVisibility;
}
// Fuzzy search
String.prototype.fuzzy = function(term, ratio) {
const string = this.toLowerCase();
const compare = term.toLowerCase();
let matches = 0;
if (string.indexOf(compare) > -1) return true; // covers basic partial matches
for (let i = 0; i < compare.length; i++) {
string.indexOf(compare[i]) > -1 ? matches += 1 : matches -=1;
}
return (matches/this.length >= ratio || term == "");
};
// Disable textboxes
_disableWebMenuInputs = (status) => {
const elems = this._webMenu.getElementsByTagName('input');
const len = elems.length;
// Search through the list
const filterWebList = () => {
for (let i = 0; i < len; i++) {
elems[i].disabled = status;
}
}
let input, filter, ul, li, a, i, txtValue;
// Create callback property, to be used when enter was pressed while item is focused
_createWebItemCallback = (li, url) => {
// Create a callback property for the passed li
li.callback = () => {
window.location.href = encodeURI(url);
}
}
input = webMenuSearchBox;
filter = input.value.toUpperCase();
ul = webMenuList;
li = ul.getElementsByTagName('li');
// Loop through all list items, and focus if matches the search query
for (let i = 0; i < li.length; i++) {
// Sort list alphabetically
_sortList = () => {
Array.from(this._webMenuList.getElementsByTagName('li'))
.sort((a, b) => a.textContent.localeCompare(b.textContent))
.forEach(li => this._webMenuList.appendChild(li));
}
a = li[i].getElementsByClassName("webItemName")[0];
txtValue = a.innerHTML || a.textContent || a.innerText;
// Create/generate web items
_populateWebMenu = () => {
// If an item match, hightlight it and focus
// if (txtValue.toUpperCase().indexOf(filter) !== -1) {
if (txtValue.toUpperCase().fuzzy(filter, 1) === true) {
// Generate a list
for (let webData of this._webSites) {
const site = webData.site;
const icon = webData.icon;
const url = webData.url;
const li = document.createElement('li');
// Create callback property
this._createWebItemCallback(li, url);
// Create a href
const aWebLink = document.createElement('a');
aWebLink.className = 'webMenuLink';
aWebLink.href = url;
aWebLink.tabIndex = '-1';
// Create an outer div, child of li
let webItemDiv = document.createElement('div')
webItemDiv.className = 'webItem';
webItemDiv.id = 'id' + site;
// Unselect/Unhightlight old active
const oldWebItemFocus = webItemFocus;
const oldWebItemFocusChild = oldWebItemFocus.querySelector('.webItem');
oldWebItemFocusChild.classList.remove('webItemFocus');
// Create a second div, webItemContainer
const webItemContainer = document.createElement('div');
webItemContainer.className = 'webItemContainer';
// Update webItemFocus
webItemFocus = li[i];
// Create the innermost div, contains icon and label
const webItemBody = document.createElement('div');
webItemBody.className = 'webItemBody';
// Update weblistindex
webListIndex = i;
// Create div for webItemIcon
const webItemIconContainer = document.createElement('div');
webItemIconContainer.className = 'webItemIconContainer';
// Get child
const webItemFocusChild = webItemFocus.querySelector('.webItem');
// Add webItemFocus class to child
webItemFocusChild.classList.add('webItemFocus');
const webItemIcon = document.createElement('div');
webItemIcon.className = 'webItemIcon';
webItemIcon.style.background = `url('assets/webcons/${icon}.svg')`;
webItemIcon.style.backgroundSize = 'cover';
// Scroll focus into active
webItemFocus.scrollIntoView();
// Create webItemName
const webItemName = document.createElement('div');
webItemName.className = 'webItemName';
webItemName.innerHTML = site;
// Append divs with heirarchy
webItemDiv.appendChild(webItemContainer);
webItemContainer.appendChild(webItemBody);
webItemIconContainer.appendChild(webItemIcon);
webItemBody.appendChild(webItemIconContainer);
webItemBody.appendChild(webItemName);
aWebLink.appendChild(webItemDiv);
li.appendChild(aWebLink);
this._webMenuList.appendChild(li);
}
// Call to sort list
this._sortList();
}
}
// Reset focus on web menu close
const focusReset = () => {
const oldWebItemFocus = webItemFocus;
const oldWebItemFocusChild = oldWebItemFocus.querySelector('.webItem');
oldWebItemFocusChild.classList.remove('webItemFocus');
webListIndex = 0;
}
// Allow fuzzy searching in web menu
_fuzzySearch = () => {
String.prototype.fuzzy = function(term, ratio) {
const string = this.toLowerCase();
const compare = term.toLowerCase();
let matches = 0;
// Covers basic partial matches
if (string.indexOf(compare) > -1) return true;
for (let i = 0; i < compare.length; i++) {
string.indexOf(compare[i]) > -1 ? matches += 1 : matches -=1;
}
return ((matches / this.length) >= ratio || term == '');
};
}
// Get first item of ul
const getFirstItem = () => {
const ul = webMenuList;
const li = ul.getElementsByTagName('li');
// Focus on searched item
_filterWebList = () => {
// Focus on first item
webItemFocus = li[0];
// Get child
const webItemFocusChildren = webItemFocus.querySelector('.webItem');
// Add webItemFocus class
webItemFocusChildren.classList.add('webItemFocus');
}
const showWebMenu = () => {
webMenu.classList.add('showWebMenu');
// Enable inputs
disableWebMenuInputs(false);
webMenuVisibility = !webMenuVisibility;
// Focus to input field
webMenuSearchBox.focus();
}
const hideWebMenu = () => {
// Clear input field
webMenuSearchBox.value = '';
// Unfocus input field
webMenuSearchBox.blur();
// Refilter web list
filterWebList();
// Scroll to top
webMenuListContainer.scrollTop = 0;
// Reset focus item
focusReset();
// Get first item
getFirstItem();
webMenu.classList.remove('showWebMenu');
// Disable inputs
disableWebMenuInputs(true);
webMenuVisibility = !webMenuVisibility;
}
const toggleWebMenu = () => {
console.log('toggle web menu');
// If profile anim is still running,
// Return to avoid spam
if (profileAnimRunning) return;
// Rotate profile
rotateProfile();
if (webMenuVisibility) {
// Hide web menu
hideWebMenu();
} else {
// Show Web menu
showWebMenu();
}
// Check if any of these are open, if yes, close it
if (weatherScreen.classList.contains('showWeatherScreen')) {
console.log('weather screen is open, closing...');
hideWeatherScreen();
return;
} else if (searchBoxContainer.classList.contains('showSearchBox')) {
console.log('searchbox is open, closing...');
hideSearchBox();
} else if (dashboard.classList.contains('showRightDashboard')) {
console.log('dashboard is open, closing...');
hideDashboard();
}
// Toggle center box
toggleCenteredBox();
}
// Remove class to focused item
const removeClass = (el, className) => {
// Remove webItemFocus class
const oldWebItemFocus = el.querySelector('.webItem');
oldWebItemFocus.classList.remove('webItemFocus');
};
// Add class to focused item
const addClass = (el, className) => {
const webItemFocusChild = el.querySelector('.webItem');
// Add webItemFocus class to child
webItemFocusChild.classList.add('webItemFocus');
// Scroll focus into active
webItemFocusChild.scrollIntoView();
};
const navigateWithArrows = (key, len) => {
// assign constiables to key codes
const [right, left, down, up] = [39, 37, 40, 38];
const getIndexByWindowWidth = () => {
if (window.innerWidth <= 580) { return 1 }
// width of elements in pixels
const menuItemWidth = 138;
const scrollBarWidth = 10;
// viewport width
const vw = (unit) => window.innerWidth * (unit / 100);
let input, filter, ul, li, a, i, txtValue;
// Gets the number of columns by dividing the screen width minus the padding, scroll width and
// average of menu item width by the menu item width
const containerWindow = ((window.innerWidth - (menuItemWidth / 2) - scrollBarWidth - vw(24)) / menuItemWidth);
// Get rounded result
return Math.round(containerWindow);
}
input = webMenuSearchBox;
filter = input.value.toUpperCase();
ul = this._webMenuList;
li = ul.getElementsByTagName('li');
// Loop through all list items, and focus if matches the search query
for (let i = 0; i < li.length; i++) {
// Determine the index position by key
const changeWebListIndex = () => {
switch (key) {
case right:
webListIndex++;
// Clear web menu searchbox
webMenuSearchBox.value = '';
break;
case left:
webListIndex--;
// Clear web menu searchbox
webMenuSearchBox.value = '';
break;
case up:
webListIndex = webListIndex - getIndexByWindowWidth();
// Clear web menu searchbox
webMenuSearchBox.value = '';
break;
case down:
webListIndex = webListIndex + getIndexByWindowWidth();
// Clear web menu searchbox
webMenuSearchBox.value = '';
break;
a = li[i].getElementsByClassName('webItemName')[0];
txtValue = a.innerHTML || a.textContent || a.innerText;
// If an item match, hightlight it and focus
// if (txtValue.toUpperCase().indexOf(filter) !== -1) {
if (txtValue.toUpperCase().fuzzy(filter, 1) === true) {
// Unselect/Unhightlight old active
const oldWebItemFocus = this._webItemFocus;
const oldWebItemFocusChild = oldWebItemFocus.querySelector('.webItem');
oldWebItemFocusChild.classList.remove('webItemFocus');
// Update webItemFocus
this._webItemFocus = li[i];
// Update weblistindex
this._webListIndex = i;
// Get child
const webItemFocusChild = this._webItemFocus.querySelector('.webItem');
// Add webItemFocus class to child
webItemFocusChild.classList.add('webItemFocus');
// Scroll focus into active
this._webItemFocus.scrollIntoView();
}
}
}
const changeItemFocus = (condition, overFlowIndex) => {
const next = webMenuList.getElementsByTagName('li')[webListIndex];
if(typeof next !== undefined && condition) {
webItemFocus = next;
// Reset focus/go back to item #1
_focusReset = () => {
const oldWebItemFocus = this._webItemFocus;
const oldWebItemFocusChild = oldWebItemFocus.querySelector('.webItem');
oldWebItemFocusChild.classList.remove('webItemFocus');
this._webListIndex = 0;
}
// Get item #1
_getFirstItem = () => {
const ul = this._webMenuList;
const li = ul.getElementsByTagName('li');
// Focus on first item
this._webItemFocus = li[0];
// Get child
const webItemFocusChildren = this._webItemFocus.querySelector('.webItem');
// Add webItemFocus class
webItemFocusChildren.classList.add('webItemFocus');
}
// Show web menu screen
showWebMenu = () => {
this._webMenu.classList.add('showWebMenu');
// Enable inputs
this._disableWebMenuInputs(false);
this._webMenuVisibility = !this._webMenuVisibility;
// Focus to input field
this._webMenuSearchBox.focus();
}
// Hide web menu screen
hideWebMenu = () => {
// Clear input field
this._webMenuSearchBox.value = '';
// Unfocus input field
this._webMenuSearchBox.blur();
// Refilter web list
this._filterWebList();
// Scroll to top
this._webMenuListContainer.scrollTop = 0;
// Reset focus item
this._focusReset();
// Get first item
this._getFirstItem();
this._webMenu.classList.remove('showWebMenu');
// Disable inputs
this._disableWebMenuInputs(true);
this._webMenuVisibility = !this._webMenuVisibility;
}
// Toggle web menu screen
toggleWebMenu = () => {
console.log('toggle web menu');
// If profile anim is still running,
// Return to avoid spam
if (profileImage.getProfileAnimationStatus()) return;
// Rotate profile
profileImage.rotateProfile();
if (this._webMenuVisibility) {
// Hide web menu
this.hideWebMenu();
} else {
// Show Web menu
this.showWebMenu();
}
// Check if any of these are open, if yes, close it
if (searchBoxContainer.classList.contains('showSearchBox')) {
console.log('searchbox is open, closing...');
searchBoxShow.hideSearchBox();
} else if (this._dashboard.classList.contains('showRightDashboard')) {
console.log('dashboard is open, closing...');
dashboard.hideDashboard();
} else if (this._weatherScreen.classList.contains('showWeatherScreen')) {
console.log('weather screen is open, closing...');
weatherScreen.hideWeatherScreen();
return;
}
// Toggle center box
centeredBox.toggleCenteredBox();
}
// Remove focus class
_removeClass = (el, className) => {
// Remove webItemFocus class
const oldWebItemFocus = el.querySelector('.webItem');
oldWebItemFocus.classList.remove('webItemFocus');
}
// Add focus class
_addClass = (el, className) => {
const webItemFocusChild = el.querySelector('.webItem');
// Add webItemFocus class to child
webItemFocusChild.classList.add('webItemFocus');
// Scroll focus into active
webItemFocusChild.scrollIntoView();
}
// Arrow key navigation
_navigateWithArrows = (key, len) => {
// assign constiables to key codes
const [right, left, down, up] = [39, 37, 40, 38];
const getIndexByWindowWidth = () => {
if (window.innerWidth <= 580) { return 1; }
// width of elements in pixels
const menuItemWidth = 138;
const scrollBarWidth = 10;
// viewport width
const vw = (unit) => window.innerWidth * (unit / 100);
// Gets the number of columns by dividing the screen width minus the padding, scroll width and
// average of menu item width by the menu item width
const containerWindow = ((window.innerWidth - (menuItemWidth / 2) - scrollBarWidth - vw(24)) / menuItemWidth);
// Get rounded result
return Math.round(containerWindow);
}
// Determine the index position by key
const changeWebListIndex = () => {
switch (key) {
case right:
this._webListIndex++;
// Clear web menu searchbox
this._webMenuSearchBox.value = '';
break;
case left:
this._webListIndex--;
// Clear web menu searchbox
this._webMenuSearchBox.value = '';
break;
case up:
this._webListIndex = this._webListIndex - getIndexByWindowWidth();
// Clear web menu searchbox
this._webMenuSearchBox.value = '';
break;
case down:
this._webListIndex = this._webListIndex + getIndexByWindowWidth();
// Clear web menu searchbox
this._webMenuSearchBox.value = '';
break;
}
}
const changeItemFocus = (condition, overFlowIndex) => {
const next = this._webMenuList.getElementsByTagName('li')[this._webListIndex];
if(typeof next !== undefined && condition) {
this._webItemFocus = next;
} else {
this._webListIndex = overFlowIndex;
this._webItemFocus = this._webMenuList.getElementsByTagName('li')[overFlowIndex];
}
}
const changeItemFocusByKey = () => {
if (key === right) { return changeItemFocus((this._webListIndex <= len), 0) }
if (key === left) { return changeItemFocus((this._webListIndex >= 0), len) }
if (key === up) { return changeItemFocus((this._webListIndex >= 0), len) }
if (key === down) { return changeItemFocus((this._webListIndex <= len), 0) }
}
changeWebListIndex();
if (this._webItemFocus) {
this._removeClass(this._webItemFocus, 'webItemFocus');
changeItemFocusByKey();
this._addClass(this._webItemFocus, 'webItemFocus');
// console.log(webListIndex);
} else {
webListIndex = overFlowIndex;
webItemFocus = webMenuList.getElementsByTagName('li')[overFlowIndex];
this._webListIndex = 0;
this._webItemFocus = this._webMenuList.getElementsByTagName('li')[0];
this._addClass(this._webItemFocus, 'webItemFocus');
}
}
const changeItemFocusByKey = () => {
if (key === right) { return changeItemFocus((webListIndex <= len), 0) }
if (key === left) { return changeItemFocus((webListIndex >= 0), len) }
if (key === up) { return changeItemFocus((webListIndex >= 0), len) }
if (key === down) { return changeItemFocus((webListIndex <= len), 0) }
_webMenuKeyDownEvent = e => {
const len = this._webMenuList.getElementsByTagName('li').length - 1;
this._navigateWithArrows(e.which, len);
}
changeWebListIndex();
if (webItemFocus) {
removeClass(webItemFocus, 'webItemFocus');
changeItemFocusByKey();
addClass(webItemFocus, 'webItemFocus');
// console.log(webListIndex);
} else {
webListIndex = 0;
webItemFocus = webMenuList.getElementsByTagName('li')[0];
addClass(webItemFocus, 'webItemFocus');
}
}
// Keyboard navigation
webMenu.addEventListener(
'keydown',
(event) => {
const len = webMenuList.getElementsByTagName('li').length - 1;
navigateWithArrows(event.which, len);
},
false
);
// Type event on web mmenu search box
webMenuSearchBox.onkeydown = (event) => {
// Don't hijack keyboard navigation buttons (up, down, left, right)
if ((event.key === 'ArrowRight') || (event.key === 'ArrowDown') ||
(event.key === 'ArrowLeft') || (event.key === 'ArrowUp')) return;
if (event.key === 'Tab') return;
if (event.key === 'Enter' && webItemFocus) {
// Run the focused li's callback
webItemFocus.callback();
// Hide web menu
toggleWebMenu();
} else if (event.key === 'Backspace' && webMenuSearchBox.value.length < 1) {
// Hide web menu if backspace is pressed and searchbox value is 0
toggleWebMenu();
return;
} else if ((event.key === 'Escape') || (event.key === 'Alt')) {
// Ignore escape and alt key
return;
_registerWebMenuKeyDownEvent = () => {
this._webMenu.addEventListener('keydown', this._webMenuKeyDownEvent, false);
}
_webMenuSearchBoxKeyDownEvent = e => {
// Don't hijack keyboard navigation buttons (up, down, left, right)
if ((e.key === 'ArrowRight') || (e.key === 'ArrowDown') ||
(e.key === 'ArrowLeft') || (e.key === 'ArrowUp')) return;
if (e.key === 'Tab') return;
if (e.key === 'Enter' && this._webItemFocus) {
// Run the focused li's callback
this._webItemFocus.callback();
// Hide web menu
this.toggleWebMenu();
} else if (e.key === 'Backspace' && webMenuSearchBox.value.length < 1) {
// Hide web menu if backspace is pressed and searchbox value is 0
this.toggleWebMenu();
return;
} else if ((e.key === 'Escape') || (e.key === 'Alt')) {
// Ignore escape and alt key
return;
}
// Filter
this._filterWebList();
}
_registerWebMenuSearchBoxKeyDownEvent = () => {
this._webMenuSearchBox.onkeydown = this._webMenuSearchBoxKeyDownEvent;
}
_init = () => {
this._populateWebMenu();
this._getFirstItem();
// Disable inputs
this._disableWebMenuInputs(true);
this._registerWebMenuSearchBoxKeyDownEvent();
this._registerWebMenuKeyDownEvent();
}
// Filter
filterWebList();
}
// Populate and get first child
const initWebMenu = () => {
populateWebMenu();
getFirstItem();
// Disable inputs
disableWebMenuInputs(true);
}
// Initialize web menu
window.onload = initWebMenu();