Skip to content

Commit

Permalink
moves snackbar code to another file
Browse files Browse the repository at this point in the history
  • Loading branch information
andOrlando committed Jan 18, 2021
1 parent cde1a7b commit a31334b
Show file tree
Hide file tree
Showing 3 changed files with 231 additions and 232 deletions.
1 change: 1 addition & 0 deletions public/home.html
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
<script src="js/calculate_grade.js" defer></script>
<script src="js/home.js" defer></script>
<script src="js/app.js" defer></script>
<script src="js/snackbar.js" defer></script>
<script src="vendor/pdf.js/pdf.min.js" defer></script>
<script src="vendor/file-saver/FileSaver.min.js" defer></script>
<script src="vendor/d3/d3-array.min.js" defer></script>
Expand Down
232 changes: 0 additions & 232 deletions public/js/home.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {};

Expand Down
Loading

0 comments on commit a31334b

Please sign in to comment.