Memory leak with addeventlistener() - javascript

I have a modal box which opens on a button click, when the modal is visible, if the area outside the content box is clicked, then the modal should disappear.
The issue i'm having is that my modal keeps creating the modal and not being completely removed, thus creating a memory leak.
The class show-login-modal handles the visibility of the modal.
let x = 1;
function LoginPopup(){
let modal = document.getElementById('modal');
modal.classList.add('show-login-modal');
let xx = x++;
function _removeModal() {
modal.classList.remove('show-login-modal');
modal.removeEventListener("click", this);
}
modal.addEventListener('click', function(event) {
console.log(xx);
if (event.target === modal) {
_removeModal();
}
});
}
I included the console.log for reference.
What is the best way to fix this?

removeEventListener is being used incorrectly, it needs to be invoked with a named function. So, in your case, you'd want to move the event target detection inside of _removeModal
function _removeModal(event){ if (event.target === this){ ... modal.removeEventListener('click', _removeModal)} }
modal.addEventListener('click', _removeModal)

Related

How to control multiple modal boxes on one webpage?

I'm currently rebuilding my portfolio and have cards for each of the projects that I've worked on, the idea being that when the user clicks on a card it opens a modal box containing more information about the project and a link to it.
Unfortunately, I can't figure out how to have multiple modal boxes on the same page, without writing a new block of code for every single box. I'm guessing I'll need some sort of for loop but I've been experimenting all day and can't find anything that works.
This is the JavaScript I have so far:
var modal = document.getElementsByClassName("modal")[1];
var card = document.getElementsByClassName("card")[1];
// When the user clicks on the card, open the modal box
card.onclick = function() {
modal.style.display = "block";
}
// When the user clicks anywhere outside of the modal box, close it
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = "none";
}
}
Many thanks!
Add a class in your modal something like .modal;
window.onclick = function(event) {
if (event.target.classList.contains('modal')) {
event.target.style.display = 'none';
}
}

Event listener does not seem to recognise my class?

I have a mobile menu that opens when the open menu button is clicked. I am trying to add a trap focus functionality to the menu when it is open so that users cannot access outside of my menu with a keyboard when tabbing.
I have used an event listener to listen for tab and shift tab keydown events in the menu. The logic is that if the active element does not have a class that only my menu items have then to lock focus back onto the close button of my menu.
Problem is that the focus gets stuck on my close button instantly and I cannot move it (even though it has the class "in-listview"). I realise that my code may not be the best way to implement this feature but for now I would just like to know why my class does not seem to be recognised and I can tidy up after. My app is built using ReactJS.
openNav = () => {
const listView = document.querySelector(".listview");
listView.classList.remove('closeMobMenu');
listView.style.visibility = "visible";
listView.classList.add('openMobMenu');
document.addEventListener('keydown', this.trapTabMobMenu)//Maybe move this to componentDidMount()?
}
trapTabMobMenu = (event) => {
if(event.keyCode === 9) { // if the tab key is pressed in the mobile menu
const closeBtn = this.closeBtn;
let activeElement = document.activeElement;
if(event.shiftKey) { // shift-tab
event.preventDefault();
//if focused element does not have class in-list-view
if(!activeElement.classList.contains("in-listview")) {
closeBtn.focus();
}
} else { // normal tab
event.preventDefault();
if(!activeElement.classList.contains("in-listview")) {
closeBtn.focus();
}
}
}
if(event.keyCode === 27) {
this.closeNav();
}
}
<button ref={(close) => { this.closeBtn = close; }} className="closebtn in-listview" onClick={closeNav} onKeyPress={handleKeyPress} tabIndex="2">×</button>
document.activeElement is not set until after the focus event has been completed, so the above code is not performing your logic on the new element that is firing the onFocus event.
You need to change document.activeElement to be event.target then perform your logic.
https://developer.mozilla.org/en-US/docs/Web/API/DocumentOrShadowRoot/activeElement

modal won't close on mobile

