title: How can I recreate Squarespace's Product Quick View in standard Product View?
body: <h1>Overview</h1>
  
  <p>So I'm trying to take functionality from one part of Squarespace's Galapagos commerce template and add it to another but it's proving to be more difficult than I thought.</p>
  
  <p>I need the image-swapping capability of the "Quick View" (example - mouse over any image and click Quick View ) to replace the column of full sized zoomable images in the "Product View" (example - you see this once you click on a product).</p>
  
  <p>So I found the code for each section:</p>
  
  <h1>Product View</h1>
  
  <p>This code simply goes through each image in the array and spits it out with the id <code>jsProductItemImages</code> which allows it to be hovered and zoomed.</p>
  
  <pre><code>&lt;div class="productitem-images" id="jsProductItemImages"&gt;
      {.repeated section items}
          {.image?}
              &lt;div class="productitem-image-zoom-wrapper sqs-image-zoom-area"&gt;&lt;img data-load="false" class="productitem-image loading" {@|image-meta} /&gt;&lt;/div&gt;
          {.end}
          {.video?}
              {@|video}
          {.end}
      {.end}
  &lt;/div&gt;
  </code></pre>
  
  <h1>Quick View</h1>
  
  <p>I'm not 100% on the logic here, but essentially it's grabbing the first image and making it a hover/zoomable primary image then listing the entire array of images beneath it as thumbnails. I read that the <code>@</code> symbol is the equivalent of saying <code>this</code> in javascript, but I don't get why it's being used to spit out only the first image in the array.</p>
  
  <pre><code>&lt;figure class="ProductItem-gallery"&gt;
    {.section items}
      &lt;div class="ProductItem-gallery-slides"&gt;
        {.repeated section @}
          {.image?}
            &lt;div class="ProductItem-gallery-slides-item" data-slide-index="{@index}"&gt;&lt;img class="ProductItem-gallery-slides-item-image" data-load="false" {@|image-meta} /&gt;&lt;/div&gt;
          {.end}
          {.video?}
            {@|video}
          {.end}
        {.end}
      &lt;/div&gt;
    {.end}
    &lt;div class="ProductItem-gallery-thumbnails"&gt;
      {.if items.1}{.repeated section items}&lt;div class="ProductItem-gallery-thumbnails-item"&gt;&lt;img class="ProductItem-gallery-thumbnails-item-image" data-load="false" {@|image-meta} /&gt;&lt;/div&gt;{.end}{.end}
    &lt;/div&gt;
  &lt;/figure&gt;
  </code></pre>
  
  <h1>Associated JS</h1>
  
  <p>First off, it should be noted that I went through and console logged every function to see what was giving the Quick View it's functionality - to no avail. Which is subsequently why I'm here. So it's easy to see where the zoom function is originating: the Product View in the <code>Galapagos.ProductItem</code> function on line 103 <code>$imageContainer = Y.one('#jsProductItemImages');</code></p>
  
  <p>But I don't see anything out of the ordinary pop up when I look at the Quick View. I've got to be missing something!</p>
  
  <pre><code>var Galapagos = {};
  
  Y.use('node', function(Y) {
  
      Galapagos.Site = (function(){
      console.log("Galapagos.Site");
  
          var $productPage;
  
          function init() {
        console.log("Galapagos.Site init()");
  
              $productPage = Y.one('.collection-type-products');
  
              if( $productPage &amp;&amp; $productPage.hasClass('view-list') ) Galapagos.ProductList.init();
              if( $productPage &amp;&amp; $productPage.hasClass('view-item') ) Galapagos.ProductItem.init();
  
              addDesktopTouchscreenClass();
              addMediaQueryBreakpointClass();
              bindEventListeners();
  
          }
  
          function addDesktopTouchscreenClass() {
        console.log("Galapagos.Site addDesktopTouchscreenClass()");
              if (Y.one('html').hasClass('touch')) {
                  var mousemoveDetection = Y.on('mousemove', function(){
                      Y.one('body').addClass('galapagos-desktop-touchscreen');
                      mousemoveDetection.detach();
                  });
              }
  
          }
  
          function addMediaQueryBreakpointClass() {
        console.log("Galapagos.Site addMediaQueryBreakpointClass()");
              if( document.documentElement.clientWidth &lt;= 724 ) {
                  if (Y.one('.catnav-container')) Y.one('.nav-container').prepend(Y.one('.catnav-list'));
                  Y.one('html').addClass('tablet-breakpoint-mixin');
              } else {
                  if (Y.one('.catnav-container')) Y.one('.catnav-container').prepend(Y.one('.catnav-list'));
                  Y.one('html').removeClass('tablet-breakpoint-mixin');
              }
  
          }
  
          function bindEventListeners() {
        console.log("Galapagos.Site bindEventListeners()");
              Y.on('resize', addMediaQueryBreakpointClass);
          }
  
          function getDocWidth() {
        console.log("Galapagos.Site getDocWidth()");
              return Y.one(document).get('docWidth');
          }
  
          function getDocHeight() {
        console.log("Galapagos.Site getDocHeight()");
              return Y.one(document).get('docHeight');
          }
  
          return {
              init:init,
              getDocWidth: getDocWidth,
              getDocHeight:  getDocHeight
          }
  
      }());
  
  
      Galapagos.TweakListener = (function(){
      console.log("Galapagos.TweakListener");
          function listen(tweakName, callBack) {
  
              if (Y.Global) {
                  Y.Global.on('tweak:change', Y.bind(function(f){
                      if ((f.getName() == tweakName) &amp;&amp; (typeof callBack === 'function')) {
                          callBack(f.getValue());
                      }
                  }));
              }
  
          }
  
          return {
              listen:listen
          }
  
      }());
  
  
      Galapagos.ProductItem = (function(){
      console.log("Galapagos.ProductItem");
          var cat;
          var $imageContainer;
          var $images;
          var imageZoomInstances = [];
          function init() {
        console.log("Galapagos.ProductItem init()");
  
              cat = Y.QueryString.parse(location.search.substring(1)).category;
              $imageContainer = Y.one('#jsProductItemImages');
              $images = $imageContainer.all('img[data-src]');
  
              if ( cat ) setCatCrumb();
              loadProductDetailImages();
  
              bindEventListeners();
              bindTweakListeners();
              buildProductDetailImagesLightbox();
  
          }
  
          function bindEventListeners() {
        console.log("Galapagos.ProductItem bindEventListeners()");
              Y.on('resize', function(){
                  loadProductDetailImages();
              });
  
          }
  
          function setCatCrumb() {
        console.log("Galapagos.ProductItem setCatCrumb()");
              var $catCrumb = Y.one('#jsCategoryCrumb');
              var $catCrumbLink = $catCrumb.one('a');
              var catCrumbHref = $catCrumbLink.getAttribute('href');
  
              //var $mobileCatCrumbLink = Y.one('#jsMobileCategoryCrumb');
  
              $catCrumbLink.set('text', cat).setAttribute('href', catCrumbHref + '?category=' + encodeURIComponent(cat));
              //$mobileCatCrumbLink.setAttribute('href', catCrumbHref + '?category=' + encodeURIComponent(cat));
  
              $catCrumb.removeClass('galapagos-display-none');
  
          }
  
          function loadProductDetailImages() {
        console.log("Galapagos.ProductItem loadProductDetailImages()");
              var imageZoomEnabled = Y.one('.tweak-product-item-image-zoom-enabled');
  
              $images.each(function(image) {
  
                  ImageLoader.load(image.removeAttribute('data-load'), { load:true });
  
                  if (imageZoomEnabled) {
                      image.on('load', function() {
                          instantiateImageZoom(image);
                      });
                  }
              });
  
          }
  
          function instantiateImageZoom(image) {
        console.log("Galapagos.ProductItem instantiateImageZoom()");
              imageZoomInstances.push(new Y.Squarespace.ImageZoom({
                  host: image.get('parentNode'),
                  behavior: 'hover',
                  zoom: parseFloat(Y.Squarespace.Template.getTweakValue('tweak-product-item-image-zoom-factor'))
              }));
          }
  
          function destroyImageZoomInstances() {
        console.log("Galapagos.ProductItem destroyImageZoomInstances()");
              if (!imageZoomInstances || imageZoomInstances.length &lt; 1) {
                return;
              }
  
              Y.Array.each(imageZoomInstances, function(zoomInstance){
                zoomInstance.destroy(true);
              });
          }
  
          function buildProductDetailImagesLightbox() {
        console.log("Galapagos.ProductItem buildProductDetailImagesLightbox()");
              if ($images.size() &gt;= 1 ) {
  
                  var lightboxSet = [];
  
                  $images.each(function(image) {
                      lightboxSet.push({
                          content: image
                      });
                  });
  
                  // Only show controls for size &gt; 1
                  var hasControls = $images.size() &gt; 1;
  
                  $imageContainer.delegate('click', function(e) {
  
                      var lightbox = new Y.Squarespace.Lightbox2({
                          controls: {
                              previous: hasControls,
                              next: hasControls
                          },
                          set: lightboxSet,
                          currentSetIndex: $images.indexOf(e.target)
                      });
  
                      lightbox.render();
  
                  }, 'img', this);
  
              }
          }
  
          function bindTweakListeners() {
        console.log("Galapagos.ProductItem bindTweakListeners()");
              if (Y.Global) {
                  Y.Global.on('tweak:close', function() {
                      if (Y.one('.collection-type-products.view-item')) {
                          destroyImageZoomInstances();
                          if (Y.one('.tweak-product-item-image-zoom-enabled')) {
                              $images.each(function(image){
                                  instantiateImageZoom(image);
                              });
                          }
                      }
                  }, this);
              }
          }
  
          return {
              init:init
          }
  
      }());
  
  
      Galapagos.ProductList = (function(){
      console.log("Galapagos.ProductList");
  
          var $catNav,
              $productGrid,
              $productGridOrphans,
              $productGridImages,
              $orphanProducts,
              productCount,
              maxGridUnit,
              orphanProductCount,
              isGridBuilt;
  
  
          function init() {
        console.log("Galapagos.ProductList init()");
  
              $catNav = Y.one('#jsCatNav');
              $productGrid = Y.one('#jsProductGrid');
              $productGridOrphans = Y.one('#jsProductGridOrphans');
  
              if (!Y.UA.mobile &amp;&amp; Y.one('.show-alt-image-on-hover:not(.product-info-style-overlay)')) {
                  $productGridImages = $productGrid.all('img[data-src]');
              } else {
                  $productGridImages = $productGrid.all('img.productlist-image--main[data-src]');
              }
  
              productCount = $productGrid.all('.productlist-item').size();
              maxGridUnit = 8;
              orphanProductCount;
              isGridBuilt = false;
  
              bindEventListeners();
              bindTweakListeners();
              if($catNav) setActiveCategory();
              if(Y.one('body').hasClass('product-grid-style-organic')) {
                  buildGrid();
              } else {
                  $productGrid.removeClass('loading').removeClass('loading-height');
                  loadGridImages($productGridImages);
              }
  
          }
  
          function bindEventListeners() {
        console.log("Galapagos.ProductList bindEventListeners()");
              Y.on('resize', function(){
                  loadGridImages($productGridImages);
              });
  
          }
  
          function buildGrid() {
        console.log("Galapagos.ProductList buildGrid()");
              for (var i = maxGridUnit; i &gt; 0; i--) {
  
                  orphanProductCount = productCount % i;
  
                  if(productCount &lt;= maxGridUnit || i &gt; 4) {
  
                      if(0 === orphanProductCount) {
  
                          $productGrid.addClass('item-grid-' + i);
  
                          isGridBuilt = true;
                          break;
  
                      }
  
                  } else {
  
                      if(0 === productCount % 9) {  // if productCount is a multiple of 9, use the 9-grid.  we use 9-grid only for multiples of 9 because 8-grid looks more interesting.
  
                          $productGrid.addClass('item-grid-' + 9);
  
                      } else { // otherwise, use the 8-grid and put the remainder into the orphan div
  
                          $productGrid.addClass('item-grid-' + maxGridUnit);
                          $orphanProducts = Y.all('.productlist-item').slice((productCount % maxGridUnit) * -1);
  
                          $productGridOrphans
                              .append($orphanProducts)
                              .addClass('item-grid-' + productCount % maxGridUnit);
                      }
  
                      isGridBuilt = true;
                      break;
  
                  }
  
              }
  
              if(isGridBuilt) {
                  $productGrid.removeClass('loading').removeClass('loading-height');
                  loadGridImages();
              }
  
          }
  
          function setActiveCategory() {
        console.log("Galapagos.ProductList setActiveCategory()");
  
              var catNavItemCount = $catNav.all('.catnav-item').size();
  
              for (var i = catNavItemCount - 1; i &gt; 0; i--) {
  
                  var $item = $catNav.all('.catnav-item').item(i);
                  var $link = $item.one('.catnav-link');
                  var category = Y.QueryString.parse(location.search.substring(1)).category;
                  var href = Y.QueryString.parse($link.getAttribute('href').substring(2)).category;
  
                  if(category &amp;&amp; href &amp;&amp; category === href) {
                      $item.addClass('active-link');
                  }
                  else if(!category) {
                      $catNav.one('#jsCatNavRoot').addClass('active-link');
                  }
  
              }
  
          }
  
          function loadGridImages() {
        console.log("Galapagos.ProductList loadGridImages()");
              $productGridImages.each(function(image) {
                  ImageLoader.load(image.removeAttribute('data-load'), { load: true });
  
                  image.on('load', function(){
                      if (image.hasClass('productlist-image--main.has-alt-image')) {
                          image.siblings('.productlist-image--alt').removeClass('galapagos-hidden');
                      }
                  });
              });
          }
  
          function bindTweakListeners() {
        console.log("Galapagos.ProductList bindTweakListeners()");
              if (Y.Global) {
  
                  Y.Global.on(['tweak:beforeopen', 'tweak:close', 'tweak:reset'], function() {
                      setTimeout(function(){
                          Galapagos.ProductList.init();
                      }, 1000);
                  });
  
                  Y.Global.on(['tweak:beforeopen'], function() {
                      setTimeout(function(){
                          Galapagos.ProductList.init();
                          $productGrid.one('.productlist-item').addClass('is-hovered');
                      }, 1000);
                  });
  
                  Y.Global.on(['tweak:close'], function() {
                      setTimeout(function(){
                          Galapagos.ProductList.init();
                          $productGrid.one('.productlist-item').removeClass('is-hovered');
                      }, 1000);
                  });
  
              }
  
              Galapagos.TweakListener.listen('product-grid-style', function(value) {
  
                  if('Organic' === value) {
                      buildGrid();
                  } else {
                      $productGrid.append($orphanProducts);
                      loadGridImages();
                  }
              });
  
              Galapagos.TweakListener.listen('product-info-style', function(value) {
  
                  if('Overlay' === value) {
                      $productGrid.one('.productlist-item').addClass('is-hovered');
                  } else {
                      $productGrid.one('.productlist-item').removeClass('is-hovered');
                  }
  
              });
  
              Galapagos.TweakListener.listen('productImageAspectRatio', function(value) {
                  loadGridImages();
              });
  
              Galapagos.TweakListener.listen('productImageSpacing', function(value) {
                  loadGridImages();
              });
  
          }
  
          return {
              init:init
          }
  
  
      }());
  
  
      Y.on('domready', function() {
  
          Galapagos.Site.init();
  
      });
  
  });
  </code></pre>
  
  <h1>My Attempts</h1>
  
  <p>My first few attempts have been dropping the <code>jsProductItemImages</code> div from the Product view and dumping in the entire <code>figure</code> block from the Quick View then updating the associated css. While it pulls in the images (I can see them in the inspector and they take up space on the page) it shows up as being blank.</p>
  
  <p>I also tried only using the thumbnails section from the Quick View and limiting the Product View to only show the first image by using <code>{.section items.0}</code> but then any thumbnail I clicked wouldn't swap out without writing the script for it (obviously) but I didn't want to write something like that when I know it exists in the code already!</p>
  
  <p>Any help would be greatly appreciated!</p>
  
  <h1>UPDATE:</h1>
  
  <p>After replacing the product view markup with the quick view markup I ran into these errors</p>
  
  <pre><code>Uncaught TypeError: Cannot read property 'all' of null    site.js:104
    init                  @ site.js:104
    init                  @ site.js:17
    (anonymous function)  @ site.js:432
    _notify                 @ common-2a739bf…-min.js:1479
    notify                  @ common-2a739bf…-min.js:1479
    _notify                 @ common-2a739bf…-min.js:1475
    _procSubs             @   common-2a739bf…-min.js:1476
    fireSimple              @ common-2a739bf…-min.js:1476
    _fire                 @   common-2a739bf…-min.js:1476
    fire                  @   common-2a739bf…-min.js:1489
    _load                 @   common-2a739bf…-min.js:1463
    f                     @   common-2a739bf…-min.js:1457
  </code></pre>
  
  <p>Unsure why it's hitting an error with .all because it should be addressing the same array of images in both situations?</p>