title: javascript forEach - add addEventListener on all buttons
body: <p>I'm not so skilled with javascript so I'm looking for a little help.
  I'm using a script found on Codrops (3D Grid Effect - <a href="http://tympanus.net/Development/3DGridEffect/" rel="noreferrer">http://tympanus.net/Development/3DGridEffect/</a>).</p>
  
  <p>All is working fine as expected but I'm trying to "modify" it for my needs.</p>
  
  <p>Basically, I want to trigger the "effect" NOT clicking on the whole container but on a button placed inside it.</p>
  
  <p>The structure I'm using is:</p>
  
  <pre><code>    &lt;section class="grid3d vertical" id="grid3d"&gt;
          &lt;div class="grid-wrap"&gt;
              &lt;div class="grid"&gt;
                  &lt;div class="box"&gt;&lt;div class="btn-click-me"&gt;Click to Show&lt;/div&gt;&lt;/div&gt;
                  &lt;div class="box"&gt;&lt;div class="btn-click-me"&gt;Click to Show&lt;/div&gt;&lt;/div&gt;
                  &lt;div class="box"&gt;&lt;div class="btn-click-me"&gt;Click to Show&lt;/div&gt;&lt;/div&gt;
  
              &lt;/div&gt;
          &lt;/div&gt;
          &lt;div class="content"&gt;
              &lt;div&gt;
                  &lt;div class="dummy-img"&gt;&lt;/div&gt;
                  &lt;p class="dummy-text"&gt;Some text&lt;/p&gt;
                  &lt;p class="dummy-text"&gt;Some more text&lt;/p&gt;
              &lt;/div&gt;
              &lt;div&gt;
                  &lt;!-- ... --&gt;
              &lt;/div&gt;
              &lt;!-- ... --&gt;
              &lt;span class="loading"&gt;&lt;/span&gt;
              &lt;span class="icon close-content"&gt;&lt;/span&gt;
          &lt;/div&gt;
      &lt;/section&gt;
  
  &lt;script&gt;
              new grid3D( document.getElementById( 'grid3d' ) );
          &lt;/script&gt;
  </code></pre>
  
  <p>And the script (js) is </p>
  
  <pre><code>/**
   * grid3d.js v1.0.0
   * http://www.codrops.com
   *
   * Licensed under the MIT license.
   * http://www.opensource.org/licenses/mit-license.php
   * 
   * Copyright 2014, Codrops
   * http://www.codrops.com
   */
  ;( function( window ) {
  
      'use strict';
  
      function grid3D( el, options ) {
          this.el = el;
          this.options = extend( {}, this.options );
          extend( this.options, options );
          this._init();
      }
  
      // any options you might want to configure
      grid3D.prototype.options = {};
  
      grid3D.prototype._init = function() {
          // grid wrapper
          this.gridWrap = this.el.querySelector( 'div.grid-wrap' );
          // grid element
          this.grid = this.gridWrap.querySelector( 'div.grid' );
          // main grid items
          this.gridItems = [].slice.call( this.grid.children );
          // default sizes for grid items
          this.itemSize = { width : this.gridItems[0].offsetWidth, height : this.gridItems[0].offsetHeight };
          // content
          this.contentEl = this.el.querySelector( 'div.content' );
          // content items
          this.contentItems = [].slice.call( this.contentEl.children );
          // close content cross
          this.close = this.contentEl.querySelector( 'span.close-content' );
          // loading indicator
          this.loader = this.contentEl.querySelector( 'span.loading' );
          // support: support for pointer events, transitions and 3d transforms
          this.support = support.pointerevents &amp;&amp; support.csstransitions &amp;&amp; support.csstransforms3d;
          // init events
          this._initEvents();
      };
  
      grid3D.prototype._initEvents = function() {
          var self = this;
  
          // open the content element when clicking on the main grid items
          this.gridItems.forEach( function( item, idx ) {
              item.addEventListener( 'click', function() {
                  self._showContent( idx );
              } );
          } );
  
          // close the content element
          this.close.addEventListener( 'click', function() {
              self._hideContent();
          } );
  
          if( this.support ) {
              // window resize
              window.addEventListener( 'resize', function() { self._resizeHandler(); } );
  
              // trick to prevent scrolling when animation is running (opening only)
              // this prevents that the back of the placeholder does not stay positioned in a wrong way
              window.addEventListener( 'scroll', function() {
                  if ( self.isAnimating ) {
                      window.scrollTo( self.scrollPosition ? self.scrollPosition.x : 0, self.scrollPosition ? self.scrollPosition.y : 0 );
                  }
                  else {
                      self.scrollPosition = { x : window.pageXOffset || docElem.scrollLeft, y : window.pageYOffset || docElem.scrollTop };
                      // change the grid perspective origin as we scroll the page
                      self._scrollHandler();
                  }
              });
          }
      };
  
      // creates placeholder and animates it to fullscreen
      // in the end of the animation the content is shown
      // a loading indicator will appear for 1 second to simulate a loading period
      grid3D.prototype._showContent = function( pos ) {
          if( this.isAnimating ) {
              return false;
          }
          this.isAnimating = true;
  
          var self = this,
              loadContent = function() {
                  // simulating loading...
                  setTimeout( function() {
                      // hide loader
                      classie.removeClass( self.loader, 'show' );
                      // in the end of the transition set class "show" to respective content item
                      classie.addClass( self.contentItems[ pos ], 'show' );
                  }, 1000 );
                  // show content area
                  classie.addClass( self.contentEl, 'show' );
                  // show loader
                  classie.addClass( self.loader, 'show' );
                  classie.addClass( document.body, 'noscroll' );
                  self.isAnimating = false;
              };
  
          // if no support just load the content (simple fallback - no animation at all)
          if( !this.support ) {
              loadContent();
              return false;
          }
  
          var currentItem = this.gridItems[ pos ],
              itemContent = currentItem.innerHTML;
  
          // create the placeholder
          this.placeholder = this._createPlaceholder(itemContent );
  
          // set the top and left of the placeholder to the top and left of the clicked grid item (relative to the grid)
          this.placeholder.style.left = currentItem.offsetLeft + 'px';
          this.placeholder.style.top = currentItem.offsetTop + 'px';
  
          // append placeholder to the grid
          this.grid.appendChild( this.placeholder );
  
          // and animate it
          var animFn = function() {
              // give class "active" to current grid item (hides it)
              classie.addClass( currentItem, 'active' );
              // add class "view-full" to the grid-wrap
              classie.addClass( self.gridWrap, 'view-full' );
              // set width/height/left/top of placeholder
              self._resizePlaceholder();
              var onEndTransitionFn = function( ev ) {
                  if( ev.propertyName.indexOf( 'transform' ) === -1 ) return false;
                  this.removeEventListener( transEndEventName, onEndTransitionFn );
                  loadContent();
              };
              self.placeholder.addEventListener( transEndEventName, onEndTransitionFn );
          };
  
          setTimeout( animFn, 25 );
      };
  
      grid3D.prototype._hideContent = function() {
          var self = this,
              contentItem = this.el.querySelector( 'div.content &gt; .show' ),
              currentItem = this.gridItems[ this.contentItems.indexOf( contentItem ) ];
  
          classie.removeClass( contentItem, 'show' );
          classie.removeClass( this.contentEl, 'show' );
          // without the timeout there seems to be some problem in firefox
          setTimeout( function() { classie.removeClass( document.body, 'noscroll' ); }, 25 );
          // that's it for no support..
          if( !this.support ) return false;
  
          classie.removeClass( this.gridWrap, 'view-full' );
  
          // reset placeholder style values
          this.placeholder.style.left = currentItem.offsetLeft + 'px';
          this.placeholder.style.top = currentItem.offsetTop + 'px';
          this.placeholder.style.width = this.itemSize.width + 'px';
          this.placeholder.style.height = this.itemSize.height + 'px';
  
          var onEndPlaceholderTransFn = function( ev ) {
              this.removeEventListener( transEndEventName, onEndPlaceholderTransFn );
              // remove placeholder from grid
              self.placeholder.parentNode.removeChild( self.placeholder );
              // show grid item again
              classie.removeClass( currentItem, 'active' );
          };
          this.placeholder.addEventListener( transEndEventName, onEndPlaceholderTransFn );
      }
  
      // function to create the placeholder
      /*
      &lt;div class="placeholder"&gt;
          &lt;div class="front"&gt;[content]&lt;/div&gt;
          &lt;div class="back"&gt;&lt;/div&gt;
      &lt;/div&gt;
      */
      grid3D.prototype._createPlaceholder = function( content ) {
          var front = document.createElement( 'div' );
          front.className = 'front';
          front.innerHTML = content;
          var back = document.createElement( 'div' );
          back.className = 'back';
          back.innerHTML = '&amp;nbsp;';
          var placeholder = document.createElement( 'div' );
          placeholder.className = 'placeholder';
          placeholder.appendChild( front );
          placeholder.appendChild( back );
          return placeholder;
      };
  
      grid3D.prototype._scrollHandler = function() {
          var self = this;
          if( !this.didScroll ) {
              this.didScroll = true;
              setTimeout( function() { self._scrollPage(); }, 60 );
          }
      };
  
      // changes the grid perspective origin as we scroll the page
      grid3D.prototype._scrollPage = function() {
          var perspY = scrollY() + getViewportH() / 2;
          this.gridWrap.style.WebkitPerspectiveOrigin = '50% ' + perspY + 'px';
          this.gridWrap.style.MozPerspectiveOrigin = '50% ' + perspY + 'px';
          this.gridWrap.style.perspectiveOrigin = '50% ' + perspY + 'px';
          this.didScroll = false;
      };
  
      grid3D.prototype._resizeHandler = function() {
          var self = this;
          function delayed() {
              self._resizePlaceholder();
              self._scrollPage();
              self._resizeTimeout = null;
          }
          if ( this._resizeTimeout ) {
              clearTimeout( this._resizeTimeout );
          }
          this._resizeTimeout = setTimeout( delayed, 50 );
      }
  
      grid3D.prototype._resizePlaceholder = function() {
          // need to recalculate all these values as the size of the window changes
          this.itemSize = { width : this.gridItems[0].offsetWidth, height : this.gridItems[0].offsetHeight };
          if( this.placeholder ) {
              // set the placeholders top to "0 - grid offsetTop" and left to "0 - grid offsetLeft"
              this.placeholder.style.left = Number( -1 * ( this.grid.offsetLeft - scrollX() ) ) + 'px';
              this.placeholder.style.top = Number( -1 * ( this.grid.offsetTop - scrollY() ) ) + 'px';
              // set the placeholders width to windows width and height to windows height
              this.placeholder.style.width = getViewportW() + 'px';
              this.placeholder.style.height = getViewportH() + 'px';
          }
      }
  
      // add to global namespace
      window.grid3D = grid3D;
  
  })( window );
  </code></pre>
  
  <p>Now, I'm aware that the "crucial" portion of the code where I have to look is:</p>
  
  <blockquote>
    <p>// open the content element when clicking on the main grid items
          this.gridItems.forEach( function(item, idx ) {
              item.addEventListener( 'click', function() {
                  item._showContent( idx );           } );        } );</p>
  </blockquote>
  
  <p>So, my question again: how to trigger the event when the div (button) class "click-me" is clicked on every "boxes"?</p>
  
  <p>Thanks to all in advance (i'm struggling with it for hours...)</p>