So previously I asked your help to execute a behaviour for when clicking a container div, said div would change height, clicking it again would revert it back to normal, as would clicking a sibling container div.
I also added code for when clicking said div, the img inside would change data-src.
This img div (not the container) has a sibling that is just text. It would change state through css, when the container div is clicked, a bit like the container div itself.
When adding the code for the data-src change, I lost this ability and cant find out why.
Can you help me?
This is my code:
const allImages = document.querySelectorAll('.containertira .imgclasstosize');
const allContainers = document.querySelectorAll('.containertira');
allContainers.forEach(el => {
el.addEventListener('click', function(event) {
const thisImg = el.querySelector('.imgclasstosize');
const thisTxt = el.querySelector('.centered');
const sibling = thisImg.nextElementSibling; // Get the next sibiling
const bigSrc = thisImg.dataset.srcBig;
const allOtherImages = Array.from(allImages).filter(img => {
return img !== thisImg;
});
const isBig = thisImg.classList.contains('big');
1
if (isBig) {
thisImg.classList.remove('big');
thisTxt.classList.remove('left');
// reset to the small image URL
thisImg.src = thisImg.dataset.smallSrc;
} else {
// save the small image URL first:
if (!thisImg.dataset.smallSrc) {
thisImg.dataset.smallSrc = thisImg.src;
}
// change to the big image URL:
thisImg.src = bigSrc;
thisImg.classList.add('big');
thisTxt.classList.add('left');
sibling.classList.remove('hide');
}
allOtherImages.forEach(img => {
img.classList.remove('big');
// reset to the small image URL
if (img.dataset.smallSrc) {
img.src = img.dataset.smallSrc;
}
img.nextElementSibling.classList[isBig ? 'remove' : 'add']("hide");
});
});
}
);
.imgclasstosize{
width: 100%;
object-fit: cover;
position: relative;
}
img.imgclasstosize {
height: 80px;
border: 1px solid gray;
transition : 1.5s all ease;
}
img.imgclasstosize.big {
height: 100%;
transition: 1.5s all ease;
width: 70vw;
margin-left: auto;
}
.containertira {
position: relative;
text-align: center;
color: white;
display: flex;
justify-content: space-between;
}
.imgclasstosize {
transition: all ease 0.5s;
}
.imgclasstosize.big {
/* transform: scale(1.1); */
}
.centered {
opacity: 1;
transition: all ease 0.5s;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-family: 'blacker_pro_displayregular';
padding-top: 10px;
/* background: linear-gradient(90deg, rgba(33,37,41,1) 0%, rgba(255,255,255,0) 50%); */
color: white;
padding-left: 10px;
padding-bottom: 6.5px;
font-size: 5vh;
display:block;
pointer-events: none;
}
#media screen and (max-width: 960px) {.centered {font-size: 4.6vh;}}
#media screen and (max-width: 500px) {.centered {font-size: 3.5vh;}}
#media screen and (max-width: 375px) {.centered {font-size: 3vh;}}
.centered.left{
top: 0%;
left: 0%;
transform: translate(0%, 0%);
color: black;
padding-left: 10px;
padding-bottom: 6.5px;
transition: all ease 0.5s;
font-size: 7vh;
}
.imgclasstosize.big+.centered.hide {
opacity: 0;
}
<div class="containertira">
<img id="primeiraimagem" class="imgclasstosize" src="//images.impresa.pt/expresso/2021-07-23-1---Minho.png-0c586cc8" data-src-big="//images.impresa.pt/expresso/2021-07-23-960px_minho.png-3938db2f">
<div class="centered">Minho</div>
</div>
<br>
<div class="containertira">
<img id="primeiraimagem" class="imgclasstosize" src="//images.impresa.pt/expresso/2021-07-23-1---Minho.png-0c586cc8" data-src-big="//images.impresa.pt/expresso/2021-07-23-960px_minho.png-3938db2f">
<div class="centered">Minho</div>
</div>
Best regards everyone.
I can't seem to reproduce your error. Tried copying your code and pasting it on a separated HTML file and everything worked.
If you execute this snippet and look at the console, you will see that the classes and properties are changing accordingly to your code.
Maybe your code is executing before some library causing it to not execute something?
const allImages = document.querySelectorAll('.containertira .imgclasstosize');
const allContainers = document.querySelectorAll('.containertira');
allContainers.forEach(el => {
el.addEventListener('click', function(event) {
const thisImg = el.querySelector('.imgclasstosize');
const thisTxt = el.querySelector('.centered');
const sibling = thisImg.nextElementSibling; // Get the next sibiling
const bigSrc = thisImg.dataset.srcBig;
const allOtherImages = Array.from(allImages).filter(img => {
return img !== thisImg;
});
const isBig = thisImg.classList.contains('big');
1
if (isBig) {
thisImg.classList.remove('big');
thisTxt.classList.remove('left');
// reset to the small image URL
thisImg.src = thisImg.dataset.smallSrc;
} else {
// save the small image URL first:
if (!thisImg.dataset.smallSrc) {
thisImg.dataset.smallSrc = thisImg.src;
}
// change to the big image URL:
thisImg.src = bigSrc;
thisImg.classList.add('big');
thisTxt.classList.add('left');
sibling.classList.remove('hide');
}
allOtherImages.forEach(img => {
img.classList.remove('big');
// reset to the small image URL
if (img.dataset.smallSrc) {
img.src = img.dataset.smallSrc;
}
img.nextElementSibling.classList[isBig ? 'remove' : 'add']("hide");
});
});
}
);
.containertira {border:1px black solid;}
<div class="containertira">
<img id="primeiraimagem" class="imgclasstosize" src="img/Tiras/1 - Minho.png" data-src-big="img/INFO joao/joao 2/joao 2/960 px/960px_minho.png">
<div class="centered">Minho</div>
</div>
<div class="containertira">
<img id="primeiraimagem" class="imgclasstosize" src="img/Tiras/1 - Minho.png" data-src-big="img/INFO joao/joao 2/joao 2/960 px/960px_minho.png">
<div class="centered">Minho2</div>
</div>
<div class="containertira">
<img id="primeiraimagem" class="imgclasstosize" src="img/Tiras/1 - Minho.png" data-src-big="img/INFO joao/joao 2/joao 2/960 px/960px_minho.png">
<div class="centered">Minho3</div>
</div>
<div class="containertira">
<img id="primeiraimagem" class="imgclasstosize" src="img/Tiras/1 - Minho.png" data-src-big="img/INFO joao/joao 2/joao 2/960 px/960px_minho.png">
<div class="centered">Minho4</div>
</div>
Related
Ok... I'm struggling here. I'm particularly new at JavaScript and am trying to fetch data from the Art Institute of Chicago's API. My goal is to display the information for a particular piece of art in a modal window after clicking on the relevant artwork. I've gotten the CSS and HTML down, I think. Everything displays properly as far as the images and titles and such. However, when I click the image to open the modal, all I can get to display is the Art itself.
I've found a similar question on here and tried some of its code, but their solution didn't quite get me to where I need to be.
Here's my HTML:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="index.css">
<script src="index.js" defer></script>
<title>Art Institute of Chicago API</title>
</head>
<body>
<h1>From the Art Institute of Chicago:<br>A Sampling of Monet, Van Gogh, and Hokusai</h1>
<div class="container">
<!-- ARTic Banner -->
<div class="gallery-container w-4 h-3">
<div class="gallery-item">
<div class="image banner" onclick="openInNewTab('https:/\/www.artic.edu');">
<img src="/images/bannerArtIC.jpg"
alt="Art Institute of Chicago banner">
</div>
<div class="text">
The Art Institute of Chicago
</div>
</div>
</div>
<!-- Fig 1 - Monet: Water Lilies -->
<div class="gallery-container w-2 h-3">
<div class="gallery-item">
<div class="image" id="16568">
<img src="images/monetWaterLilies_1933.1157.jpg"
alt="Painting of a pond seen up close spotted with thickly
painted pink and white water lilies and a shadow across the
top third of the picture."
onclick="openModal(event); event.stopPropagation(); getArtwork(this.id, event)">
</div>
<div class="text">
Claude Monet:<br>Water Lilies
</div>
</div>
</div>
<!-- Fig 2 - Van Gogh: Self Portrait -->
<div class="gallery-container w-2 h-6">
<div class="gallery-item">
<div class="image" id="80607">
<img src="images/vanGoghSelfPortrait_1954.326.jpg"
alt="Painting of a red-haired, bearded man with light skin,
painted in short brushstrokes and multicolored dots. The
background is likewise a mass of small, closely spaced colored
dots, these in green, blue, and red-orange."
onclick="openModal(event); event.stopPropagation(); getArtwork(this.id, event)">
</div>
<div class="text">
Vincent Van Gogh:<br>Self Portrait
</div>
</div>
</div>
<!-- Fig 3 - Monet: Water Lily Pond -->
<div class="gallery-container w-4 h-3">
<div class="gallery-item">
<div class="image" id="87088">
<img src="images/monetWaterLilyPond_1933.441.jpg"
alt="Painting of a small pond dense with pink water lilies,
their roots visible through the water, a railed footbridge
arching over the pond and lush, dark green folliage surrounding
it."
onclick="openModal(event); event.stopPropagation(); getArtwork(this.id, event)">
</div>
<div class="text">
Claude Monet:<br>Water Lily Pond
</div>
</div>
</div>
<!-- Fig 4 - Van Gogh: The Poet's Garden -->
<div class="gallery-container w-2 h-3">
<div class="gallery-item">
<div class="image" id="14586">
<img src="images/vanGoghThePoetsGarden_1933.433.jpg"
alt="Lush tall grasses with small white flowers foreground a
grove of bushy trees of varying types and heights, their leaves
ranging from deep green to golden. Beneath a dense and heavy
yellow sky, a small blue triangle suggesting a mountain peak
crests above the treeline at far left."
onclick="openModal(event); event.stopPropagation(); getArtwork(this.id, event)">
</div>
<div class="text">
Vincent Van Gogh:<br>The Poet's Garden
</div>
</div>
</div>
<!-- Fig 5 - Hokusai: Under the Wave Off Kanagawa -->
<div class="gallery-container w-4 h-3">
<div class="gallery-item">
<div class="image" id="24645">
<img src="images/hokusaiUnderTheWaveOffKanagawa_1925.3245.jpg"
alt="A crashing wave looms over two small ships, Mount Fuji
in the background."
onclick="openModal(event); event.stopPropagation(); getArtwork(this.id, event)">
</div>
<div class="text">
Katsushika Hokusai:<br>Under the Wave Off Kanagawa
</div>
</div>
</div>
<!-- Fig 6 - Hokusai: Chrysanthemums and Bee -->
<div class="gallery-container w-2 h-6">
<div class="gallery-item">
<div class="image" id="25110">
<img src="images/hokusaiChrysanthemumsAndBee_1925.3373.jpg"
alt="A color woodblock print of pink, orange and yellow
chrysanthemums. In the upper rihgt a tiny bee flies above the
flowers. Signature and seals in the lower left corner."
onclick="openModal(event); event.stopPropagation(); getArtwork(this.id, event)">
</div>
<div class="text">
Katsushika Hokusai:<br>Chrysanthemums and Bee
</div>
</div>
</div>
<!-- div for modal -->
<div id="myModal" class="modal">
<span class="closebtn" onclick="closeModal(event)">×</span>
<img class="modal-content" id="expandedImg">
<div id="caption">
</div>
</div>
</div>
</body>
</html>
And here's my JS (with additions from answers found on stack overflow):
// function to open the AIC homepage in new tab
function openInNewTab(url) {
var win = window.open(url, 'blank');
win.focus();
}
// function to open each image as a modal once it is clicked
function openModal(event) {
var modal = document.getElementById("myModal");
modal.style.display = "block";
document.getElementById("expandedImg").setAttribute('src', event.target.getAttribute("src"));
}
// function to close the image modal
function closeModal(event) {
const modal = document.getElementById("myModal");
modal.style.display = "none";
}
// // // // // // // // // // // // // // // // // // // // // // // // // // //
// //
// functions and methods to pull data for art pieces //
// let art;
let showArtInfo;
/**
* #param art_index
* #param info_index
*
* function to pull the info on the art from AIC
*/
async function clickedEvent(art_index, info_index) { // is the info_index actually necessary here if it's not used again? is that for the API's benefit?
// Get id of artwork
let elem = document.getElementsByTagName('img')[art_index];
let id = elem.attributes[2].value;
let headers = new Headers([
['Content-Type', 'application/json'],
['Accept', 'application/json']
]);
let request = new Request(
`https://api.artic.edu/api/v1/artworks${id}?fields=id,title,artist_display,date_display`, {
method: 'GET',
headers: headers
});
let result = await fetch(request);
let response = await result.json();
console.log(response)
if (showArtInfo) {
stopShow();
} else {
let title = response.data.title;
let artist = response.data['artist_display'];
let date = response.data['date_display'];
let div = document.getElementById('caption');
div.innerHTML = `<br> Title: ${title}<br> Artist: ${artist}<br> Date Display: ${date}`;
elem.parentElement.appendChild(div);
};
}
/**
* #param id // art id
* #param event // 'onClick' event
*
* function to display the pulled info of the artpiece when clicked on
*/
function getArtwork(id, event) {
switch(id) {
case '16568': { // Water Lilies by Claude Monet, id# 16568
event.stopPropagation();
clickedEvent(0, 0)
break;
}
case '80607': { // Self Portrait by Vincent Van Gogh, id# 80607
event.stopPropagation();
clickedEvent(1, 0)
break;
}
case '87088': { // Water Lily Pond by Claude Monet, id# 87088
event.stopPropagation();
clickedEvent(2, 0)
break;
}
case '14586': { // The Poet's Garden by Vincent Van Gogh, id# 14586
event.stopPropagation();
clickedEvent(3, 0)
break;
}
case '24645': { // Under the Wave Off Kanagawa by Katsushika Hokusai, id# 24645
event.stopPropagation();
clickedEvent(4, 0)
break;
}
case '25110': { // Chrysanthemums and Bee by Katsushika Hokusai, id# 25110
event.stopPropagation();
clickedEvent(5, 0)
break;
}
}
}
And lastly, my CSS (in case you want to fully replicate my page to see what I'm going for in real time):
body {
margin: 50px;
padding: 0;
text-align: center;
background-color: #292C33;
}
h1 {
margin-bottom: 50px;
padding: 20px;
outline: 5px solid white;
color: white;
border-radius: 5px;
background-color: #b60235;
}
.container {
display: grid;
grid-template-columns: repeat(6, 1fr);
grid-auto-rows: 100px 100px;
grid-gap: 18px;
grid-auto-flow: dense;
}
.gallery-item {
width: 100%;
height: 100%;
position: relative;
}
.gallery-item .image {
width: 100%;
height: 100%;
overflow: hidden;
border: 2px solid white;
border-radius: 5px;
}
.gallery-item .image img {
width: 100%;
height: 100%;
object-fit: cover;
object-position: 50% 50%;
cursor: pointer;
transition: .66s ease-in-out;
border-radius: 5px;
}
.gallery-item:hover .image img {
transform: scale(1.12);
}
.gallery-item .text {
opacity: 0;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: white;
font-size: 30px;
pointer-events: none;
z-index: 4;
-webkit-backdrop-filter: blur(22px) saturate(1.5);
backdrop-filter: blur(22px) saturate(1.5);
}
.gallery-item:hover .text {
opacity: 1;
animation: move-up .33s linear;
padding: 1em;
width: 77.5%;
outline: 2px solid #b60235;
border-radius: 5px;
}
#keyframes move-up {
0% {top:77.5%}
50% {top:63.75%}
100% {top:50%}
}
.w-1 {
grid-column: span 1;
}
.w-2 {
grid-column: span 2;
}
.w-3 {
grid-column: span 3;
}
.w-4 {
grid-column: span 4;
}
.w-5 {
grid-column: span 5;
}
.w-6 {
grid-column: span 6;
}
.h-1 {
grid-row: span 1;
}
.h-2 {
grid-row: span 2;
}
.h-3 {
grid-row: span 3;
}
.h-4 {
grid-row: span 4;
}
.h-5 {
grid-row: span 5;
}
.h-6 {
grid-row: span 6;
}
#media screen and (max-width: 850px) {
.container {
grid-template-columns: repeat(3,1fr);
}
.w-1, .w-2, .w-3, .w-4, .w-5, .w-6 {
grid-column: span 3;
}
}
/* -------------------------------------------------------------------------- */
.closebtn {
position: absolute;
top: 15px;
right: 35px;
color: #f1f1f1;
font-size: 40px;
font-weight: bold;
transition: 0.3s;
}
.closebtn:hover, .closebtn:focus {
color: #bbb;
text-decoration: none;
cursor: pointer;
}
.modal {
display: none;
position: fixed;
z-index: 10;
padding-top: 5%;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgb(0, 0, 0);
background-color: rgba(0, 0, 0, 0.9);
}
.modal-content {
/* leave it centered and just display info underneath -- maybe?
margin-left: 5%;
display: block; */
width: 80%;
max-width: 750px;
max-height: 650px;
object-fit: contain;
}
#caption {
margin: auto;
display: block;
width: 80%;
max-width: 700px;
text-align: center;
color: #ccc;
padding: 10px 0;
height: 150px;
}
.modal-content {
animation-name: zoom;
animation-duration: 0.5s;
}
#keyframes zoom {
from {
transform: scale(0)
} to {
transform: scale(1)
}
}
So, hopefully you'll see that nearly every thing else I'm programming functions as it should, but I can't quite get the data pulled from the API and displaying inside of the modal when opened. I believe my problem rests fully in the JS code and how I'm attempting to fetch and display the data from the API. Also, I have a div with an id of 'info' placed inside of the 'modal' div in my HTML, but I've got a sneaking suspicion that I'm not using that properly either. Let me know if there's any additional information required on my end.
I'm using animation property CSS to animate the window when the user clicks maximize button. The window is created ONLY when the maximize button was clicked and the animation is working, but the problem is when I click the close button the window is doesn't animate. How can I animate when the close button is click?
JavaScript:
Show project image.
_showProjectImage(e) {
const btn = e.target.closest('.projects__maximize-btn');
if (!btn) return;
const { id } = btn.dataset;
const { image } = this._data.find(image => image.id === +id);
this._projectBox = e.target.closest('.projects__box');
const markup = this._generateProjectImage(image);
this._projectBox.insertAdjacentHTML('afterbegin', markup);
}
Hide project image.
_hideProjectImage(e) {
const btnClose = e.target.closest('.btn__close-window');
if (!btnClose) return;
this._projectBox.removeChild(this._projectBox.firstElementChild);
}
HTML Element:
_generateProjectImage(image) {
return `
<div class="projects__window">
<div class="projects__window-content">
<button class="projects__window-close btn__close-window">
<svg class="projects__window-icon">
<use
xlink:href="${icon}#icon-close"
></use>
</svg>
</button>
<div class="projects__window-box">
<img src="${image}" alt="" class="projects__window-image">
</div>
</div>
</div>
`;
}
CSS:
.projects {
&__window {
position: fixed;
inset: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.7);
z-index: 1000;
animation: window-animate 300ms linear;
}
}
#keyframes window-animate {
from {
transform: scale(0);
opacity: 0;
}
to {
transform: scale(1);
opacity: 1;
}
}
So I'm making a simple pokemon app where the front-end makes fetch calls to grab the Pokemon from PokeAPI and displays it, but when loading a pokemon you can see that the fetch info gets loaded at different rates.
For example the pokemon loads then the name loads then the background loads then the type loads.
Is there anyway to have it so the HTML fills all at one time?
This is what my Javascript fetch function looks like, additionally here is the app so you can see how the information loads slowly / not all at once : https://bui-pokemon.herokuapp.com/
pokeButton.addEventListener('click', (e)=> {
e.preventDefault();
const pokeNameSearch = pokeSearch.value.toLowerCase();
fetch(`https://pokeapi.co/api/v2/pokemon/${pokeNameSearch}`)
.then((response) => response.json())
.then(data => {
if(pokeCard.classList.value === 'poke_card'){
pokeCard.classList.add('border');
};
//If a pokemon was normal / flying type then flying should be shown in the background isntead of normal
//because flying type is more of a defining characteristic of that pokemon rather than normal
if(data.types.length > 1 && data.types[0].type.name === "normal" && data.types[1].type.name === "flying"){
pokeCard.className = `poke_card border ${data.types[1].type.name}_background`
} else {
pokeCard.className = `poke_card border ${data.types[0].type.name}_background`;
}
pokeImg.src = data.sprites.front_default;
pokeName.innerHTML = data.name;
// Fill in Pokemon Type
pokeTypeIcon1.src = "";
pokeTypeIcon2.src = "";
pokeTypeIcon1.className = '';
pokeTypeIcon2.className = '';
pokeTypeIcon2.style.display = "none";
pokeType.innerHTML = `${data.types[0].type.name}`;
pokeNumDisplay.innerHTML = `#${fillInZero(data.id.toString())}`
pokeTypeIcon1.src = `img/icons/${data.types[0].type.name}.svg`
pokeTypeIcon1.className = `type_icon_1 ${data.types[0].type.name}`
if(data.types.length > 1){
pokeType.innerHTML += `/${data.types[1].type.name}`
pokeTypeIcon2.src = `img/icons/${data.types[1].type.name}.svg`
pokeTypeIcon2.style.display = "inline-block";
pokeTypeIcon2.className = `type_icon_2 ${data.types[1].type.name}`
} else {
pokeType.innerHTML = `${data.types[0].type.name}`
}
})
Seems the font and images loading causes the issue.
What you could do, is listen for the load event on each image and transition the opacity. Then, use document.fonts.ready and transition the color:
const container = document.querySelector(".container");
const background = document.getElementById("background")
const imgOne = document.getElementById("img-one")
const imgTwo = document.getElementById("img-two")
const fadeIn = (el) => {
el.addEventListener("load", () => el.style.opacity = "1")
}
document.fonts.ready.then(() => container.style.color = "#fff")
fadeIn(background)
fadeIn(imgOne)
fadeIn(imgTwo)
background.src = "https://ak.picdn.net/shutterstock/videos/9589454/thumb/2.jpg"
imgOne.src = "https://toppng.com/public/uploads/thumbnail/ikachu-8-bits-8-bit-pokemon-grid-11563233054e4sqfqyl2l.png"
imgTwo.src = "https://icons.iconarchive.com/icons/paomedia/small-n-flat/1024/lightning-icon.png"
#import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap');
body {
background: #43464b;
font-family: "Press Start 2P", Arial, Helvetica, sans-serif;
}
.container {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
position: relative;
margin: 0 auto;
width: 200px;
height: 300px;
color: transparent;
overflow: hidden;
transition: color 0.25s;
}
.container>*:not(#background) {
z-index: 1;
}
img {
opacity: 0;
transition: opacity 0.25s;
}
#background {
position: absolute;
top: 0;
left: 0;
}
#img-one,
#img-two {
height: 80px;
}
<div class="container">
<img id="background" />
<img id="img-one" />
<p>#25 Pikachu</p>
<img id="img-two" />
<p>Electric</p>
</div>
However, it could still be uneven this way if one thing takes longer to load than the other.
Another solution is to push values to an array once loaded, and check the length of the array before setting the opacity of the container:
const container = document.querySelector(".container");
const background = document.getElementById("background")
const imgOne = document.getElementById("img-one")
const imgTwo = document.getElementById("img-two")
const loaded = []
const setLoadState = (el) => {
loaded.push(el)
if (loaded.length === 4)
container.style.opacity = "1"
}
const imgLoad = (img) => {
img.addEventListener("load", () => setLoadState(img.id))
}
document.fonts.ready.then(() => setLoadState('font'))
imgLoad(background)
imgLoad(imgOne)
imgLoad(imgTwo)
background.src = "https://ak.picdn.net/shutterstock/videos/9589454/thumb/2.jpg"
imgOne.src = "https://toppng.com/public/uploads/thumbnail/ikachu-8-bits-8-bit-pokemon-grid-11563233054e4sqfqyl2l.png"
imgTwo.src = "https://icons.iconarchive.com/icons/paomedia/small-n-flat/1024/lightning-icon.png"
#import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap');
body {
background: #43464b;
font-family: "Press Start 2P", Arial, Helvetica, sans-serif;
}
.container {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
position: relative;
margin: 0 auto;
width: 200px;
height: 300px;
color: #fff;
overflow: hidden;
opacity: 0;
transition: opacity 0.25s;
}
.container>*:not(#background) {
z-index: 1;
}
#background {
position: absolute;
top: 0;
left: 0;
}
#img-one,
#img-two {
height: 80px;
}
<div class="container">
<img id="background" />
<img id="img-one" />
<p>#25 Pikachu</p>
<img id="img-two" />
<p>Electric</p>
</div>
//Overlay mobile menu open
$('#burger-icon').on('click', function(e) {
e.stopPropagation();
document.getElementById('fp-menu').style.height = "100%";
let overlay_content = document.getElementsByClassName("overlay-content")[0];
let pipe = overlay_content.querySelector(".pipe");
let contact = document.querySelector("#sidebar-leftButton");
let case_studies = document.querySelector("#sidebar-rightButton");
if (screen.width < 1000) {
let overlay_contentA = document.querySelectorAll(".overlay a");
for (i = 0; i < overlay_contentA.length; i++) {
overlay_contentA[i].style.color = "white";
}
//changes the social icons to white if in mobile view.
document.getElementById('instagram').src = "instagram_white.svg";
document.getElementById('linkedin').src = "linkedin_white.svg";
document.getElementById('twitter').src = "twitter_white.svg";
//gets rid of the pipe in menu that is visible for the desktop version
//removes sidetabs while in overlay menu
pipe.style.display = "none";
contact.style.display = "none";
case_studies.style.display = "none";
//changes how the elements are displayed when overlay is triggered
$('#fp-menu .news').removeClass("col-sm-2");
$('#fp-menu .portfolio').removeClass("col-sm-3");
$('#fp-menu #social').removeClass("col-sm-6");
}
});
function closeOverlayMenu() { //closes the overlay mobile menu
// e.stopPropagation();
$('#fp-menu').animateCss('slideUp');
$('#fp-menu').css('height', 0);
let overlay_content = document.getElementsByClassName("overlay-content")[0];
let pipe = overlay_content.querySelector(".pipe");
let contact = document.querySelector("#sidebar-leftButton");
let case_studies = document.querySelector("#sidebar-rightButton");
let overlay_contentA = document.querySelectorAll(".overlay a");
for (i = 0; i < overlay_contentA.length; i++) {
overlay_contentA[i].style.color = "black";
}
//changes icons to black on slide up of overlay
document.getElementById('instagram').src = "instagram.svg";
document.getElementById('linkedin').src = "linkedin.svg";
document.getElementById('twitter').src = "twitter.svg";
//restores elements of the original homepage that were hidden for overlay
pipe.style.display = "block";
contact.style.display = "block";
case_studies.style.display = "block";
$('#fp-menu .news').addClass("col-sm-2");
$('#fp-menu .portfolio').addClass("col-sm-3");
$('#fp-menu #social').addClass("col-sm-6");
};
document.getElementsByTagName('body')[0].onresize = function() {
closeOverlayMenu();
};
//overlay mobile menu close
$('#closebtn').on('click', function(e) {
e.stopPropagation();
$('#fp-menu').animateCss('slideUp');
$('#fp-menu').css('height', 0);
//if overlay mobile menu is down, close it by clicking the X
if (screen.width < 1000) {
closeOverlayMenu();
console.log(document.querySelectorAll("#social"));
}
});
//overlay menu styling
.overlay {
height: 0;
width: 100%;
position: fixed;
z-index: 999;
top: 0;
left: 0;
background-color: #000000;
overflow-x: hidden;
transition: 0.5s;
}
.overlay-content {
position: relative;
top: 5%;
width: 100%;
text-align: center !important;
margin-top: 90px;
.row{
padding: 50px 30px 50px 30px;
.column{
float: left;
width: 33.33%;
padding: 0 5px 0 5px;
}
}
img {
width: 50px;
}
div {
padding: 30px 0 30px 0;
}
}
.overlay a {
padding: 8px;
text-decoration: none;
font-size: 36px;
color: #FFFFFF;
}
.overlay a:hover, .overlay a:focus {
color: #f1f1f1;
}
#closebtn {
display:block;
position: relative;
top: 5px;
right: 20px;
font-size: 60px;
}
#social{
position: relative;
top: 10px;
a {
padding: 5% 5% 5% 5%;
}
}
#fp-menu{
display: block;
color: $menu_black;
}
.pipe{
display: block;
transition: 0.4s;
}
<div id="fp-menu" class="overlay">
<div id="closebtn" style="color: white;">X</div>
<div class="column overlay-content">
<!-- <div class="column"> -->
<div class="col-sm-2 news">
NEWS
</div>
<div class="col-sm-1 pipe">
|
</div>
<div class="col-sm-3 portfolio">
PORTFOLIO
</div>
<div id="social" class="col-sm-6">
<img id="instagram" src='instagram.svg' />
<img id="linkedin" src='linkedin.svg' />
<img id="twitter" src='twitter.svg' />
</div>
</div>
</div>
So the weirdest thing, I've got 1 function that is to trigger under 2 conditions: when the window is resized and when the exit button is clicked.
This relates to an overlay menu that's actually intended for mobile users.
The functions work as they are supposed to, in both cases, when I have the inspection console open in chrome. However, when I close this and return to the normal browser window, the functions cease to execute.
On the mobile it is fine. I have only encountered this problem on the desktop/laptop (as I tried it on different desktops [iMacs] and 2 laptops [Macbooks, but the type of hardware I don't think matters]).
Currently the icons in the "#social" div are not being changed to white, which is what I expect to happen when opened, and when closed, they return to black. They are staying black throughout the execution.
Has anyone ever experienced this before? This is related to a Wordpress platform site. Totally custom built, no themes.
Please let me know if this description helps. If any code is needed, please let me know.
Ps: I thought it was a caching problem, on the terminals or on the server, and I cleared the cache on both but the issue still persists.
function closeOverlayMenu(){//closes the overlay mobile menu
$('#fp-menu').animateCss('slideUp');
$('#fp-menu').css('height', 0);
let overlay_content = document.getElementsByClassName("overlay-content")[0];
let pipe = overlay_content.querySelector(".pipe");
let contact = document.querySelector("#sidebar-leftButton");
let case_studies = document.querySelector("#sidebar-rightButton");
let overlay_contentA = document.querySelectorAll(".overlay a");
for (i = 0; i < overlay_contentA.length; i++) {
overlay_contentA[i].style.color = "black";
}
//changes icons to black on slide up of overlay
document.getElementById('instagram').src="https://s3-eu-west-1.amazonaws.com/mvt-hosted-images/instagram.svg";
document.getElementById('linkedin').src="https://s3-eu-west-1.amazonaws.com/mvt-hosted-images/linkedin.svg";
document.getElementById('twitter').src="https://s3-eu-west-1.amazonaws.com/mvt-hosted-images/twitter.svg";
//restores elements of the original homepage that were hidden for overlay
pipe.style.display="block";
contact.style.display="block";
case_studies.style.display="block";
$('#fp-menu .news').addClass("col-sm-2");
$('#fp-menu .portfolio').addClass("col-sm-3");
$('#fp-menu #social').addClass("col-sm-6");
};
I would expect that the function would trigger without the dev console being active. Please let me know if any further description or information would help.
PROBLEM: Element with id "containerLnkMenu" does not center correctly in it's parent div when passed into the js function "centerElementYParent" unless I put a break point in the function using google chrome's debugger.
The "getComputedStyle(f, null)" call returns a "0px" for height if executed normally so I end up with a '-57px' for the margin-top.
COMMENT: So I found a few people that had similar problems on the internet, but I couldn't find a way to map their solution to my needs.
Any help on this would be appreciated.
Let me know if you need me to explain anything further.
I would prefer a detailed response or links to further reading, that is related to my issue (so I can learn from this error), but any related/helpful comment is welcome.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<!--[if lt IE 9]>
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link rel="stylesheet" href="main.css">
<script src="main.js"></script>
</head>
<body>
<div id="btnMenu" class="borderRadius" style="top: 10px; left: 10px;" onClick="btnMenuClicked(this)">
<div id="bar1" class="bar"></div>
<div id="bar2" class="bar"></div>
<div id="bar3" class="bar"></div>
</div>
<div id="menu" class="borderRadius" style="width: 0px; height: 0px;">
<div id="containerLnkMenu">
<a id="lnkNews" class="centerTxt lnkMenu" href="">NEWS</a>
<a id="lnkFiles" class="centerTxt lnkMenu" href="">FILES</a>
<a id="lnkTree" class="centerTxt lnkMenu" href="">TREE</a>
</div>
</div>
</body>
<script>
function btnMenuClicked(e) {
animateBtnMenu(e);
var menu = document.getElementById('menu');
var menuStyle = window.getComputedStyle(menu, null);
if (menuStyle.width == '0px' && menuStyle.height == '0px') {
openMenu(menu, menuStyle, e);
centerElementYParent(document.getElementById('containerLnkMenu'), document.getElementById('menu'));
} else {
closeMenu(menu, menuStyle, e);
}
}
</script>
</html>
body {
margin: 0;
font-family: Arial;
font-size: 16px;
}
a {
display: block;
text-decoration: none;
cursor: pointer;
}
/* Class Tools */
.centerTxt { text-align: center; }
.borderRadius { border-radius: 5px; }
.bar {
height: 5px;
transition: 0.4s;
background-color: #2E0A91;
}
.lnkMenu {
padding: 5px;
color: #FFD500;
font-size: 1.5em;
}
/*--- navigation ---*/
#btnMenu {
position: fixed;
width: 25px;
padding: 5px;
transition: 0.8s;
cursor: pointer;
}
#btnMenu:hover { background-color: #2E0A91; }
#btnMenu:hover .bar { background-color: #D4B100; }
#bar2 { margin: 5px 0 5px 0; }
.change #bar1 {
transform: rotate(-45deg) translate(-10px, 4px);
width: 141%;
}
.change #bar2 { opacity: 0; }
.change #bar3 {
transform: rotate(45deg) translate(-10px, -4px);
width: 141%;
}
#menu {
position: fixed;
z-index: 100;
top: 0;
left: 0;
overflow: hidden;
transition: 0.8s;
background-color: #2E0A91;
}
//NAME: centerElementYParent
//DESCRITPTION: e = element to center, f = parent element
// Adds margin top to e in order to vertically center element within parent (f)
function centerElementYParent(e, f) {
var eStyle = window.getComputedStyle(e, null);
var fStyle = window.getComputedStyle(f, null);
console.log(fStyle.height);
var eHeight = parseInt(eStyle.height.slice(0, eStyle.height.length - 2));
var fHeight = parseInt(fStyle.height.slice(0, fStyle.height.length - 2));
var marginTop = ((fHeight - eHeight)/2) + 'px';
e.style.marginTop = marginTop;
}
//NAME: animateBtnMenu
//DESCRIPTION: Attaches the 'change' class to the btnMenu element.
function animateBtnMenu(e) {
e.classList.toggle('change');
}
//NAME: openMenu
//DESCRIPTION: Applies a width and height to the menu whilst moving the menu button respectivley
function openMenu(e, eStyle, f) {
e.style.height = '250px';
e.style.width = '300px';
var eStyle = window.getComputedStyle(e, null);
f.style.left = '310px';
f.style.top = '260px';
}
//NAME: closeMenu
//DESCRIPTION: Sets width and height of the menu to 0 and moves the menu button respectivley
function closeMenu(e, eStyle, f) {
e.style.width = '0px';
e.style.height = '0px';
f.style.top = '10px';
f.style.left = '10px';
}
It may be because the element you want to center didn't rendered on the right position yet. Try adding setTimeout to call the function.
openMenu(menu, menuStyle, e);
setTimeout(function() {
centerElementYParent(document.getElementById('containerLnkMenu'), document.getElementById('menu'));
}, 800);