|
@@ -0,0 +1,263 @@
|
|
|
|
+/**
|
|
|
|
+ * The globally-accessible Bumble Object
|
|
|
|
+ *
|
|
|
|
+ * Here I can store any and all utilities without taking up space in the
|
|
|
|
+ * gloabl namespace.
|
|
|
|
+ */
|
|
|
|
+var Bumble = {};
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * The info panel
|
|
|
|
+ *
|
|
|
|
+ * The info panel is a utility that allows me to add information to a page
|
|
|
|
+ * in such a way that it can easily be closed when the user is done reading
|
|
|
|
+ * it.
|
|
|
|
+ *
|
|
|
|
+ * This aims to improve the SEO of pages by adding as much descriptive
|
|
|
|
+ * text as I want, without harming the usability of the page. This takes into
|
|
|
|
+ * consideration that most of my pages are, currently, JS games on canvasses.
|
|
|
|
+ *
|
|
|
|
+ * @param {HTMLElement} panel - An HTML element with the .infopanel class
|
|
|
|
+ */
|
|
|
|
+Bumble.InfoPanel = function(panel){
|
|
|
|
+ this.panel = panel;
|
|
|
|
+ this.head = undefined;
|
|
|
|
+ this.body = undefined;
|
|
|
|
+ this.title = undefined
|
|
|
|
+ this.closer = undefined;
|
|
|
|
+ this.icons = {
|
|
|
|
+ close: "uil-times-circle",
|
|
|
|
+ open: "uil-info-circle"
|
|
|
|
+ }
|
|
|
|
+ this.isClosed = false;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Initialzize the info panel
|
|
|
|
+ */
|
|
|
|
+ this.init = function(){
|
|
|
|
+ if(!this.panel){ throw new Error("Panel not found."); }
|
|
|
|
+
|
|
|
|
+ this.head = this.panel.querySelector('.infopanel-head');
|
|
|
|
+ this.body = this.panel.querySelector('.infopanel-body');
|
|
|
|
+ this.title = this.head.querySelector('.infopanel-title');
|
|
|
|
+ this.closer = this.head.querySelector('.infopanel-closer');
|
|
|
|
+ this.isClosed = this.panel.classList.contains('closed');
|
|
|
|
+
|
|
|
|
+ this.closer.addEventListener("click", ()=>{ this.toggleVisibility(); });
|
|
|
|
+ this.toggleCloseButtonIcon();
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Close the info panel
|
|
|
|
+ */
|
|
|
|
+ this.close = function() {
|
|
|
|
+ this.panel.classList.add("closed");
|
|
|
|
+ this.isClosed = true;
|
|
|
|
+ }
|
|
|
|
+ /**
|
|
|
|
+ * Open the info panel
|
|
|
|
+ */
|
|
|
|
+ this.open = function() {
|
|
|
|
+ this.panel.classList.remove("closed")
|
|
|
|
+ this.isClosed = false;
|
|
|
|
+ }
|
|
|
|
+ /**
|
|
|
|
+ * Toggle the info panel's visibility
|
|
|
|
+ */
|
|
|
|
+ this.toggleVisibility = function() {
|
|
|
|
+ if(this.isClosed) { this.open(); }
|
|
|
|
+ else { this.close(); }
|
|
|
|
+
|
|
|
|
+ this.toggleCloseButtonIcon();
|
|
|
|
+ }
|
|
|
|
+ /**
|
|
|
|
+ * Toggle the icon of the info panel's open/close button
|
|
|
|
+ */
|
|
|
|
+ this.toggleCloseButtonIcon = function() {
|
|
|
|
+ if(this.isClosed) {
|
|
|
|
+ this.closer.classList.remove(this.icons.close);
|
|
|
|
+ this.closer.classList.add(this.icons.open);
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ this.closer.classList.remove(this.icons.open);
|
|
|
|
+ this.closer.classList.add(this.icons.close);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ this.init();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * A classic modal
|
|
|
|
+ *
|
|
|
|
+ * @param {string} DOMID - An option string of the DOM ID for premade modal
|
|
|
|
+ */
|
|
|
|
+Bumble.Modal = function(DOMID) {
|
|
|
|
+ this.overlay = undefined;
|
|
|
|
+ this.modal = {
|
|
|
|
+ base: undefined,
|
|
|
|
+ header: undefined,
|
|
|
|
+ title: undefined,
|
|
|
|
+ closer: undefined,
|
|
|
|
+ body: undefined
|
|
|
|
+ };
|
|
|
|
+ this.isShown = false;
|
|
|
|
+
|
|
|
|
+ this.init = function(DOMID) {
|
|
|
|
+ // Build the overlay
|
|
|
|
+ this.overlay = document.createElement("div");
|
|
|
|
+ this.overlay.classList.add("modal-overlay", "hidden");
|
|
|
|
+ // Initialize a predefined modal
|
|
|
|
+ if(DOMID) {
|
|
|
|
+ const elem = document.getElementById(DOMID);
|
|
|
|
+ if(!elem){
|
|
|
|
+ console.warn("No element found with ID: ", DOMID);
|
|
|
|
+ console.warn("Creating modal");
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ this.modal.pane = elem;
|
|
|
|
+ this.modal.header = elem.querySelector(".modal-header");
|
|
|
|
+ this.modal.title = elem.querySelector(".modal-title");
|
|
|
|
+ this.modal.closer = elem.querySelector(".uil-times-circle");
|
|
|
|
+ this.modal.body = elem.querySelector(".modal-body");
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // Build the modal from scratch
|
|
|
|
+ if(!this.modal.pane) {
|
|
|
|
+ this.modal.pane = document.createElement("div");
|
|
|
|
+ this.modal.pane.classList.add("modal");
|
|
|
|
+
|
|
|
|
+ this.modal.header = document.createElement("div");
|
|
|
|
+ this.modal.header.classList.add("modal-header");
|
|
|
|
+
|
|
|
|
+ this.modal.title = document.createElement("div");
|
|
|
|
+ this.modal.title.classList.add("modal-title");
|
|
|
|
+
|
|
|
|
+ const closerContainer = document.createElement("div");
|
|
|
|
+ closerContainer.classList.add("modal-closer", "text-right");
|
|
|
|
+
|
|
|
|
+ this.modal.closer = document.createElement("i");
|
|
|
|
+ this.modal.closer.classList.add("uil", "uil-times-circle");
|
|
|
|
+ closerContainer.appendChild(this.modal.closer);
|
|
|
|
+
|
|
|
|
+ this.modal.header.append(this.modal.title, closerContainer);
|
|
|
|
+
|
|
|
|
+ this.modal.body = document.createElement("div");
|
|
|
|
+ this.modal.body.classList.add("modal-body");
|
|
|
|
+
|
|
|
|
+ this.modal.pane.append(this.modal.header, this.modal.body);
|
|
|
|
+ }
|
|
|
|
+ // Add event listener to closer button
|
|
|
|
+ this.modal.closer.addEventListener("click", this.hide.bind(this));
|
|
|
|
+
|
|
|
|
+ // Add modal pane to the overlay
|
|
|
|
+ this.overlay.appendChild(this.modal.pane);
|
|
|
|
+
|
|
|
|
+ // Add overlay to body
|
|
|
|
+ document.body.appendChild(this.overlay);
|
|
|
|
+
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ this.SetTitle = function(title) {
|
|
|
|
+ this.modal.title.innerText = title;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ this.SetBody = function(bodyHTML) {
|
|
|
|
+ this.modal.body.innerHTML = bodyHTML;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ this.show = function() {
|
|
|
|
+ this.isShown = true;
|
|
|
|
+ this._toggleVisibility();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ this.hide = function() {
|
|
|
|
+ this.isShown = false;
|
|
|
|
+ this._toggleVisibility();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ this._toggleVisibility = function() {
|
|
|
|
+ if(this.isShown) {
|
|
|
|
+ this.overlay.classList.remove("hidden");
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ this.overlay.classList.add("hidden");
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ this.init(DOMID);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * Store GET Parameters
|
|
|
|
+ *
|
|
|
|
+ * A convenient place to store and access GET parameters sent to the page.
|
|
|
|
+ */
|
|
|
|
+Bumble._GET = {
|
|
|
|
+ /**
|
|
|
|
+ * Loads the GET parameters into this object
|
|
|
|
+ */
|
|
|
|
+ __init: function() {
|
|
|
|
+ const params = (new URL(document.location)).searchParams.entries();
|
|
|
|
+ for(const entry of params) {
|
|
|
|
+ if(entry[0] == "__init"){ continue; }
|
|
|
|
+ this[entry[0]] = !isNaN(entry[1]) ? Number(entry[1]) : entry[1];
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+Bumble.XFN = {
|
|
|
|
+ me: "uil-cell",
|
|
|
|
+ friend: "uil-user-check",
|
|
|
|
+ colleague: "uil-books",
|
|
|
|
+
|
|
|
|
+ _buildIcon: function(iconClass) {
|
|
|
|
+ const icon = document.createElement("i");
|
|
|
|
+ icon.classList.add("uil", iconClass);
|
|
|
|
+
|
|
|
|
+ return icon;
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ init: function() {
|
|
|
|
+ const links = document.querySelectorAll("a[rel]");
|
|
|
|
+
|
|
|
|
+ for(const link of links) {
|
|
|
|
+ const rels = link.rel.split(' ');
|
|
|
|
+ let rel = null;
|
|
|
|
+
|
|
|
|
+ if(rels.indexOf("me") >= 0) {
|
|
|
|
+ rel = this.me;
|
|
|
|
+ }
|
|
|
|
+ else if(rels.indexOf("friend") >= 0) {
|
|
|
|
+ rel = this.friend;
|
|
|
|
+ }
|
|
|
|
+ else if(rels.indexOf("colleague") >= 0) {
|
|
|
|
+ rel = this.colleague;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if(rel) {
|
|
|
|
+ link.insertAdjacentElement("afterbegin", this._buildIcon(rel));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function page_init() {
|
|
|
|
+ /* Initialize info panels */
|
|
|
|
+ const panels = document.querySelectorAll('.infopanel');
|
|
|
|
+ for(const panel of panels) {
|
|
|
|
+ panel._infoPanel = new Bumble.InfoPanel(panel);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Bumble._GET.__init();
|
|
|
|
+ Bumble.XFN.init();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+if(document.readyState != 'loading') {
|
|
|
|
+ page_init();
|
|
|
|
+}
|
|
|
|
+else {
|
|
|
|
+ document.addEventListener('DOMContentLoaded', page_init);
|
|
|
|
+}
|