I'm using JS modal (no jquery), since I have some issues with that approach...
Everything works good except that on mobile user can't close it.
var modal = document.getElementById('myModal');
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = "none";
}
};
It is probably related to that touch that I'm missing...
I tried with jquery like this:
$(document).ready(function(){
$(modal).on('click touchstart', function() {
modal.style.display = "none";
});
});
The problem here is that if user clicks inside the modal, it will also disappear...
What I need is that when user clicks only outside, modal should disappear...
Any ideas how can I solve this issue?
Thanks.
instead of registering click on the target, register on the document and then check to see that the mouse wasn't inside of the target
$(document).on ('mouseup touchstart', function (e)
{
var container = $("#myModal");
if (!container.is(e.target) // if the target of the click isn't the container...
&& container.has(e.target).length === 0) // ... nor a descendant of the container
{
container.hide();
}
});
You can listen for the 'mousedown' event on the document, then check if the modal is in the event path. If it's not, then hide the modal. If it is, then do nothing.
var myModal = document.getElementById('myModal');
document.addEventListener('mousedown', function(e)
{
if (e.path.indexOf(myModal) == -1)
myModal.hidden = true;
});
Have you tried to use contains ?
I just tested it on iOS safari and chrome, it works correctly
please check out the demo,
when you click the yellow part, it still exists
however, when you click the pink part, the whole modal will hide
JS Bin
code in JS Bin
var pa = document.querySelector('#modal-overlay');
var ch = document.querySelector('#modal-container');
pa.addEventListener('click', function(e) {
if (!ch.contains(e.target)) {
pa.style.display = 'none';
}
});

One div disappears, another div appears at the same time when click the button in CSS, JSP

I'm totally new to Web programming.
I've just learned HTML and CSS, but have no any knowledge about Java Script.
Situation what i have is like this.
There are two buttons and two divs.
If one button is clicked, the div related in that button appears.(visibility:visible)
And click same button one more, div is disappear.
So now when I click buttons at once, two divs are overlapped.
Now I want to build an effect like this.
If one button already clicked(one div is appeared already), and click another
button then first div is disappeared and another div appear at the same time.(replace position)
<script>
function show1() {
document.getElementById("div1").classList.toggle("show");
}
window.onclick = function(event) {
if (!event.target.matches('.button1'))
var dropdowns = document.getElementsByClassName("div1_pop");
}
function show2() {
document.getElementById("div2").classList.toggle("show");
}
window.onclick = function(event) {
if (!event.target.matches('.button2'))
var dropdowns = document.getElementsByClassName("div2_pop");
}
</script>
I'm totally toddler when it comes to Java Script. So I just copy&paste that
script section. Can I get an appear/disappear effect fixing that script?
One possible solution is to show one dive and hide the second div.
function show1() {
document.getElementById("div1").style.display = "block";
document.getElementById("div2").style.display = "none";
}
window.onclick = function(event) {
if (!event.target.matches('.button1'))
var dropdowns = document.getElementsByClassName("div1_pop");
}
function show2() {
document.getElementById("div1").style.display = "none";
document.getElementById("div2").style.display = "block";
}
window.onclick = function(event) {
if (!event.target.matches('.button2'))
var dropdowns = document.getElementsByClassName("div2_pop");
}
</script>

A Double Click event also triggers Click event in EaselJS

Adding Event Listener
function Solitaire() {
this.table.addEventListener("click", this.handleClick.bind(this));
this.table.addEventListener("dblclick", this.handleDoubleClick.bind(this));
}
Handling Event
Solitaire.prototype.handleDoubleClick = function(event) {
console.log("DoubleClick");
};
Solitaire.prototype.handleClick = function(event) {
console.log("Click");
};
Expected output (in console) on a double click event
DoubleClick
But the output I get in console:
Click
Click
DoubleClick
I don't know about easeljs, but I can tell you about how it is done in jQuery, where you need to "hack" it to make it actually work.
var DELAY = 500;
$('#my_element').on('click', function(e){
++clicks; // Count the clicks
if(clicks === 1){
// One click has been made
var myTimerToDetectDoubleClick = setTimeout(function(){
console.log('This was a single click');
doStuffForSingleClick();
clicks = 0;
}, DELAY);
} // End of if
else{
// Someone is clicking pretty damn fast, they probably mean double click :p
clearTimeout(myTimerToDetectDoubleClick);
doStuffForDoubleClick();
clicks = 0;
}
}).on('dblclick', function(evt){
evt.preventDefault(); // cancel system's default double click
});
The basic essence will remain the same for event handling for easeljs. You can imitate this behaviour accordingly there.

Categories