diff --git a/public/home.html b/public/home.html
index 3a3153ea..837164d7 100644
--- a/public/home.html
+++ b/public/home.html
@@ -32,6 +32,7 @@
+
diff --git a/public/js/home.js b/public/js/home.js
index 811f6edd..dbafa011 100644
--- a/public/js/home.js
+++ b/public/js/home.js
@@ -1205,238 +1205,6 @@ function closeSideNav() {
// Allows exiting sidenav by clicking anywhere outside
document.getElementById("sidenav-overlay").addEventListener("click", closeSideNav);
-
-class Snackbar {
- static snackbars = {};
- static snackbarIDs = [];
-
- /**
- * text is the main requirement, and it's just text
- * color: String - string reference to a color or a variable, sets the background color
- * textColor: String - string reference to a color or a variable, sets the text color
- * buttonText: String - Sets the button text, both it and buttonClick have to be defined for the button to show
- * buttonClick: Function - Sets the button's onclick logic, both it and buttonText have to be defined for the button to show
- * destroyWhenButtonClicked : Boolean - Whether or not it should destroy itself when the button is clicked, defaults to true
- * bodyClick: Function - Sets the body's onclick logic
- * destroyWhenBodyClicked : Boolean - Whether or not it should destroy itself when the body is clicked, defaults to true
- * timeout: Int - Time in ms
- * timeoutFunction: Function - What to run on timeout (doesn't run if hidden or destroyed)
- * timeoutMode: can be "destroy", "hide", "none" or empty. Determines what to do on timeout, destroys by default
- */
- constructor(text, options = {}) {
- this.text = text;
- this.color = options["color"];
- this.textColor = options["textColor"];
- this.buttonText = options["buttonText"];
- this.buttonClick = options["buttonClick"];
- this.destroyWhenButtonClicked = options["destroyWhenButtonClicked"] || true;
- this.bodyClick = options["bodyClick"];
- this.destroyWhenBodyClicked = options["destroyWhenBodyClicked"] || true;
-
- //timeout logic
- this.timeoutFunction = options["timeoutFunction"] !== undefined ? options["timeoutFunction"] : () => {};
- this.timeout = options["timeout"];
- this.timeoutInProgress;
-
- //what to run on timeout
- this.timeoutEndFunction;
- switch(options["timeoutMode"]) {
- case "destroy":
- case undefined:
- this.timeoutEndFunction = () => this.destroy();
- break;
- case "hide":
- this.timeoutEndFunction = () => this.hide();
- break;
- case "none":
- this.timeoutEndFunction = () => {};
- break;
- }
-
- //creates this.id
- this.id;
- }
-
- /**
- * creates the snackbar in the HTML
- * if you want to show it as soon as you make it, use show without calling make instead
- * returns the snackbar object
- */
- make() {
- //stops if the element already exists
- if (typeof document.getElementById(`sidenav-${this.id}`) === undefined) {
- return;
- }
-
- //gives it an ID if it doesn't already have one
- if (this.id === undefined) {
- this.createID();
- }
-
- //creates the snackbar and gives it classes
- const snackbarNode = document.createElement("DIV");
- snackbarNode.classList.add("snackbar");
- snackbarNode.classList.add("hidden");
-
- //assigns it id based off of it's actual id
- snackbarNode.id = `snackbar-${this.id}`;
-
- //adds color if given
- if (this.color !== undefined) {
- snackbarNode.style.backgroundColor = `${this.color}`;
- }
-
- //sets the body onclick listener which just destroys it by default
- const bodyOnClickFunction = this.bodyClick !== undefined ? () => this.bodyClick() : () => {};
- const destroyFromBody = this.destroyWhenBodyClicked ? () => this.destroy() : () => {};
- snackbarNode.addEventListener("click", () => {
- bodyOnClickFunction();
- destroyFromBody();
- })
-
- //adds the text
- const textNode = document.createElement("SPAN");
- textNode.textContent = this.text;
-
- //colors the text if necessary
- if (this.textColor !== undefined) {
- textNode.style.color = this.textColor;
- }
-
- //adds the text node
- snackbarNode.appendChild(textNode);
-
- //makes the button if given button parameters
- if (this.buttonText !== undefined && this.buttonClick != undefined) {
- //creates the button and adds class
- const buttonNode = document.createElement("BUTTON");
-
- //creates the text span
- const buttonTextNode = document.createElement("SPAN");
- buttonTextNode.textContent = this.buttonText;
-
- //colors the text if necessary
- if (this.textColor !== undefined) {
- buttonTextNode.style.color = this.textColor;
- }
-
- if (this.color !== undefined) {
- buttonNode.style.backgroundColor = this.color;
- }
-
- //adds the text node
- buttonNode.appendChild(buttonTextNode);
-
- //sets the button onclick listener which runs the given funtion and destroys the snackar by default
- const destroyFromButton = this.destroyWhenButtonClicked ? () => this.destroy() : () => {};
- buttonNode.addEventListener("click", event => {
- this.buttonClick();
- destroyFromButton();
- //stops propogation so the body event isn't called
- event.stopPropagation();
- })
-
- snackbarNode.appendChild(buttonNode);
- }
-
- //adds the node to the body, puts reference to DOM element in this.element
- document.body.appendChild(snackbarNode);
- this.element = document.getElementById(`snackbar-${this.id}`);
-
- return this;
- }
-
- /**
- * shows the snackbar
- * if it's not already made, makes it
- * if you need to show right after making, use this
- * returns the snackbar object
- */
- show() {
- //starts the timeout
- if (this.timeout !== undefined) {
- this.timeoutInProgress = setTimeout(() => {
- this.timeoutFunction();
- this.timeoutEndFunction();
- this.timeoutInProgress = undefined; //resets the timeoutInProgress variable at the end of the timeout
- }, this.timeout);
- }
-
- const removeHidden = () => this.element.classList.remove("hidden");
-
- //if not already made, makes the snackbar
- if (document.getElementById(`snackbar-${this.id}`) === null) {
- this.make();
- //waits a momement to make sure the snackbar's animation functions properly
- setTimeout(removeHidden, 10);
- return this;
- } else {
- removeHidden();
- return this;
- }
- }
-
- /**
- * hides the snackbar
- * returns the snackbar object
- */
- hide() {
- if (this.timeoutInProgress !== undefined) {
- clearTimeout(this.timeoutInProgress);
- this.timeoutInProgress = undefined;
- }
-
- this.element.classList.add("hidden");
- return this;
- }
-
- /**
- * destroys the snackbar, its references and its ID
- * if it's not already hidden, hides it unless override is true
- */
- destroy() {
- const snackbar = this;
-
- //function which deletes the references and ids
- const finalizeDeletion = function() {
- snackbar.element.remove();
- delete Snackbar.snackbarIDs[Snackbar.snackbarIDs.indexOf(snackbar.id)];
- delete Snackbar.snackbars[snackbar.id];
- snackbar.id = undefined;
- }
-
- //if it's not hidden it shouldn't just dissapear
- if (this.element.classList.contains("hidden")) {
- finalizeDeletion();
- } else {
- this.hide();
- //deletes it as soon as it's actually hidden
- setTimeout(finalizeDeletion, 250);
- }
- }
-
- /**
- * creates and reserves the ID for this snackbar
- * also creates its reference in snackbars
- */
- createID() {
- let id = null;
-
- //goes through all consecutive numbers to find an id
- let iterator = 0
- while (id === null) {
- //checks if the id already exists, otherwise continues to iterate
- Snackbar.snackbarIDs.includes(iterator) ? iterator++ : id = iterator;
- }
-
- Snackbar.snackbarIDs.push(id);
- Snackbar.snackbars[id] = this;
- this.id = id;
-
- return id;
- }
-}
-
$("#export_button").click(() => {
prefs = {};
diff --git a/public/js/snackbar.js b/public/js/snackbar.js
new file mode 100644
index 00000000..3ae9215f
--- /dev/null
+++ b/public/js/snackbar.js
@@ -0,0 +1,230 @@
+class Snackbar {
+ static snackbars = {};
+ static snackbarIDs = [];
+
+ /**
+ * text is the main requirement, and it's just text
+ * color: String - string reference to a color or a variable, sets the background color
+ * textColor: String - string reference to a color or a variable, sets the text color
+ * buttonText: String - Sets the button text, both it and buttonClick have to be defined for the button to show
+ * buttonClick: Function - Sets the button's onclick logic, both it and buttonText have to be defined for the button to show
+ * destroyWhenButtonClicked : Boolean - Whether or not it should destroy itself when the button is clicked, defaults to true
+ * bodyClick: Function - Sets the body's onclick logic
+ * destroyWhenBodyClicked : Boolean - Whether or not it should destroy itself when the body is clicked, defaults to true
+ * timeout: Int - Time in ms
+ * timeoutFunction: Function - What to run on timeout (doesn't run if hidden or destroyed)
+ * timeoutMode: can be "destroy", "hide", "none" or empty. Determines what to do on timeout, destroys by default
+ */
+ constructor(text, options = {}) {
+ this.text = text;
+ this.color = options["color"];
+ this.textColor = options["textColor"];
+ this.buttonText = options["buttonText"];
+ this.buttonClick = options["buttonClick"];
+ this.destroyWhenButtonClicked = options["destroyWhenButtonClicked"] || true;
+ this.bodyClick = options["bodyClick"];
+ this.destroyWhenBodyClicked = options["destroyWhenBodyClicked"] || true;
+
+ //timeout logic
+ this.timeoutFunction = options["timeoutFunction"] !== undefined ? options["timeoutFunction"] : () => {};
+ this.timeout = options["timeout"];
+ this.timeoutInProgress;
+
+ //what to run on timeout
+ this.timeoutEndFunction;
+ switch(options["timeoutMode"]) {
+ case "destroy":
+ case undefined:
+ this.timeoutEndFunction = () => this.destroy();
+ break;
+ case "hide":
+ this.timeoutEndFunction = () => this.hide();
+ break;
+ case "none":
+ this.timeoutEndFunction = () => {};
+ break;
+ }
+
+ //creates this.id
+ this.id;
+ }
+
+ /**
+ * creates the snackbar in the HTML
+ * if you want to show it as soon as you make it, use show without calling make instead
+ * returns the snackbar object
+ */
+ make() {
+ //stops if the element already exists
+ if (typeof document.getElementById(`sidenav-${this.id}`) === undefined) {
+ return;
+ }
+
+ //gives it an ID if it doesn't already have one
+ if (this.id === undefined) {
+ this.createID();
+ }
+
+ //creates the snackbar and gives it classes
+ const snackbarNode = document.createElement("DIV");
+ snackbarNode.classList.add("snackbar");
+ snackbarNode.classList.add("hidden");
+
+ //assigns it id based off of it's actual id
+ snackbarNode.id = `snackbar-${this.id}`;
+
+ //adds color if given
+ if (this.color !== undefined) {
+ snackbarNode.style.backgroundColor = `${this.color}`;
+ }
+
+ //sets the body onclick listener which just destroys it by default
+ const bodyOnClickFunction = this.bodyClick !== undefined ? () => this.bodyClick() : () => {};
+ const destroyFromBody = this.destroyWhenBodyClicked ? () => this.destroy() : () => {};
+ snackbarNode.addEventListener("click", () => {
+ bodyOnClickFunction();
+ destroyFromBody();
+ })
+
+ //adds the text
+ const textNode = document.createElement("SPAN");
+ textNode.textContent = this.text;
+
+ //colors the text if necessary
+ if (this.textColor !== undefined) {
+ textNode.style.color = this.textColor;
+ }
+
+ //adds the text node
+ snackbarNode.appendChild(textNode);
+
+ //makes the button if given button parameters
+ if (this.buttonText !== undefined && this.buttonClick != undefined) {
+ //creates the button and adds class
+ const buttonNode = document.createElement("BUTTON");
+
+ //creates the text span
+ const buttonTextNode = document.createElement("SPAN");
+ buttonTextNode.textContent = this.buttonText;
+
+ //colors the text if necessary
+ if (this.textColor !== undefined) {
+ buttonTextNode.style.color = this.textColor;
+ }
+
+ if (this.color !== undefined) {
+ buttonNode.style.backgroundColor = this.color;
+ }
+
+ //adds the text node
+ buttonNode.appendChild(buttonTextNode);
+
+ //sets the button onclick listener which runs the given funtion and destroys the snackar by default
+ const destroyFromButton = this.destroyWhenButtonClicked ? () => this.destroy() : () => {};
+ buttonNode.addEventListener("click", event => {
+ this.buttonClick();
+ destroyFromButton();
+ //stops propogation so the body event isn't called
+ event.stopPropagation();
+ })
+
+ snackbarNode.appendChild(buttonNode);
+ }
+
+ //adds the node to the body, puts reference to DOM element in this.element
+ document.body.appendChild(snackbarNode);
+ this.element = document.getElementById(`snackbar-${this.id}`);
+
+ return this;
+ }
+
+ /**
+ * shows the snackbar
+ * if it's not already made, makes it
+ * if you need to show right after making, use this
+ * returns the snackbar object
+ */
+ show() {
+ //starts the timeout
+ if (this.timeout !== undefined) {
+ this.timeoutInProgress = setTimeout(() => {
+ this.timeoutFunction();
+ this.timeoutEndFunction();
+ this.timeoutInProgress = undefined; //resets the timeoutInProgress variable at the end of the timeout
+ }, this.timeout);
+ }
+
+ const removeHidden = () => this.element.classList.remove("hidden");
+
+ //if not already made, makes the snackbar
+ if (document.getElementById(`snackbar-${this.id}`) === null) {
+ this.make();
+ //waits a momement to make sure the snackbar's animation functions properly
+ setTimeout(removeHidden, 10);
+ return this;
+ } else {
+ removeHidden();
+ return this;
+ }
+ }
+
+ /**
+ * hides the snackbar
+ * returns the snackbar object
+ */
+ hide() {
+ if (this.timeoutInProgress !== undefined) {
+ clearTimeout(this.timeoutInProgress);
+ this.timeoutInProgress = undefined;
+ }
+
+ this.element.classList.add("hidden");
+ return this;
+ }
+
+ /**
+ * destroys the snackbar, its references and its ID
+ * if it's not already hidden, hides it unless override is true
+ */
+ destroy() {
+ const snackbar = this;
+
+ //function which deletes the references and ids
+ const finalizeDeletion = function() {
+ snackbar.element.remove();
+ delete Snackbar.snackbarIDs[Snackbar.snackbarIDs.indexOf(snackbar.id)];
+ delete Snackbar.snackbars[snackbar.id];
+ snackbar.id = undefined;
+ }
+
+ //if it's not hidden it shouldn't just dissapear
+ if (this.element.classList.contains("hidden")) {
+ finalizeDeletion();
+ } else {
+ this.hide();
+ //deletes it as soon as it's actually hidden
+ setTimeout(finalizeDeletion, 250);
+ }
+ }
+
+ /**
+ * creates and reserves the ID for this snackbar
+ * also creates its reference in snackbars
+ */
+ createID() {
+ let id = null;
+
+ //goes through all consecutive numbers to find an id
+ let iterator = 0
+ while (id === null) {
+ //checks if the id already exists, otherwise continues to iterate
+ Snackbar.snackbarIDs.includes(iterator) ? iterator++ : id = iterator;
+ }
+
+ Snackbar.snackbarIDs.push(id);
+ Snackbar.snackbars[id] = this;
+ this.id = id;
+
+ return id;
+ }
+}
\ No newline at end of file