I have a popup that opens on a button click and then closes if you click on another button or outside of the popup. I want the popup to fade in on opening and fade out on closing. How can I switch between the two keyframes with javascript?
I tried to do it with switching classes with javascript, but that doesn't work.
var popup = document.getElementById("popup");
var popup_content = document.getElementById("popup_content");
var add = document.getElementById("add");
var span = document.getElementById("close");
add.onclick = function() {
popup.style.display = "block";
popup.className = "opened";
popup_content = "opened";
}
span.onclick = function() {
popup.style.display = "none";
popup.className = "closed";
popup_content = "closed";
}
window.onclick = function(event) {
if (event.target == popup) {
popup.style.display = "none";
popup.className = "closed";
popup_content = "closed";
}
}
#popup {
display: none;
position: fixed;
z-index: 1;
padding-top: 100px;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.4);
}
#popup_content {
position: relative;
margin: auto;
background-color: white;
width: 80%;
max-width: 500px;
border-radius: 5px;
padding: 20px;
text-decoration: none;
box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.5);
}
.closed {
-webkit-animation-name: animate-in;
-webkit-animation-duration: 0.6s;
animation-name: animate-in;
animation-duration: 0.6s;
}
.opened {
-webkit-animation-name: animate-out;
-webkit-animation-duration: 0.6s;
animation-name: animate-out;
animation-duration: 0.6s;
}
#-webkit-keyframes animate-in {
from {
opacity: 0
}
to {
opacity: 1
}
}
#keyframes animate-in {
from {
opacity: 0
}
to {
opacity: 1
}
}
#-webkit-keyframes animate-out {
from {
opacity: 1
}
to {
opacity: 0
}
}
#keyframes animate-out {
from {
opacity: 1
}
to {
opacity: 0
}
}
#close {
float: right;
cursor: pointer;
margin: -15px -15px 0 0;
}
<button id="add">Open popup</button>
<div class="closed" id="popup">
<div class="closed" id="popup_content">
<i class="fas fa-times-circle" id="close">Close</i> //////content
</div>
</div>
What would be the best way to achieve my goal?
I would use a transition - see the comments in the css and js as to what I changed:
var popup = document.getElementById("popup");
var add = document.getElementById("add");
var span = document.getElementById("close");
add.onclick = function() {
popup.className = "opened"; // only need to transition the popup
}
span.onclick = function() {
popup.className = "closed";
}
window.onclick = function(event) {
if (event.target == popup) {
popup.className = "closed";
}
}
#popup {
position: fixed;
z-index: 1;
padding-top: 100px;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.4);
/* add the following and remove the display:none */
transition: opacity 0.6s;
opacity: 0; /* start off closed and opacity 0 to hide */
}
#popup.opened {
opacity: 1; /* add opacity 1 so it transitions to be shown */
}
#popup.closed {
/* this stops the popup from overlaying the content when closed */
pointer-events:none;
}
#popup_content {
position: relative;
margin: auto;
background-color: white;
width: 80%;
max-width: 500px;
border-radius: 5px;
padding: 20px;
text-decoration: none;
box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.5);
}
#close {
float: right;
cursor: pointer;
margin: -15px -15px 0 0;
}
<button id="add">Open popup</button>
<div class="closed" id="popup">
<div id="popup_content">
<i class="fas fa-times-circle" id="close">Close</i> //////content
</div>
</div>
To apply an animation using CSS. do not use the display none / block property or snippet. you can instead use the transition property and the opacity property for the fade in / out.
Here is an example of the code
var popup = document.getElementById("popup");
var popup_content = document.getElementById("popup_content");
var add = document.getElementById("add");
var span = document.getElementById("close");
add.onclick = function() {
popup.className="opened";
popup_content.className="opened";
}
span.onclick = function() {
popup.className="closed";
popup_content.className="closed";
}
window.onclick = function(event) {
if (event.target == popup) {
popup.className="closed";
popup_content.className="closed";
}
}
#popup {
position: fixed;
z-index: 1;
padding-top: 100px;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.4);
}
#popup_content {
position: relative;
margin: auto;
background-color: white;
width: 80%;
max-width: 500px;
border-radius: 5px;
padding: 20px;
text-decoration: none;
box-shadow: 0 8px 16px 0 rgba(0,0,0,0.5);
}
.closed {
opacity:0;
visibility:hidden;
transition: opacity 0.8s ease;
}
.opened {
opacity:1;
visibility:visible;
transition: opacity 0.8s ease;
}
#close {
float: right;
cursor: pointer;
margin: -15px -15px 0 0;
}
<button id="add">Open popup</button>
<div class="closed" id="popup">
<div class="closed" id="popup_content">
<i class="fas fa-times-circle" id="close">Close</i>
//////content
</div>
</div>
Mahmoud is right about using display: none/block while trying to introduce a transition or animation. The transition is also best here vs. animations. I did not include here that using classList.add/remove will give you more flexibility in using classes later since it's not the question, but I think it's important side note. What is different here is the inclusion of the visibility attribute to the transition in your opened/closed classes. Since visibility is binary much like using display: none/block, this will remove the transition from site. For example, when closing the popup, the visibility: hidden; attribute will execute right at the beginning of the transition execution. In result, you never see the transition when closing. If you include visibility in your transition, it will execute at the proper time of your transition. I've tested this on firefox and chrome.
var popup = document.getElementById("popup");
var popup_content = document.getElementById("popup_content");
var add = document.getElementById("add");
var span = document.getElementById("close");
add.onclick = function() {
popup.className="opened";
popup_content.className="opened";
}
span.onclick = function() {
popup.className="closed";
popup_content.className="closed";
}
window.onclick = function(event) {
if (event.target == popup) {
popup.className="closed";
popup_content.className="closed";
}
}
#popup {
position: fixed;
z-index: 1;
padding-top: 100px;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.4);
}
#popup_content {
position: relative;
margin: auto;
background-color: white;
width: 80%;
max-width: 500px;
border-radius: 5px;
padding: 20px;
text-decoration: none;
box-shadow: 0 8px 16px 0 rgba(0,0,0,0.5);
}
.closed {
opacity:0;
visibility:hidden;
transition: opacity 0.8s ease, visibility 0.8s ease;
}
.opened {
opacity:1;
visibility:visible;
transition: opacity 0.8s ease, visibility 0.8s ease;
}
#close {
float: right;
cursor: pointer;
margin: -15px -15px 0 0;
}
<button id="add">Open popup</button>
<div class="closed" id="popup">
<div class="closed" id="popup_content">
<i class="fas fa-times-circle" id="close">Close</i>
//////content
</div>
</div>
Related
;
(function($) {
class Popup {
constructor(options, elem) {
var self = this;
var defaultPopupMenu = `<div>
<i id="faInfo" class="fa fa-info"></i>
<i id="faQuest" class="fa fa-question"></i>
<i id="faLink" class="fa fa-external-link"></i>
</div>`;
this.defaultOptions = {
content: defaultPopupMenu, //this option MUST be set when new options passed through, or only the default menu will show
position: "top", //where the popup will show by default- top. Other options: right, bottom, or left
theme: "popupTheme", //Menu Element theme. Defaults to popupTheme, but custom class can be set instead
style: "", //Popup Menu Style. Default no style, will revert to default colours. Other options: Blue, Red, Green, Custom
animation: "standard", //Standard animation by default. Other options: flip, grow, bounce
event: "click", //Default set to "click", can also be set to hover
hideOnClick: true, //When true, clicking off the menu closes it. When false, only clicking on the menu closes it
zIndex: 100, //Individual z-index can be set for each menu for layering if necessary
//function to handle actions when clicking on popup menu icons. MUST be set when options are passed through or an error or default menu actions will occur
popItemClick: function(globalthis) {
//Default actions
var twentyEightSpaces = `
`;
var twentyFourSpaces = `
`;
var eightSpaces = ` `;
var sixteenSpaces = `
`;
var content;
var container = $(event.target).attr("id");
switch (container) {
case "faInfo":
content = {
type: "info",
heading: "Information",
text: `<p>To set a new menu when calling .popup() on an element,
you must set a variable that holds a string with the html for that menu, then
pass that variable through as the "content" part of the options. For example: </p>
<p>var myMenu = '<div>\ <br />
${twentyEightSpaces}<a href="#''><i id="faInfo" class="fa fa-info"></i></a>\<br />
${twentyFourSpaces}</div>'; </p>
<p>would create a menu with one item, and just add more '<a>' tags with icons inside the '<div>' tags to add more menu items. </p>
<p>Then add it to the content when calling the popup: </p>
<p>$("#myPopUp").popup({ <br />
${eightSpaces}content: myMenu, <br />
${eightSpaces}popItemClick(globalthis) { <br />
${sixteenSpaces}...new actions here... <br />
${eightSpaces}} <br />
});</p>
<p>You must set new actions in the "popItemClick" function for your menu
in the options you pass or it will throw an error.</p>`
}
globalthis.alertBox(content);
break;
case "faQuest":
content = {
type: "info",
heading: "Question",
text: `<p>Why is this being shown?</p>
<p>Because you need to set a popup menu of your own (and the popItemClick() function) or you get this default menu.</p>
<p>If you set the popup menu but don't change the popItemClick() function, you will get an error.</p>
<p>Click the "i" button for more info.</p>`
}
globalthis.alertBox(content);
break;
case "faLink":
window.open("http://example.com/");
break;
default:
content = {
type: "danger",
heading: "Error",
text: `<p>Error! You have set a new menu without changing the 'popItemClick' function.
The 'popItemClick' function must be set to new menu actions.</p>`
}
globalthis.alertBox(content);
}
}
}
this.elem = elem;
this.$elem = $(elem);
this.options = $.extend({}, this.defaultOptions, options);
if (!this.$elem.hasClass(this.options.theme)) {
this.$elem.addClass(this.options.theme);
}
this.init();
}
init() {
this.popup = $('<div class="pop-cont" />')
.addClass('pop-' + this.options.position)
.addClass('popupTheme' + this.options.style)
.append('<div class="pop-items" />')
.appendTo('body').css("opacity", 0).hide();
this.setContent();
this.setTriggers();
}
setContent() {
var self = this;
var location = this.popup.find(".pop-items");
var content;
if ((this.options.position == 'top') || (this.options.position == 'bottom')) {
content = $(this.options.content).find("a").addClass("pop-item");
location.html(content);
this.popup.find("i").first().addClass("leftBorder");
this.popup.find("i").last().addClass("rightBorder");
} else if ((this.options.position == 'left') || (this.options.position == 'right')) {
content = $(this.options.content).find("a").addClass("pop-item").addClass('item-side');
location.html(content);
this.popup.find("i").first().addClass("topBorder");
this.popup.find("i").last().addClass("bottomBorder");
}
//popItemClick callback****************************************
location.find('.pop-item').on('click', function(event) {
event.preventDefault();
self.options.popItemClick.call(this, self);
});
}
setTriggers() {
var self = this;
if (this.options.event === 'click') {
this.$elem.on('click', function(event) {
event.preventDefault();
if (self.$elem.hasClass('pressed')) {
self.pophide();
} else {
self.popshow();
}
});
}
if (this.options.event === 'hover') {
this.$elem.on('mouseenter', function(event) {
setTimeout(function() {
self.popshow();
self.popup = $(self.popup[0]);
}, 250);
});
$(this.popup).on('mouseleave', function(event) {
setTimeout(function() {
self.pophide();
}, 1000);
});
}
if (this.options.hideOnClick === true) {
$('html').on('click.popup', function(event) {
if (event.target != self.elem && self.$elem.has(event.target).length === 0 &&
self.popup.has(event.target).length === 0 && self.popup.is(":visible")) {
self.pophide();
}
});
}
}
pophide() {
var self = this;
var animation = {
opacity: 0
};
this.$elem.removeClass('pressed');
switch (this.options.position) {
case 'top':
animation.top = '+=20';
break;
case 'left':
animation.left = '+=20';
break;
case 'right':
animation.left = '-=20';
break;
case 'bottom':
animation.top = '-=20';
break;
}
this.popup.animate(animation, 200, function() {
self.popup.hide();
});
}
popshow() {
this.$elem.addClass('pressed');
this.setPosition();
this.popup.show().css({
opacity: 1
}).addClass('animate-' + this.options.animation);
}
setPosition() {
var self = this;
this.coords = this.$elem.offset();
var x = this.coords.left;
var y = this.coords.top;
var popWidth = this.popup.width();
var popHeight = this.popup.height();
var adjLeft = popWidth / 2;
var adjTop = popHeight / 2;
this.testy = $('<div class="test" />')
.css({
display: 'inline-block',
margin: '0px',
padding: '0px'
})
.appendTo('body');
var measure = this.$elem.clone().css({
padding: "0px",
margin: "0px"
});
var loc = this.testy;
loc.html(measure);
var textWidth = this.testy.width();
var textHeight = this.testy.height();
this.testy.remove();
var adjMenuWidth = textWidth / 2;
var adjMenuHeight = textHeight / 2;
var up = y - (popHeight + 7);
var down = y + textHeight;
if (this.popup.hasClass('pop-top')) {
this.popup.css({
top: up + "px",
left: (x - adjLeft + adjMenuWidth + 5) + "px",
right: "auto",
'z-index': this.options.zIndex
});
}
if (this.popup.hasClass('pop-bottom')) {
this.popup.css({
top: (down + 7) + "px",
left: (x - adjLeft + adjMenuWidth + 5) + "px",
right: "auto",
'z-index': this.options.zIndex
});
}
if (this.popup.hasClass('pop-left')) {
this.popup.css({
top: (y - adjTop + adjMenuHeight + 5) + "px",
left: (x - popWidth - 2) + "px",
right: "auto",
'z-index': this.options.zIndex
});
}
if (this.popup.hasClass('pop-right')) {
this.popup.css({
top: (y - adjTop + adjMenuHeight + 5) + "px",
left: (x + textWidth + 12) + "px",
right: "auto",
'z-index': this.options.zIndex
});
}
}
alertBox(content) {
var self = this;
var myAlert = `<div id="alertBox" class="alert">
<div class="alert-content">
<div class="alert-header">
<h2></h2>
</div>
<div class="alert-body"></div>
<div class="alert-footer">
<button class="alert-close">OK</button>
</div>
</div>
</div>`;
$('body').append(myAlert);
this.alert = $('#alertBox');
this.header = this.alert.find('div.alert-header');
this.heading = this.header.find('h2');
this.alertBody = this.alert.find('div.alert-body');
this.footer = this.alert.find('div.alert-footer');
this.close = this.footer.find('button.alert-close');
this.heading.append(content.heading);
this.alertBody.append(content.text);
switch (content.type) {
case "info":
this.header.addClass("info");
this.footer.addClass("info");
this.close.addClass("info");
break;
case "success":
this.header.addClass("success");
this.footer.addClass("success");
this.close.addClass("success");
break;
case "danger":
this.header.addClass("danger");
this.footer.addClass("danger");
this.close.addClass("danger");
break;
case "warning":
this.header.addClass("warning");
this.footer.addClass("warning");
this.close.addClass("warning");
break;
default:
break;
}
this.alert.show();
var closeBtn = $("button.alert-close");
closeBtn.on("click", function() {
self.alert.remove();
});
$(document).on("click", function(event) {
event.preventDefault();
if (event.target == self.alert[0]) {
self.alert.remove();
}
});
}
};
//Set $.fn.popup so it returns an instance of the Popup class when called*******************************
$.fn.popup = function(options) {
return this.each(function() {
var popobject = new Popup(options, this);
});
};
}(jQuery));
/*jshint multistr: true */
//this is a sample .js file that shows how you might set up the popup menus
;
(function($) {
$(document).ready(function() {
$('#defaultTest').popup();
});
}(jQuery));
/*Default theme**************/
.popupTheme {
background-color: #333;
background-size: 100% 100%;
color: #fff;
text-align: center;
border-radius: 6px;
padding: 0;
position: relative;
box-shadow: 5px 5px 3px #888;
z-index: 1;
float: left;
margin: 5px;
cursor: pointer;
}
.popupTheme i,
.popupThemeRed i,
.popupThemeBlue i,
.popupThemeGreen i,
.popupThemeCustom i {
width: 20px;
height: 20px;
font-size: 18px;
color: #fff;
display: block;
background-color: transparent;
padding: 10px;
background-size: 100% 100%;
cursor: pointer;
}
.popupTheme i:hover {
background-color: #4d4d4d;
}
.pop-cont.pop-top::after {
content: "";
position: absolute;
top: 100%;
left: 50%;
margin-left: -7px;
border-width: 7px;
border-style: solid;
border-color: #333 transparent transparent transparent;
z-index: 100;
}
.pop-cont.pop-bottom::before {
content: "";
position: absolute;
top: -14px;
left: 50%;
margin-left: -7px;
border-width: 7px;
border-style: solid;
border-color: transparent transparent #333 transparent;
z-index: 100;
}
.pop-cont.pop-left::after {
content: "";
position: absolute;
top: 50%;
left: 100%;
margin-top: -7px;
border-width: 7px;
border-style: solid;
border-color: transparent transparent transparent #333;
z-index: 100;
}
.pop-cont.pop-right::before {
content: "";
position: absolute;
top: 50%;
left: -14px;
margin-top: -7px;
border-width: 7px;
border-style: solid;
border-color: transparent #333 transparent transparent;
z-index: 100;
}
.pop-cont {
margin: auto;
position: relative;
display: block;
cursor: pointer;
border-radius: 6px;
box-shadow: 5px 5px 3px #888;
}
.pop-cont,
.pop-item,
.popupTheme {
-webkit-box-sizing: content-box;
-moz-box-sizing: content-box;
box-sizing: content-box;
}
/*Individual menu item*/
.pop-item {
height: 100%;
display: block;
width: 20px;
height: 20px;
text-align: center;
padding: 10px;
text-decoration: none;
float: left;
}
.item-side {
float: none !important;
}
.pop-item i {
margin: -10px 0 0 -10px;
}
.pop-top {
position: absolute;
top: 100%;
left: 50%;
margin-left: -5px;
}
.pop-bottom {
position: absolute;
top: 0;
left: 50%;
margin-left: -5px;
}
.pop-left {
position: absolute;
top: 100%;
left: 50%;
margin-left: -5px;
margin-top: -7px;
}
.pop-right {
position: absolute;
top: 100%;
left: 50%;
margin-left: -5px;
margin-top: -7px;
}
.animate-standard {
animation: animateStandard 0.3s 1 ease;
-webkit-animation: animateStandard 0.3s 1 ease;
}
#-webkit-keyframes animateStandard {
from {
transform: translateY(20px);
opacity: 0;
}
to {
transform: translateY(0px);
opacity: 1;
}
}
#keyframes animateStandard {
from {
transform: translateY(20px);
opacity: 0;
}
to {
transform: translateY(0px);
opacity: 1;
}
}
.animate-grow {
animation: animateGrow 0.4s 1 ease;
-webkit-animation: animateGrow 0.4s 1 ease;
}
#-webkit-keyframes animateGrow {
0% {
transform: scale(0) translateY(40px);
opacity: 0;
}
70% {
transform: scale(1.5) translate(0px);
}
100% {
transform: scale(1) translate(0px);
opacity: 1;
}
}
#keyframes animateGrow {
0% {
transform: scale(0) translateY(40px);
opacity: 0;
}
70% {
transform: scale(1.5) translate(0px);
}
100% {
transform: scale(1) translate(0px);
opacity: 1;
}
}
.animate-flip {
animation: animateFlip 0.4s 1 ease;
-webkit-animation: animateFlip 0.4s 1 ease;
}
#-webkit-keyframes animateFlip {
from {
transform: rotate3d(2, 2, 2, 180deg);
opacity: 0;
}
to {
transform: rotate3d(0, 0, 0, 0deg);
opacity: 1;
}
}
#keyframes animateFlip {
from {
transform: rotate3d(2, 2, 2, 180deg);
opacity: 0;
}
to {
transform: rotate3d(0, 0, 0, 0deg);
opacity: 1;
}
}
.leftBorder {
border-top-left-radius: 6px;
border-bottom-left-radius: 6px;
}
.rightBorder {
border-top-right-radius: 6px;
border-bottom-right-radius: 6px;
}
.bottomBorder {
border-bottom-left-radius: 6px;
border-bottom-right-radius: 6px;
}
.topBorder {
border-top-left-radius: 6px;
border-top-right-radius: 6px;
}
.hidden {
display: none !important;
}
.clear {
clear: both;
}
/* The Alert Box (background) */
.alert {
display: none;
/* Hidden by default */
position: fixed;
/* Stay in place */
z-index: 1001;
/* Sit on top */
padding-top: 250px;
/* Location of the box */
left: 0;
top: 0;
width: 100%;
/* Full width */
height: 100%;
/* Full height */
overflow: auto;
/* Enable scroll if needed */
background-color: rgb(0, 0, 0);
/* Fallback color */
background-color: rgba(0, 0, 0, 0.8);
/* Black w/ opacity */
}
.alert-content {
position: relative;
background-color: #fefefe;
margin: auto;
padding: 0;
border: 1px solid #888;
border-radius: 6px;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
-webkit-animation-name: animatetop;
-webkit-animation-duration: 0.4s;
animation-name: animatetop;
animation-duration: 0.4s;
max-width: 700px;
min-width: 300px;
/*width settings for different browsers. Note that these won't work at all for IE and versions of Edge before v79*/
width: fit-content;
/*works in chrome and opera*/
width: -moz-fit-content;
/*works for firefox */
width: -webkit-fit-content;
/*works for Edge v79 and up*/
width: -ms-fit-content;
width: -o-fit-content;
}
#-webkit-keyframes animatetop {
from {
top: -300px;
opacity: 0
}
to {
top: 0;
opacity: 1
}
}
#keyframes animatetop {
from {
top: -300px;
opacity: 0
}
to {
top: 0;
opacity: 1
}
}
.alert-header,
.alert-header.info {
padding: 2px 16px;
background-color: #02baf2;
color: #fff;
border-radius: 5px 5px 0px 0px;
text-align: center;
}
.alert-header.success {
background-color: #00cc1b;
}
.alert-header.danger {
background-color: #ff0000;
}
.alert-header.warning {
background-color: #f7931e;
}
.alert-body {
padding: 2px 16px;
text-align: left;
font-size: 18px;
font-weight: bold;
color: #000;
min-height: 40px;
}
.alert-footer,
.alert-footer.info {
padding: 15px 16px;
background-color: #02baf2;
color: #fff;
border-radius: 0px 0px 5px 5px;
text-align: center;
}
.alert-footer.success {
background-color: #00cc1b;
}
.alert-footer.danger {
background-color: #ff0000;
}
.alert-footer.warning {
background-color: #f7931e;
}
.alert-close,
.alert-close.info {
padding: 5px 15px;
border-radius: 3px;
border: 0;
background-color: #fff;
color: #02baf2;
font-weight: bold;
box-shadow: 5px 5px 10px #666;
}
.alert-close.success {
color: #00cc1b;
}
.alert-close.danger {
color: #ff0000;
}
.alert-close.warning {
color: #f7931e;
}
.alert-close:hover {
color: #000;
text-decoration: none;
cursor: pointer;
}
.alert-close:focus {
outline: none;
}
body {
font-family: Helvetica, sans-serif;
}
.displayBox {
background-color: #efefef;
padding: 0px 0px 30px 0px;
display: inline-block;
width: 100%;
}
.header {
text-align: center;
font-size: 12px;
border-bottom: 1px solid #fff;
width: 100%;
color: #fff;
background-color: #130e5a;
}
.header h1 {
margin: 0px;
padding: 5px 0px;
}
div.icon-box-top {
margin: 50px 0px 25px 0px;
display: block;
float: left;
clear: both;
}
div.icon-box {
margin: 25px 0px 25px 0px;
display: block;
float: left;
clear: both;
}
p.icon-text,
p.menuText {
display: block;
margin-left: 45px;
margin-bottom: 0px;
float: left;
}
p.menuText {
margin-left: 20px !important;
margin-top: 0px;
}
.textPopup {
/*When attaching popups to text menus, style text menu separately*/
display: block;
font-size: 28px;
font-weight: bold;
color: #130e5a;
margin: 0px 0px 0px 75px;
-webkit-box-sizing: content-box;
-moz-box-sizing: content-box;
box-sizing: content-box;
cursor: pointer;
float: left;
z-index: 1;
}
p.textPopup.pressed {
color: #02baf2 !important;
}
div#myPopUp,
div#myPopUp2,
div#myPopUp3,
div#myPopUp4 {
margin-left: 75px;
display: inline-block;
}
i.swIcon {
font-size: 208px !important;
margin: 10px;
}
text-decoration: none;
}
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" />
<div class="icon-box-top">
<div id="defaultTest" style="margin-left: 75px">
<i class="fa fa-cog leftBorder rightBorder"></i>
</div>
</div>
I have an example I'm working from which works fine. When I duplicate that code in my app, the icon looks too small and off center.
Here is how it is supposed to look, per example:
Here is how it looks when I enter the same code:
It is smaller and the cog is off center.
Here is the example's html:
<div class="icon-box-top">
<div id="defaultTest" style="margin-left: 75px">
<i class="fa fa-cog leftBorder rightBorder"></i>
</div>
</div>
Here is my html:
<div class="icon-box-top">
<div id="defaultTest" style="margin-left: 75px">
<i class="fa fa-cog leftBorder rightBorder"></i>
</div>
</div>
Here are the example's dependencies:
<link rel="stylesheet" type="text/css" href="styles/Popup-plugin.css">
<link rel="stylesheet" type="text/css" href="styles/Example.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script src="https://code.jquery.com/jquery-1.12.4.min.js" integrity="sha384-nvAa0+6Qg9clwYCGGPpDQLVpLNn0fRaROjHqs13t4Ggj3Ez50XnGQqc/r8MhnRDZ" crossorigin="anonymous"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script> <!-- necessary for the "draggable" ui -->
<script src="scripts/Popup-plugin.js"></script>
<script src="scripts/Example.js"></script>
Here are my dependencies:
<link rel="stylesheet" type="text/css" href="css/Popup-plugin.css">
<link rel="stylesheet" type="text/css" href="css/Example.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script> <!-- necessary for the "draggable" ui -->
<script src="js/Popup-plugin.js"></script>
<script src="js/Example.js"></script>
The only difference that I can see is he stores his javascript in scripts folder and mine is in js folder. And he stores his css in styles folder whereas mine is in css folder.
The javascript is the same too:
$('#defaultTest').popup();
Any ideas?
I finally found the problem. There was a bootstrap css library that was interfering with the Popup-plugin css. But now my bootstrap tabs don't work and I'll have to spend additional time looking at different versions of it, or replacing the tabs with something else. I figured there was a css conflict somewhere but it took me all day to find it. This has happened to me before and it is a painful and time-consuming process to isolate the problem and fix it. If anyone has suggestions of tools or techniques for speeding up this process, please leave comments below for everyone reading this to benefit.
after click on Open Modal button. it's disappear . i did not see anything wrong with my code.
Code Example - Scenario
let nrSanckbar = (function(){
const modalContent = `<div class="nr-modal-container" class="modal">
<div class="modal-content">
<span class="close">×</span>
<p>Some text in the Modal..</p>
</div>
</div>`;
document.addEventListener("click",function(e){
e.preventDefault();
e.stopPropagation()
const modal = document.querySelector(".nr-modal-container");
if(e.target.classList.contains('close')){
console.log(e.target)
modal.classList.remove("visible");
modal.remove();
return false;
}
})
const shwoModal = function(){
document.body.innerHTML = modalContent;
const modal = document.querySelector(".nr-modal-container");
modal.classList.add("visible");
return false;
}
return {
deleteConfirm: function(data) {
shwoModal()
},
}
})();
document.addEventListener("click",function(e){
e.preventDefault();
e.stopPropagation()
if(e.target.classList.contains('open-modal-button')){
nrSanckbar.deleteConfirm()
}
})
.modal {
position: fixed;
z-index: 10;
padding-top: 100px;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0, 0, 0, 0.5);
display: none;
}
/* Modal Content */
.modal-content {
background-color: #fefefe;
margin: auto;
padding: 20px;
border: 1px solid #888;
width: 50%;
border-radius: 5px;
box-shadow: 0 24px 38px 3px rgba(60, 75, 100, 0.14);
display:none;
}
.close {
color: #aaaaaa;
float: right;
font-size: 28px;
font-weight: bold;
}
.close:hover,
.close:focus {
color: #000;
text-decoration: none;
cursor: pointer;
}
.visible {
display: block;
}
.visible > .modal-content {
display: block;
-webkit-animation: scale .3s ease-out;
-moz-animation: scale .3s ease-out;
}
#-webkit-keyframes scale {
0% { opacity: 0; -webkit-transform: scale(1.3); }
100% { opacity: 1; -webkit-transform: scale(1); }
}
#-moz-keyframes scale{
0% { opacity: 0; -moz-transform: scale(1.3); }
100% { opacity: 1; -moz-transform: tscale(1);}
}
<button class="open-modal-button">Open Modal</button>
Your button is being removed due to document.body.innerHTML = modalContent; (as inner HTML contains the button)
You should be able to do something like document.body.innerHTML += modalContent;
Or: document.body.insertAdjacentHTML( 'beforeend', modalContent);
In a gallery of images, it is possible to click on each image in order to enlarge it. The sources of the enlarged images are received from the background-image of the small ones. I want to create a previous and next button to these enlarged images.
I have done this previously for a set of images with separate divs. However, I have never done it with arrays. Here is my code.
var modal = document.getElementById("myModal");
var modalImg = document.getElementById("modalImg");
var imgArr = Array.from(document.querySelectorAll('.img-container .img'));
imgArr.forEach(function(img) {
img.onclick = function() {
var backgroundImage = img.style.backgroundImage.slice(4, -1).replace(/"/g, '');
modal.style.display = "flex";
modalImg.src = backgroundImage;
}
});
/* This is the part where I tried adding previous & next
functions, but it doesn't work and it makes the close
button not work either. */
/*
var prev = document.getElementsByClassName("prev");
var next = document.getElementsByClassName("next");
var index = 0;
imgArr[index] = modalImg.src;
next.addEventListener('click', nextImage);
function nextImage() {
for (i = 0; i < 10; i++) {
modalImg.src = imgArr[index + 1];
}
}
previous.addEventListener('click', previousImage);
function previousImage() {
for (i = 0; i < 10; i++) {
modalImg.src = imgArr[index - 1];
}
}
*/
// add caption
var captionText = document.getElementById("caption");
// close the modal
var span = document.getElementsByClassName("close")[0];
span.onclick = function() {
modal.style.display = "none";
}
.close {
position: absolute;
top: 15px;
right: 35px;
color: #f1f1f1;
font-size: 40px;
font-weight: bold;
transition: 0.3s;
}
.close:hover,
.close:focus {
color: #bbb;
text-decoration: none;
cursor: pointer;
}
.img {
display: block;
width: 200px;
height: 100%;
margin-right: 10px;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
cursor: pointer;
}
.img-container {
display: flex;
height: 100px;
min-height: 20rem;
}
.modal {
display: none;
position: fixed;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 100%;
box-sizing: border-box;
overflow: auto;
background-color: rgb(0, 0, 0);
background-color: rgba(0, 0, 0, 0.9);
justify-content: center;
align-items: center;
}
.modal-content {
margin: auto;
display: block;
width: 80%;
max-width: 700px;
max-height: 80%;
object-fit: contain;
-o-object-fit: contain;
animation-name: zoom;
animation-duration: 0.6s;
}
/* Next & previous buttons */
.prev,
.next {
cursor: pointer;
position: absolute;
top: 50%;
-moz-transform: translateY(-50%);
-ms-transform: translateY(-50%);
transform: translateY(-50%);
width: auto;
padding: 0.8rem;
color: #777;
font-weight: normal;
font-size: 18px;
transition: 0.6s ease;
border-radius: 0 3px 3px 0;
user-select: none;
-webkit-user-select: none;
z-index: 3;
}
.prev:hover,
.next:hover {
color: #000;
}
.next {
right: 0;
}
.prev {
left: 0;
}
#keyframes zoom {
from {
transform: scale(0)
}
to {
transform: scale(1)
}
}
<div class="img-container">
<div id="tehran" class="img" style="background-image: url(https://images.unsplash.com/photo-1524567492592-cee28084482e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=600&q=60)">
</div>
<div id="masuleh" class="img" style="background-image: url(https://images.unsplash.com/photo-1567317255448-8e6c04e22114?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=634&q=80)">
</div>
<div id="zanjan" class="img" style="background-image: url(https://images.unsplash.com/photo-1518727577784-f62f1115eefb?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1050&q=80)">
</div>
</div>
<!-- The Modal -->
<div id="myModal" class="modal">
<!-- Buttons -->
<span class="close">×</span>
<a class="prev">❮</a>
<a class="next">❯</a>
<!-- Modal Content -->
<img id="modalImg" class="modal-content">
<div id="caption"></div>
</div>
var modal = document.getElementById("myModal");
var modalImg = document.getElementById("modalImg");
var imgArr = Array.from(document.querySelectorAll('.img-container .img'));
var currentIndex = 0;
imgArr.forEach(function(img, i) {
img.onclick = function() {
currentIndex = i;
var backgroundImage = img.style.backgroundImage.slice(4, -1).replace(/"/g, '');
modal.style.display = "flex";
modalImg.src = backgroundImage;
}
});
var prev = document.getElementsByClassName("prev")[0];
var next = document.getElementsByClassName("next")[0];
next.addEventListener('click', nextImage);
function nextImage() {
currentIndex = (currentIndex+1)%imgArr.length;
var backgroundImage = imgArr[currentIndex].style.backgroundImage.slice(4, -1).replace(/"/g, '');
modalImg.src = backgroundImage
}
prev.addEventListener('click', previousImage);
function previousImage() {
currentIndex = (currentIndex+imgArr.length-1)%imgArr.length;
var backgroundImage = imgArr[currentIndex].style.backgroundImage.slice(4, -1).replace(/"/g, '');
modalImg.src = backgroundImage
}
// add caption
var captionText = document.getElementById("caption");
// close the modal
var span = document.getElementsByClassName("close")[0];
span.onclick = function() {
modal.style.display = "none";
}
.close {
position: absolute;
top: 15px;
right: 35px;
color: #f1f1f1;
font-size: 40px;
font-weight: bold;
transition: 0.3s;
}
.close:hover,
.close:focus {
color: #bbb;
text-decoration: none;
cursor: pointer;
}
.img {
display: block;
width: 200px;
height: 100%;
margin-right: 10px;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
cursor: pointer;
}
.img-container {
display: flex;
height: 100px;
min-height: 20rem;
}
.modal {
display: none;
position: fixed;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 100%;
box-sizing: border-box;
overflow: auto;
background-color: rgb(0, 0, 0);
background-color: rgba(0, 0, 0, 0.9);
justify-content: center;
align-items: center;
}
.modal-content {
margin: auto;
display: block;
width: 80%;
max-width: 700px;
max-height: 80%;
object-fit: contain;
-o-object-fit: contain;
animation-name: zoom;
animation-duration: 0.6s;
}
/* Next & previous buttons */
.prev,
.next {
cursor: pointer;
position: absolute;
top: 50%;
-moz-transform: translateY(-50%);
-ms-transform: translateY(-50%);
transform: translateY(-50%);
width: auto;
padding: 0.8rem;
color: #777;
font-weight: normal;
font-size: 18px;
transition: 0.6s ease;
border-radius: 0 3px 3px 0;
user-select: none;
-webkit-user-select: none;
z-index: 3;
}
.prev:hover,
.next:hover {
color: #000;
}
.next {
right: 0;
}
.prev {
left: 0;
}
#keyframes zoom {
from {
transform: scale(0)
}
to {
transform: scale(1)
}
}
<div class="img-container">
<div id="tehran" class="img" style="background-image: url(https://images.unsplash.com/photo-1524567492592-cee28084482e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=600&q=60)">
</div>
<div id="masuleh" class="img" style="background-image: url(https://images.unsplash.com/photo-1567317255448-8e6c04e22114?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=634&q=80)">
</div>
<div id="zanjan" class="img" style="background-image: url(https://images.unsplash.com/photo-1518727577784-f62f1115eefb?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1050&q=80)">
</div>
</div>
<!-- The Modal -->
<div id="myModal" class="modal">
<!-- Buttons -->
<span class="close">×</span>
<a class="prev">❮</a>
<a class="next">❯</a>
<!-- Modal Content -->
<img id="modalImg" class="modal-content">
<div id="caption"></div>
</div>
You can keep track of the currently clicked image, later you can increment/decrement the value based on which you can select image from the NodeList:
Please Note: You do not need Array.from() to implement forEach() on NodeList returned by querySelectorAll():
Try the following way:
var modal = document.getElementById("myModal");
var modalImg = document.getElementById("modalImg");
var imgArr = document.querySelectorAll('.img-container .img');
var curSrc;
imgArr.forEach(function(img, i) {
img.onclick = function() {
var backgroundImage = img.style.backgroundImage.slice(4, -1).replace(/"/g, '');
modal.style.display = "flex";
modalImg.src = backgroundImage;
curSrc = i;
}
});
var prev = document.querySelector(".prev");
var next = document.querySelector(".next");
next.addEventListener('click', nextImage);
function nextImage() {;
if(curSrc < imgArr.length - 1){
curSrc++;
modalImg.src = imgArr[curSrc].style.backgroundImage.slice(4, -1).replace(/"/g, '');
}
}
prev.addEventListener('click', previousImage);
function previousImage() {
if(curSrc>0){
curSrc--;
modalImg.src = imgArr[curSrc].style.backgroundImage.slice(4, -1).replace(/"/g, '');
}
}
// add caption
var captionText = document.getElementById("caption");
// close the modal
var span = document.getElementsByClassName("close")[0];
span.onclick = function() {
modal.style.display = "none";
}
.close {
position: absolute;
top: 15px;
right: 35px;
color: #f1f1f1;
font-size: 40px;
font-weight: bold;
transition: 0.3s;
}
.close:hover,
.close:focus {
color: #bbb;
text-decoration: none;
cursor: pointer;
}
.img {
display: block;
width: 200px;
height: 100%;
margin-right: 10px;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
cursor: pointer;
}
.img-container {
display: flex;
height: 100px;
min-height: 20rem;
}
.modal {
display: none;
position: fixed;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 100%;
box-sizing: border-box;
overflow: auto;
background-color: rgb(0, 0, 0);
background-color: rgba(0, 0, 0, 0.9);
justify-content: center;
align-items: center;
}
.modal-content {
margin: auto;
display: block;
width: 80%;
max-width: 700px;
max-height: 80%;
object-fit: contain;
-o-object-fit: contain;
animation-name: zoom;
animation-duration: 0.6s;
}
/* Next & previous buttons */
.prev,
.next {
cursor: pointer;
position: absolute;
top: 50%;
-moz-transform: translateY(-50%);
-ms-transform: translateY(-50%);
transform: translateY(-50%);
width: auto;
padding: 0.8rem;
color: #777;
font-weight: normal;
font-size: 18px;
transition: 0.6s ease;
border-radius: 0 3px 3px 0;
user-select: none;
-webkit-user-select: none;
z-index: 3;
}
.prev:hover,
.next:hover {
color: #000;
}
.next {
right: 0;
}
.prev {
left: 0;
}
#keyframes zoom {
from {
transform: scale(0)
}
to {
transform: scale(1)
}
}
<div class="img-container">
<div id="tehran" class="img" style="background-image: url(https://images.unsplash.com/photo-1524567492592-cee28084482e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=600&q=60)">
</div>
<div id="masuleh" class="img" style="background-image: url(https://images.unsplash.com/photo-1567317255448-8e6c04e22114?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=634&q=80)">
</div>
<div id="zanjan" class="img" style="background-image: url(https://images.unsplash.com/photo-1518727577784-f62f1115eefb?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1050&q=80)">
</div>
</div>
<!-- The Modal -->
<div id="myModal" class="modal">
<!-- Buttons -->
<span class="close">×</span>
<a class="prev">❮</a>
<a class="next">❯</a>
<!-- Modal Content -->
<img id="modalImg" class="modal-content">
<div id="caption"></div>
</div>
I am trying to build a menu that slides in and out with the press of a button. Also, when menu is opened, it should slide out when clicked any part of the screen.
So far I have managed to create everything except the slide out effect, now the slide just disappears, without moving from right to left.
var navBtn = document.getElementById("navBtn");
var navMenu = document.getElementById("navMenu");
var container = document.getElementById("container");
navBtn.addEventListener("click", showMenu);
container.addEventListener("click", hideMenu);
navMenu.style.display = "none";
function showMenu(){
if(navMenu.style.display !== "none"){
navMenu.style.display = "none"}
else{navMenu.style.display = "block", container.style.background = "rgba(0, 102, 199, 1)";}}
function hideMenu(){
if(navMenu.style.display = "block"){
navMenu.style.display = "none", container.style.background = "lightblue";}}
#main-container {
width: 350px;
height: 600px;
border: 1px solid black;
position: absolute;
overflow: hidden;
}
#container {
width: 350px;
height: 100%;
display: absolute;
z-index: 1;
background: rgba(0, 102, 199, 0.8);
}
#navBtn {
width: 50px;
height: 50px;
background: red;
position: absolute;
z-index: 999;
}
#navMenu {
width: 250px;
height: 100%;
background: blue;
position: absolute;
z-index: 9999;
top: 0;
animation-name: slidein;
animation-duration: .5s;
}
#-webkit-keyframes slidein {
0% {transform: translateX(-200px);}
100% {transform: translateX(0px);}
}
#navMenu.close {
animation-name: slideout;
animation-duration: .5s;
}
#-webkit-keyframes slideout {
0% {transform: translateX(0px);}
100% {transform: translateX(-200px);}
}
<div id="main-container">
<div id="navBtn"></div>
<div id="container">
<div id="navMenu"></div>
</div>
</div>
Maybe someone could show me a way to achieve this? Basically the slide in effect should be the same as the slide in, just in a reverse way.
function openNav() {
document.getElementById("mySidenav").style.width = "250px";
document.getElementById("main").style.marginLeft = "250px";
}
function closeNav() {
document.getElementById("mySidenav").style.width = "0";
document.getElementById("main").style.marginLeft = "0";
}
body {
font-family: "Lato", sans-serif;padding:40px;
}
.sidenav {
height: 100%;
width: 0;
position: fixed;
z-index: 1;
top: 0;
left: 0;
background-color: #B971BB;
overflow-x: hidden;
transition: 0.5s;
padding-top: 60px;
}
.sidenav a {
padding: 8px 8px 8px 32px;
text-decoration: none;
font-size: 25px;
color: #fff;
display: block;
transition: 0.3s;
}
.sidenav a:hover {
color: #f1f1f1;
}
.sidenav .closebtn {
position: absolute;
top: 0;
right: 25px;
font-size: 36px;
margin-left: 50px;
}
#main {
transition: margin-left .5s;
padding: 16px;
}
#media screen and (max-height: 450px) {
.sidenav {padding-top: 15px;}
.sidenav a {font-size: 18px;}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div id="mySidenav" class="sidenav">
×
About
Services
Clients
Contact
</div>
<div id="main">
<h2>Sidena Example</h2>
<p>Click on the element below to open the side navigation menu, and push this content to the right.</p>
<span style="font-size:30px;cursor:pointer" onclick="openNav()">☰ open</span>
</div>
html
<div id="main-container">
<div id="navBtn"></div>
<div id="container">
<div id="navMenu"></div>
</div>
</div>
jsCode
var navBtn = document.getElementById("navBtn");
var navMenu = document.getElementById("navMenu");
var container = document.getElementById("container");
navBtn.addEventListener("click", showMenu);
container.addEventListener("click", hideMenu);
//navMenu.style.display = "none"; // remove the display: none as you cannot animate display block to display none
function showMenu() {
container.classList.add('open');
}
function hideMenu() {
container.classList.remove('open');
}
and the css
#main-container {
width: 350px;
height: 600px;
border: 1px solid black;
position: absolute;
overflow: hidden;
}
#container {
width: 350px;
height: 100%;
z-index: 1;
background: rgba(0, 102, 199, 0.8);
transition: all 0.3s ease-in-out;
}
#navBtn {
width: 50px;
height: 50px;
background: red;
position: absolute;
z-index: 999;
}
#navMenu {
width: 250px;
height: 100%;
background: blue;
position: absolute;
z-index: 9999;
top: 0;
left: -250px;
transition: all 0.3s ease-in-out;
}
#container.open {
background: rgba(0, 102, 199,1);
}
#container.open #navMenu {
left: 0;
}
Looks like you attached the slide-out animation to a .close class that you never apply to the menu.
The easiest way to do this and to have more control is to add a class to the container, when the menu should be opened. afterwards just use css and left position along with transition to animate the menu. I'll provide code in a minute
I am trying to make my custom alert fade in and out. I am altering its visibility by adding and removing the class "show" to the toast-container div.It fades in fine however it fades out just momentarily before immediately reappearing again. Using inspect element it shows that it encountered this error:
job-application-form.php:463 Uncaught TypeError: Cannot read property 'classList' of undefined
at job-application-form.php:463
which is at the function setTimeout(function(){ cont.classList.remove("show")}, 3000);and the "show" class was not removed from the div.
I do not understand why I am getting this error or how to fix it. Please help.
Div
<div id="toast-container" class="toast-top-right"><div id="toast-type" class="toast" aria-live="assertive" style=""><div id="snackbar">message</div></div></div>
Function:
<script>
function Toast(message, messagetype)
{
var cont = document.getElementById("toast-container").classList.add("show");
var type = document.getElementById("toast-type");
type.className += " " + messagetype;
var x = document.getElementById("snackbar");
x.innerHTML = message;
setTimeout(function(){ cont.classList.remove("show")}, 3000);
}
</script>
Function call in php
$Toast = "We have <strong>successfully</strong> received your message and will get back to you as soon as possible.";
$Error = "toast-error";
$Success = "toast-success";
echo "<script type='text/javascript'>Toast('$Toast', '$Success');</script>";
CSS:
#snackbar {
word-wrap: break-word;
}
#toast-container {
visibility: hidden;
position: fixed;
z-index: 999999;
-webkit-animation: fadein 0.5s, fadeout 0.5s 2.5s;
animation: fadein 0.5s, fadeout 0.5s 2.5s;
}
#toast-container.show {
visibility: visible;
}
#toast-container * {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
.toast-top-right {
top: 12px;
right: 12px;
}
#toast-container > div {
position: relative;
pointer-events: auto;
overflow: hidden;
margin: 0 0 6px;
padding: 20px 25px;
width: 300px;
-moz-border-radius: 3px 3px 3px 3px;
-webkit-border-radius: 3px 3px 3px 3px;
border-radius: 3px 3px 3px 3px;
background-repeat: no-repeat;
-moz-box-shadow: 0 0 12px #999999;
-webkit-box-shadow: 0 0 12px #999999;
box-shadow: 0 0 12px #999999;
color: #FFFFFF;
opacity: 0.8;
-ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80);
filter: alpha(opacity=80);
}
.toast {
background-color: #030303;
}
.toast-success {
background-color: #51A351;
}
.toast-error {
background-color: #BD362F;
}
#-webkit-keyframes fadein {
from {bottom: 0; opacity: 0;}
to {bottom: 30px; opacity: 1;}
}
#keyframes fadein {
from {bottom: 0; opacity: 0;}
to {bottom: 30px; opacity: 1;}
}
#-webkit-keyframes fadeout {
from {bottom: 30px; opacity: 1;}
to {bottom: 0; opacity: 0;}
}
#keyframes fadeout {
from {bottom: 30px; opacity: 1;}
to {bottom: 0; opacity: 0;}
}
Problem is in your variable cont which isn't correctly initialized.
Change this line:
var cont = document.getElementById("toast-container").classList.add("show");
to this:
var cont = document.getElementById("toast-container");
cont.classList.add("show");
Dean Strydom, you are almost there. Actually, the error message describes exactly the issue.
var cont = document.getElementById("toast-container").classList.add("show");
in this line, it is your expectation that cont is the toast-container but it isn't. It is the result of classList.add which is just undefined.
By the time, you use cont again to remove the show class, it will attempt to access classList from cont which is in fact undefined.
In summary,
var cont = document.getElementById("toast-container"); // simply save this element first
cont.classList.add("show"); // then manipulate afterwards
Here is a running snippet. Modified to prompt on button click. Hope this helps you understand the issue better. Just play around the styling/animation.
let animating = false;
function Toast(message, messagetype) {
var cont = document.getElementById("toast-container");
cont.classList.add("show"); // correct manipulation
var type = document.getElementById("toast-type");
type.className += " " + messagetype;
var x = document.getElementById("snackbar");
x.innerHTML = message;
setTimeout(function() {
cont.classList.remove("show"); // access it again here
animating = false;
}, 3000);
}
let btn = document.querySelector('button');
btn.addEventListener('click', function(e) {
if (animating) {
return;
}
animating = true;
Toast("hi there", "toast-success");
});
#snackbar {
word-wrap: break-word;
}
#toast-container {
visibility: hidden;
position: fixed;
z-index: 999999;
-webkit-animation: fadein 0.5s, fadeout 0.5s 2.5s;
animation: fadein 0.5s, fadeout 0.5s 2.5s;
}
#toast-container.show {
visibility: visible;
}
#toast-container * {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
.toast-top-right {
top: 12px;
right: 12px;
}
#toast-container>div {
position: relative;
pointer-events: auto;
overflow: hidden;
margin: 0 0 6px;
padding: 20px 25px;
width: 300px;
-moz-border-radius: 3px 3px 3px 3px;
-webkit-border-radius: 3px 3px 3px 3px;
border-radius: 3px 3px 3px 3px;
background-repeat: no-repeat;
-moz-box-shadow: 0 0 12px #999999;
-webkit-box-shadow: 0 0 12px #999999;
box-shadow: 0 0 12px #999999;
color: #FFFFFF;
opacity: 0.8;
-ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80);
filter: alpha(opacity=80);
}
.toast {
background-color: #030303;
}
.toast-success {
background-color: #51A351;
}
.toast-error {
background-color: #BD362F;
}
#-webkit-keyframes fadein {
from {
bottom: 0;
opacity: 0;
}
to {
bottom: 30px;
opacity: 1;
}
}
#keyframes fadein {
from {
bottom: 0;
opacity: 0;
}
to {
bottom: 30px;
opacity: 1;
}
}
#-webkit-keyframes fadeout {
from {
bottom: 30px;
opacity: 1;
}
to {
bottom: 0;
opacity: 0;
}
}
#keyframes fadeout {
from {
bottom: 30px;
opacity: 1;
}
to {
bottom: 0;
opacity: 0;
}
}
<div id="toast-container" class="toast-top-right">
<div id="toast-type" class="toast" aria-live="assertive" style="">
<div id="snackbar">message</div>
</div>
</div>
<button>Toast!</button>
https://codepen.io/aldnav/pen/gqbEQE
cont is not referencing the element you are looking for. classList.add("show") does not return anything and in JavaScript if function does not return any thing explicitly, the function by default returns undefined. Thus the variable actually holds undefined and you get the error.
Try the following:
<script>
function Toast(message, messagetype)
{
var cont = document.getElementById("toast-container")
cont.classList.add("show");
var type = document.getElementById("toast-type");
type.className += " " + messagetype;
var x = document.getElementById("snackbar");
x.innerHTML = message;
setTimeout(function(){ cont.classList.remove("show")}, 3000);
}
</script>
Demo of the issue:
var cont = document.getElementById("toast-container").classList.add("show");
console.log(cont);
.show{
color: red;
}
<div id="toast-container">Test Container</div>