How to remove a class when its element is not in view? - javascript

In plain js I want to remove a class when the user scroll down from it. (basically toggle when in view it appear when it is not in view it disappear)
I have to code to add the class when scrolled in view:
const appearOnScroll = new IntersectionObserver(function(entries, appearOnScroll){
entries.forEach(entry =>{
if(!entry.isIntersecting){
return;
}else{
entry.target.classList.add("appear");
appearOnScroll.unobserve(entry.target);
}
})
}, appearOptions);
faders.forEach(fader =>{
appearOnScroll.observe(fader)
})
How can I remove the class when you scroll out?

Related

Is it possible to add multiple classes with one toggle event?

I have a div with one toggle event that add a class to it and I wanna know if is it possible to add more than one class with classList.toggle
let navLinks = document.querySelectorAll('.nav-link');
navLinks.forEach(navLink => {
navLink.onclick = e => {
event.target.classList.toggle('open')
}
})
This's my code adding a class to the div.

class toggle is adding the same class instead of toggling

I am trying to switch between a leaflet map and a list. It is working fine untill the code is compiled by webpack. After clicking on an item the map shows up as it should. But when I close the map with the close button, I have map.remove() which removes the map but the class toggles do not toggle but instead they add the already existing class.
The function below runs to open the map and toggles correctly. And it runs when closing the map, but then the same toggles do not run correctly and adds the same class, as you can see in the photo below. The menu class is also duplicated which it should not.
Before I compile with webpack it does run correctly. Thanks!
const mapHandler = async id => {
let brewery;
if (id) {
brewery = await fetchBreweries.get('/' + id);
if (!brewery.latitude || !brewery.longitude) {
alert('Sorry, this entry has no coordinates.');
return;
};
};
if (!id) {
//no id means we are clicking the closehandler, so enable buttons in footer and remove the map
footerBtns.map(btn => btn.disabled = false);
//remove it before toggling classes or it will throw the can't find it error
if (map) map.remove();
};
mapEl.classList.toggle('not-visible');
list.classList.toggle('not-visible');
mapEl.classList.toggle('visible');
list.classList.toggle('visible');
if (!id) return;
//there is an id, so we are going to build the map to show it
//disable buttons in the footer so we cannot click on them when the map is shown
footerBtns.map(btn => btn.disabled = true);
if (aroundMyLocation) {
//if above flag is true than we want to build the map, show own location and then fly to brewery location
buildMap(myLocation);
setTimeout(() => {
map.flyTo([brewery.latitude, brewery.longitude], 12, {duration: 3})
}, 800);
setTimeout(() => {
L.marker([brewery.latitude, brewery.longitude])
.addTo(map)
.bindPopup(brewery.name)
.openPopup();
}, 1200);
} else {
//flag is false so we only want to show the brewery location
buildMap({lat: brewery.latitude, lng: brewery.longitude});
L.marker([brewery.latitude, brewery.longitude])
.addTo(map)
.bindPopup(brewery.name)
.openPopup();
};
//show brewery details in bottom right box
details.innerHTML = `
<h3>${brewery.name}</h3>
<p>${brewery.phone || 'number unknown'}</p>
<p>${brewery.street || 'street unknown'}</p>
<p>${brewery.city || 'city unknown'}</p>
`;
};
My script was being added twice with webpack. After adding inject: false to HtmlWebpackPlugin in my config file it was running as it should. I was trying to do a simple project so I could focus on learning webpack, serviceworkers and testing. A bit too much all at once probably...

Toggle Switch correctly removes css class on false but doesn't put the class back on when true

