Search code examples
javascriptmasonry

Enable only one masonry tile open at a time


I have a masonry layout (using the library from here), that when a user clicks a tile, only one tile should be able to expand at a time. If the user clicks another tile, the previously opened tile should close. How can I check for any previously opened tiles, close them, and then open the newly selected tile?

// external js: masonry.pkgd.js

var grid = document.querySelector('.grid');
var msnry = new Masonry( grid);

grid.addEventListener( 'click', function( event ) {
  // don't proceed if item was not clicked on
  if ( !matchesSelector( event.target, '.grid-item' ) ) {
    return;
  }
  // change size of item via class
  event.target.classList.toggle('grid-item--gigante');
  // trigger layout
  msnry.layout();
});
.grid {
  background: #eee;
  width: 1200px;
  margin: 0 auto;
}

.grid-holder {
  background: #fff;
  margin: 0 auto;
  display: block;
}

.grid-item {
  width: 375px;
  height: 375px;
  margin-bottom: 4%;
  float: left;
  border: 1px solid #ddd;
  margin-right: 10px;
  background-color: #eee;
  box-shadow: 2px 2px 2px 2px #eee;
}

.grid-item--gigante {
  max-width: 600px;
  min-width: 100px;
  width: 63%;
  min-height: 375px;
  height: auto;
  margin-left: 8px;
  background-color: rgba(215, 210, 203, 0.3) !important;

  color: #666;
  border: 1px solid #ddd;
  padding: 0.5% 8% 2.5% 5%;
  z-index: 2; /* above other items */
}

.grid-item:hover {
  background: #a2c;
  border-color: white;
  cursor: pointer;
}
<script src="https://masonry.desandro.com/masonry.pkgd.js"></script>
<div class="grid">
  <div class="grid-holder">
  <div class="grid-item">Jim</div>
  <div class="grid-item">Joe</div>
  <div class="grid-item">John</div>
  <div class="grid-item">James</div>
  <div class="grid-item">Jack</div>
  <div class="grid-item">Joseph</div>
  </div>
 </div>


Solution

  • You need to keep a reference to previously enlarged grid item.

    Whenever the click event occurs, check if current event target is equal to previously enlarged grid item or not. If it is not, remove .grid-item--gigante class from previously enlarged grid item and update the reference to previously enlarged grid item to now point to event.target.

    P.S. removed some CSS to make the example code snippet easy to understand.

    var grid = document.querySelector('.grid');
    var msnry = new Masonry(grid);
    var previouslyEnlarged;
    
    grid.addEventListener('click', function(event) {
      if ( !matchesSelector( event.target, '.grid-item' ) ) {
        return;
      }
      
      if (previouslyEnlarged == event.target) {
        return;
      } else if (previouslyEnlarged) {
        previouslyEnlarged.classList.remove('grid-item--gigante');
      }
    
      previouslyEnlarged = event.target;
    
      event.target.classList.toggle('grid-item--gigante');
      msnry.layout();
    });
    .grid-holder {
      background: #fff;
      margin: 0 auto;
      display: block;
    }
    
    .grid-item {
      width: 50px;
      height: 50px;
      margin-bottom: 4%;
      float: left;
      border: 1px solid #ddd;
      margin-right: 10px;
      background-color: #eee;
      box-shadow: 2px 2px 2px 2px #eee;
    }
    
    .grid-item--gigante {
      width: 100px;
      height: 100px;
      margin-left: 8px;
      background-color: rgba(215, 210, 203, 0.3) !important;
      color: #666;
      border: 1px solid #ddd;
      padding: 0.5% 8% 2.5% 5%;
      z-index: 2;
    }
    
    .grid-item:hover {
      background: #a2c;
      border-color: white;
      cursor: pointer;
    }
    <script src="https://masonry.desandro.com/masonry.pkgd.js"></script>
    <div class="grid">
      <div class="grid-holder">
        <div class="grid-item">Jim</div>
        <div class="grid-item">Joe</div>
        <div class="grid-item">John</div>
        <div class="grid-item">James</div>
        <div class="grid-item">Jack</div>
        <div class="grid-item">Joseph</div>
      </div>
    </div>