Search code examples
javascripthtmlcssnavigationgallery

How to find the original source of an image and its siblings to get gallery navigation to work?


I'm a novice at Javascript and I cannot wrap my head around getting my navigation buttons to work (prev, next)

Not sure the best way to do it but was thinking that if there's a way to call back to the original < figure class="thumb" > and then navigating to its sibling figures then it could be done that way?

Been struggling with this for a little over a week now... let me know if there's anything else that jumps out in the code please! Always open to tips and best practices

https://codepen.io/pamflambe/pen/dygMYRO

HTML, CSS, JAVASCRIPT:

function run() {const buttons = document.querySelectorAll('.thumb');
const overlay = document.querySelector('.overlay');
const overlayBG = document.querySelector('.overlayBG');
const overlayImage = document.querySelector('.overlay__inner img');
const overlayInner = document.querySelector('.overlay__inner');
buttons.forEach(button => button.addEventListener('click', open));
overlayImage.addEventListener('click', close);
overlayInner.addEventListener('click', close);
overlayBG.addEventListener('click', close);

function open(e) {
    overlay.style.display="table";
    const src= e.currentTarget.querySelector('img').src;
    overlayImage.src = src;
    overlayBG.style.display="table";
    overlayInner.style.display="table-cell";
    document.querySelector('.navButtons').style.display = "inline-grid";
};

function close() {
  overlay.classList.remove('open');
        overlay.style.display="none";
};


}
#gallery {
    margin: 1.5vw 1.5vw;
    position: relative;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    }

.thumb {
    position: relative;
    margin: 1em;
    min-width: 30vw;
    min-height: 25vw;
    position: relative;
    overflow: hidden;
    }  

.thumb > img {
    position: absolute;
    }


//project popup overlay



.overlay {
    display: none;
    position: absolute;
    justify-content: center;
    align-content: center;
    width: 100%;
    top: 0;
    left: 0;
    z-index: 0;
    }

.overlayBG {
    display: none;
    position: fixed;
    align-content: center;
    width: 100vw;
    height: 100vh;
    bottom: 0;
    left: 0;
    background: rgba(0,0,0, .9);
    z-index: 2;
    }


.overlay__inner {
    display: none;
    margin-left: 15vw;
    margin-right: 15vw;
    margin-bottom: 2%;
    top: 10vh;
    vertical-align: middle;
    background: #ffffff;
    padding: 1.2vw;
    position: fixed;
    opacity: 1;
    z-index: 2;
    }


.innerImage{
    width: 68.4vw;
    height: 38.475vw;
    }




.navContainer{
    width: 68.4vw;
    margin-left: 17vw;
    margin-right: 15vw;
    margin-bottom: 40%;
    margin-top: 17vw;
    vertical-align: middle;
    position: absolute;
}

.navButtons {
    display: none;
    height: 1px;
    z-index: 3;
    position: sticky;
    vertical-align: middle;
    }

.prev,
.next {
    cursor: pointer;
    position: fixed;
    width: auto;
    color: white;
    font-weight: bold;
    font-size: 3vw;
    transition: 0.6s ease;
    user-select: none;
    -webkit-user-select: none;
    z-index: 2;
}



.next {
    right: 16vw;

}


.full_image {
    height: 100%;
    margin-left: -25%;
    }
<div class="overlay">
  <div class="overlayBG"></div>
  <div class="overlay__inner">
    <img class="innerImage">
  </div>
<div class="navContainer">
  <nav class="navButtons">
        <nav class="prev" onclick="prv()">&#10094;</nav>
        <nav class="next" onclick="nxt()">&#10095;</nav>
    </nav>  
</div>
</div>   
   
<main id="gallery" onclick="run()">
    <figure class="thumb">
      <img class="full_image" id="soySauce" src="https://images.squarespace-cdn.com/content/v1/5cb788c29b8fe84734590bee/1605154714762-Q1AF1GRGP7L3E9TRFEQM/soy_sauce_ad.png" alt=""/>
    </figure>
    
    <figure class="thumb">
      <img class="full_image" id="jelloWorld" src="https://images.squarespace-cdn.com/content/v1/5cb788c29b8fe84734590bee/1636172941453-JDHE57N1W1TDY44J9SL1/jello.png" alt=""/>
    </figure>
    
    <figure class="thumb">
      <img class="full_image" src="https://images.squarespace-cdn.com/content/v1/5cb788c29b8fe84734590bee/1598817571504-UF8F3Y2A38QX2GOVJCKK/taco_logo_033.jpg" alt=""/>
    </figure>
    
    <figure class="thumb">
      <img class="full_image" src="https://images.squarespace-cdn.com/content/v1/5cb788c29b8fe84734590bee/1598503927733-RIKXJZFVVNY1BYQ5K7HI/I_cant_sleep.png" alt=""/>
    </figure>
    
    
    <figure class="thumb">
      <img class="full_image" src="https://images.squarespace-cdn.com/content/v1/5cb788c29b8fe84734590bee/1598817571941-GIGUFXXC50SSJ92C69ZM/corndog_020.jpg" alt=""/>
    </figure>
    
    
    <figure class="thumb">
      <img class="full_image" id="pearAss" src="https://images.squarespace-cdn.com/content/v1/5cb788c29b8fe84734590bee/1598817570971-QYM2SN2290R7KIU8N41K/pear_ass.jpg" alt=""/>
    </figure>
      
</main>

Tried to create a function for prv() and nxt() that calls to the parentNode and then can access the previousSibling and nextSibling, but not sure the syntax for doing that or if it's even possible


Solution

  • One possible way is to give all your figures ids and store the currently opened id in a variable. Your buttons then increase / decrease this id.

    HTML:

    <figure data-id="1" class="thumb">
    

    JS:

    var curImgId = 0;
    document.querySelector(".prev").addEventListener("click", prv);
    document.querySelector(".next").addEventListener("click", nxt);
    ...
    function open(e) {
      openFig(e.currentTarget);
    }
    function openFig(fig) {
      ...
      curImgId = parseInt(fig.dataset.id);
      ...
    }
    function prv() {
      var prvFig = document.querySelector(".thumb[data-id='" + (curImgId - 1) + "']");
    
      if (prvFig != null) {
        openFig(prvFig);
      } else {
        console.log("first image reached");
      }
    }
    
    function nxt() {
      var nxtFig = document.querySelector(".thumb[data-id='" + (curImgId + 1) + "']");
    
      if (nxtFig != null) {
        openFig(nxtFig);
      } else {
        console.log("last image reached");
      }
    }
    

    Note that the way your run function is set up, it might execute multiple times. You can use this to only execute the function once:

    document.addEventListener("DOMContentLoaded", function(event) {
      ...
    })
    

    See here: https://codepen.io/Sebireb/pen/NWONxvK

    One more note: Using jQuery makes stuff like this easier, if u didn't already, give it a try.