Using a Bootstrap5 toggle switch (which is basically just a checkbox) to toggle on and off lines in a grid. I have it set up so if the toggle is true then add the class which adds lines for the grid and if it's false then remove class and the lines. When I toggle off the class that holds the style for the line gets removed correctly but when I toggle on then the class doesn't come back and toggle the lines on. I am also using a forEach() to loop through all the divs.
I have console.log within and they fire for each toggle so I am not sure what I am missing. Here is the code
JS
let gridToggleSwitch = document.querySelector("#gridToggle")
gridToggleSwitch.addEventListener('change', () => {
let boxList = document.querySelectorAll('.box')
let toggleChoice = gridToggleSwitch.checked
if(toggleChoice == true) {
console.log("LINES")
boxList.forEach((e) => {
console.log(e)
e.classList.add('box')
})
} else if (toggleChoice == false) {
console.log('NO LINES')
boxList.forEach((e) => {
console.log(e)
e.classList.remove('box')
})
} else {
console.log('woops')
}
})
CSS:
.box {
border: 1px solid black;
}
SOLVED:
since the grid can change dynamically I needed to also dynamically add an ID to the divs for the grid and instead of using the forEach() for the classes I looped through the ID and added/removed the border style

Reusable javascript component issue

I have a woking accessible responsive navigation which for DEMO perpuses I have to make it reusable so I can show different sort of senarios. However tho, the click burger menu is not working.
This header with responsive navigation should work indipenently multiple times.
On click and matchMedia
typial responsive nav behavious with an extra touch of matchMedia in case user moves the window.
open navigation on click and remove navigation if > 900
navigation remove Attribute hidden on desktop and on click.
All of this should work multiple times.
if (navBlocks.length > 0){
Array.prototype.forEach.call(navBlocks, function(el) {
the forEach function shoud do the work right? how come is not really working?
DEMO HERE
const navBlocks = document.querySelectorAll('.nav-container');
const nav = document.querySelector('.sliding-nav');
const menu = document.querySelector(".sliding-nav ul");
const toggleMenu = document.querySelector(".nav-container .nav-cta");
const mediaQuery = window.matchMedia('(min-width: 900px)');
let isMenuOpen = false;
if (navBlocks.length > 0) {
Array.prototype.forEach.call(navBlocks, function(el) {
el.addEventListener('click', e => {
e.preventDefault();
isMenuOpen = !isMenuOpen;
toggleMenu.setAttribute('aria-expanded', String(isMenuOpen));
menu.hidden = !isMenuOpen;
if (isMenuOpen) {
nav.classList.add('is-open');
document.body.classList.add("is-no-scroll", "is-fixed");
//console.log(isMenuOpen);
} else {
nav.classList.remove('is-open');
document.body.classList.remove("is-no-scroll", "is-fixed");
//console.log(!isMenuOpen);
}
});
function handleTabletChange(e) {
// Check if the media query is true
if (e.matches) {
toggleMenu.setAttribute("aria-expanded", false);
menu.removeAttribute("hidden");
nav.classList.remove('is-open');
document.body.classList.remove("is-no-scroll", "is-fixed");
} else {
toggleMenu.setAttribute("aria-expanded", false);
//nav.removeAttribute("aria-expanded");
}
}
// Register event listener
mediaQuery.addListener(handleTabletChange);
// Initial check
handleTabletChange(mediaQuery);
});
}
I think you should do something like this,
add event listener on burger menu icon to toggle an active class in nav bar and you should write css for that active class that if nav contains "active" class it should be set to display or else it should display none!

InboxSDK - make sidebarContentPanel collapsed after it's added to threadView

I'm using InboxSDK to add sidebar to thread view on GMail.
I do it like this:
InboxSDK.load(2, 'MY_KEY').then(sdk => {
sdk.Conversations.registerThreadViewHandler(threadView => {
const el = document.createElement("div");
el.id = 'mySidebar';
ReactDOM.render(<App />, el);
threadView.addSidebarContentPanel({
title: 'Sidebar Example',
iconUrl:chrome.extension.getURL('icon.png'),
hideTitleBar:true,
el:el
});
});
});
But I couldn't find any setting in InboxSDK docs that would enable me to show this panel as collapsed after it's created. Is it possible, or should I do it the dirty way, by adding/removing classes from elements manually?
How about trigger a click event on the button programmatically if the sidebar is opened?
if ($('.companion_app_sidebar_wrapper_visible').length > 0) {
$('.sidebar_thread_iconArea button[data-tooltip="Sidebar Example"]').trigger('click');
}

Categories

Resources