<div class="demo-page-zoomer">

    <h4>Single image</h4>
    <a href="#" data-zoomer="https://picsum.photos/2000/2000">
        Open single image
    </a>

    <h4>Gallery (one link)</h4>
    <a href="#" data-zoomer="gallery" data-zoomer-gallery="demo-gallery-1">
        Open gallery
    </a>

    <script>
        document.addEventListener('DOMContentLoaded', () => {
            new Zoomer({
                'gallery': 'demo-gallery-1',
                'images': [{
                        'thumb': 'https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-main.png?h=400&amp;w=500&amp;hash=4E254D2964FDDD4D12E42FC032EB8F15',
                        'large': 'https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-main.jpg',
                        'title': 'DDJ-SP1',
                    },
                    {
                        'thumb': 'https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-angle.png?h=400&amp;w=500&amp;hash=046DD37AD384473762672F5553C1A823',
                        'large': 'https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-angle.jpg',
                        'title': 'DDJ-SP1',
                    },
                    {
                        'thumb': 'https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-side.png?h=400&amp;w=500&amp;hash=E511BA1EB20FAF9E6A348DAEE13B3135',
                        'large': 'https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-side.jpg',
                        'title': 'DDJ-SP1',
                    },
                    {
                        'thumb': 'https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-front.png?h=400&amp;w=500&amp;hash=F5F0BADDBA4FFEF5E7168D1C31246F8F',
                        'large': 'https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-front.jpg',
                        'title': 'DDJ-SP1',
                    },
                    {
                        'thumb': 'https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-perspective.png?h=400&amp;w=500&amp;hash=9127D631BD40CE9D2118A81BB05AAE0C',
                        'large': 'https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-perspective.jpg',
                        'title': 'DDJ-SP1',
                    },
                ],
            });
        });
    </script>

    <h4>Gallery 2 (multiple triggers, less triggers for larger gallery)</h4>
    <ul class="demo-page-zoomer-list">
        <li>
            <a href="#" data-zoomer="gallery" data-zoomer-gallery="demo-gallery-2" data-zoomer-index="1">
                <img src="https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-main.png?h=400&amp;w=500&amp;hash=4E254D2964FDDD4D12E42FC032EB8F15" alt="DDJ-SP1">
            </a>
        </li>
        <li>
            <a href="#" data-zoomer="gallery" data-zoomer-gallery="demo-gallery-2" data-zoomer-index="2">
                <img src="https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-angle.png?h=400&amp;w=500&amp;hash=046DD37AD384473762672F5553C1A823" alt="DDJ-SP1">
            </a>
        </li>
        <li>
            <a href="#" data-zoomer="gallery" data-zoomer-gallery="demo-gallery-2" data-zoomer-index="3">
                <img src="https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-side.png?h=400&amp;w=500&amp;hash=E511BA1EB20FAF9E6A348DAEE13B3135" alt="DDJ-SP1">
            </a>
        </li>
    </ul>

    <script>
        document.addEventListener('DOMContentLoaded', () => {
            new Zoomer({
                'gallery': 'demo-gallery-2',
                'images': [{
                        'thumb': 'https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-main.png?h=400&amp;w=500&amp;hash=4E254D2964FDDD4D12E42FC032EB8F15',
                        'large': 'https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-main.jpg',
                        'title': 'DDJ-SP1',
                    },
                    {
                        'thumb': 'https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-angle.png?h=400&amp;w=500&amp;hash=046DD37AD384473762672F5553C1A823',
                        'large': 'https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-angle.jpg',
                        'title': 'DDJ-SP1',
                    },
                    {
                        'thumb': 'https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-side.png?h=400&amp;w=500&amp;hash=E511BA1EB20FAF9E6A348DAEE13B3135',
                        'large': 'https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-side.jpg',
                        'title': 'DDJ-SP1',
                    },
                    {
                        'thumb': 'https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-front.png?h=400&amp;w=500&amp;hash=F5F0BADDBA4FFEF5E7168D1C31246F8F',
                        'large': 'https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-front.jpg',
                        'title': 'DDJ-SP1',
                    },
                    {
                        'thumb': 'https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-perspective.png?h=400&amp;w=500&amp;hash=9127D631BD40CE9D2118A81BB05AAE0C',
                        'large': 'https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-perspective.jpg',
                        'title': 'DDJ-SP1',
                    },
                ],
            });
        });
    </script>

    <h4>Gallery 3 (multiple triggers, no extra JS required)</h4>
    <ul class="demo-page-zoomer-list">
        <li>
            <a href="#" data-zoomer="gallery" data-zoomer-gallery="demo-gallery-3" data-zoomer-image-thumbnail="https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-main.png?h=400&amp;w=500&amp;hash=4E254D2964FDDD4D12E42FC032EB8F15" data-zoomer-image-large="https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-main.jpg">
                <img src="https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-main.png?h=400&amp;w=500&amp;hash=4E254D2964FDDD4D12E42FC032EB8F15" alt="DDJ-SP1">
            </a>
        </li>
        <li>
            <a href="#" data-zoomer="gallery" data-zoomer-gallery="demo-gallery-3" data-zoomer-image-thumbnail="https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-angle.png?h=400&amp;w=500&amp;hash=046DD37AD384473762672F5553C1A823" data-zoomer-image-large="https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-angle.jpg">
                <img src="https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-angle.png?h=400&amp;w=500&amp;hash=046DD37AD384473762672F5553C1A823" alt="DDJ-SP1">
            </a>
        </li>
        <li>
            <a href="#" data-zoomer="gallery" data-zoomer-gallery="demo-gallery-3" data-zoomer-image-thumbnail="https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-side.png?h=400&amp;w=500&amp;hash=E511BA1EB20FAF9E6A348DAEE13B3135" data-zoomer-image-large="https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-side.jpg">
                <img src="https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-side.png?h=400&amp;w=500&amp;hash=E511BA1EB20FAF9E6A348DAEE13B3135" alt="DDJ-SP1">
            </a>
        </li>
        <li>
            <a href="#" data-zoomer="gallery" data-zoomer-gallery="demo-gallery-3" data-zoomer-image-thumbnail="https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-front.png?h=400&amp;w=500&amp;hash=F5F0BADDBA4FFEF5E7168D1C31246F8F" data-zoomer-image-large="https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-front.jpg" data-zoomer-title="Specific title for this image">
                <img src="https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-front.png?h=400&amp;w=500&amp;hash=F5F0BADDBA4FFEF5E7168D1C31246F8F" alt="DDJ-SP1">
            </a>
        </li>
        <li>
            <a href="#" data-zoomer="gallery" data-zoomer-gallery="demo-gallery-3" data-zoomer-image-thumbnail="https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-perspective.png?h=400&amp;w=500&amp;hash=9127D631BD40CE9D2118A81BB05AAE0C" data-zoomer-image-large="https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-perspective.jpg">
                <img src="https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-perspective.png?h=400&amp;w=500&amp;hash=9127D631BD40CE9D2118A81BB05AAE0C" alt="DDJ-SP1">
            </a>
        </li>
    </ul>

</div>

<style>
    /* this is demo page css only */
    .demo-page-zoomer {
        padding: 40px;
    }

    .demo-page-zoomer ul {
        display: flex;
        justify-content: flex-start;
        align-items: stretch;
        flex-wrap: wrap;
        margin: 0;
        padding: 0;
        list-style: none;
    }

    .demo-page-zoomer ul li {
        flex: 0 0 150px;
        border: 1px solid #efefef;
        padding: 20px;
    }

    .demo-page-zoomer ul li img {
        display: block;
        width: 100%;
        margin: 0;
    }
</style>
<div class="demo-page-zoomer">

  <h4>Single image</h4>
  <a href="#" data-zoomer="https://picsum.photos/2000/2000">
    Open single image
  </a>

  <h4>Gallery (one link)</h4>
  <a href="#" data-zoomer="gallery" data-zoomer-gallery="demo-gallery-1">
    Open gallery
  </a>

  <script>
  document.addEventListener('DOMContentLoaded', () => {
    new Zoomer({
      'gallery': 'demo-gallery-1',
      'images': [
        {
          'thumb': 'https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-main.png?h=400&amp;w=500&amp;hash=4E254D2964FDDD4D12E42FC032EB8F15',
          'large': 'https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-main.jpg',
          'title': 'DDJ-SP1',
        },
        {
          'thumb': 'https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-angle.png?h=400&amp;w=500&amp;hash=046DD37AD384473762672F5553C1A823',
          'large': 'https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-angle.jpg',
          'title': 'DDJ-SP1',
        },
        {
          'thumb': 'https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-side.png?h=400&amp;w=500&amp;hash=E511BA1EB20FAF9E6A348DAEE13B3135',
          'large': 'https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-side.jpg',
          'title': 'DDJ-SP1',
        },
        {
          'thumb': 'https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-front.png?h=400&amp;w=500&amp;hash=F5F0BADDBA4FFEF5E7168D1C31246F8F',
          'large': 'https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-front.jpg',
          'title': 'DDJ-SP1',
        },
        {
          'thumb': 'https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-perspective.png?h=400&amp;w=500&amp;hash=9127D631BD40CE9D2118A81BB05AAE0C',
          'large': 'https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-perspective.jpg',
          'title': 'DDJ-SP1',
        },
      ],
    });
  });
  </script>

  <h4>Gallery 2 (multiple triggers, less triggers for larger gallery)</h4>
  <ul class="demo-page-zoomer-list">
    <li>
      <a href="#" data-zoomer="gallery" data-zoomer-gallery="demo-gallery-2" data-zoomer-index="1">
        <img src="https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-main.png?h=400&amp;w=500&amp;hash=4E254D2964FDDD4D12E42FC032EB8F15" alt="DDJ-SP1">
      </a>
    </li>
    <li>
      <a href="#" data-zoomer="gallery" data-zoomer-gallery="demo-gallery-2" data-zoomer-index="2">
        <img src="https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-angle.png?h=400&amp;w=500&amp;hash=046DD37AD384473762672F5553C1A823" alt="DDJ-SP1">
      </a>
    </li>
    <li>
      <a href="#" data-zoomer="gallery" data-zoomer-gallery="demo-gallery-2" data-zoomer-index="3">
        <img src="https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-side.png?h=400&amp;w=500&amp;hash=E511BA1EB20FAF9E6A348DAEE13B3135" alt="DDJ-SP1">
      </a>
    </li>
    {{!--
    // disabled this to demo only limited triggers can start larger gallery
    <li>
      <a href="#" data-zoomer="gallery" data-zoomer-gallery="demo-gallery-2" data-zoomer-index="4">
        <img src="https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-front.png?h=400&amp;w=500&amp;hash=F5F0BADDBA4FFEF5E7168D1C31246F8F" alt="DDJ-SP1">
      </a>
    </li>
    <li>
      <a href="#" data-zoomer="gallery" data-zoomer-gallery="demo-gallery-2" data-zoomer-index="5">
        <img src="https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-perspective.png?h=400&amp;w=500&amp;hash=9127D631BD40CE9D2118A81BB05AAE0C" alt="DDJ-SP1">
      </a>
    </li>
    --}}
  </ul>

  <script>
  document.addEventListener('DOMContentLoaded', () => {
    new Zoomer({
      'gallery': 'demo-gallery-2',
      'images': [
        {
          'thumb': 'https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-main.png?h=400&amp;w=500&amp;hash=4E254D2964FDDD4D12E42FC032EB8F15',
          'large': 'https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-main.jpg',
          'title': 'DDJ-SP1',
        },
        {
          'thumb': 'https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-angle.png?h=400&amp;w=500&amp;hash=046DD37AD384473762672F5553C1A823',
          'large': 'https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-angle.jpg',
          'title': 'DDJ-SP1',
        },
        {
          'thumb': 'https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-side.png?h=400&amp;w=500&amp;hash=E511BA1EB20FAF9E6A348DAEE13B3135',
          'large': 'https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-side.jpg',
          'title': 'DDJ-SP1',
        },
        {
          'thumb': 'https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-front.png?h=400&amp;w=500&amp;hash=F5F0BADDBA4FFEF5E7168D1C31246F8F',
          'large': 'https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-front.jpg',
          'title': 'DDJ-SP1',
        },
        {
          'thumb': 'https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-perspective.png?h=400&amp;w=500&amp;hash=9127D631BD40CE9D2118A81BB05AAE0C',
          'large': 'https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-perspective.jpg',
          'title': 'DDJ-SP1',
        },
      ],
    });
  });
  </script>

  <h4>Gallery 3 (multiple triggers, no extra JS required)</h4>
  <ul class="demo-page-zoomer-list">
    <li>
      <a href="#"
        data-zoomer="gallery"
        data-zoomer-gallery="demo-gallery-3"
        data-zoomer-image-thumbnail="https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-main.png?h=400&amp;w=500&amp;hash=4E254D2964FDDD4D12E42FC032EB8F15"
        data-zoomer-image-large="https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-main.jpg"
      >
        <img src="https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-main.png?h=400&amp;w=500&amp;hash=4E254D2964FDDD4D12E42FC032EB8F15" alt="DDJ-SP1">
      </a>
    </li>
    <li>
      <a href="#"
        data-zoomer="gallery"
        data-zoomer-gallery="demo-gallery-3"
        data-zoomer-image-thumbnail="https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-angle.png?h=400&amp;w=500&amp;hash=046DD37AD384473762672F5553C1A823"
        data-zoomer-image-large="https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-angle.jpg"
      >
        <img src="https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-angle.png?h=400&amp;w=500&amp;hash=046DD37AD384473762672F5553C1A823" alt="DDJ-SP1">
      </a>
    </li>
    <li>
      <a href="#"
        data-zoomer="gallery"
        data-zoomer-gallery="demo-gallery-3"
        data-zoomer-image-thumbnail="https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-side.png?h=400&amp;w=500&amp;hash=E511BA1EB20FAF9E6A348DAEE13B3135"
        data-zoomer-image-large="https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-side.jpg"
      >
        <img src="https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-side.png?h=400&amp;w=500&amp;hash=E511BA1EB20FAF9E6A348DAEE13B3135" alt="DDJ-SP1">
      </a>
    </li>
    <li>
      <a href="#"
        data-zoomer="gallery"
        data-zoomer-gallery="demo-gallery-3"
        data-zoomer-image-thumbnail="https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-front.png?h=400&amp;w=500&amp;hash=F5F0BADDBA4FFEF5E7168D1C31246F8F"
        data-zoomer-image-large="https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-front.jpg"
        data-zoomer-title="Specific title for this image"
      >
        <img src="https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-front.png?h=400&amp;w=500&amp;hash=F5F0BADDBA4FFEF5E7168D1C31246F8F" alt="DDJ-SP1">
      </a>
    </li>
    <li>
      <a href="#"
        data-zoomer="gallery"
        data-zoomer-gallery="demo-gallery-3"
        data-zoomer-image-thumbnail="https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-perspective.png?h=400&amp;w=500&amp;hash=9127D631BD40CE9D2118A81BB05AAE0C"
        data-zoomer-image-large="https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-perspective.jpg"
      >
        <img src="https://www.pioneerdj.com/-/media/pioneerdj/images/products/controller/ddj-sp1/black/ddj-sp1-perspective.png?h=400&amp;w=500&amp;hash=9127D631BD40CE9D2118A81BB05AAE0C" alt="DDJ-SP1">
      </a>
    </li>
  </ul>

</div>




















<style>
/* this is demo page css only */
.demo-page-zoomer { padding: 40px; }
.demo-page-zoomer ul { display: flex; justify-content: flex-start; align-items: stretch; flex-wrap: wrap; margin: 0; padding: 0; list-style: none; }
.demo-page-zoomer ul li { flex: 0 0 150px; border: 1px solid #efefef; padding: 20px; }
.demo-page-zoomer ul li img { display: block; width: 100%; margin: 0; }
</style>
/* No context defined. */
  • Content:
    /**
     * Zoomer
     *
     * This is the plugin code for the Zoomer overlayer/gallery/image zoom effect.
     *
     * @demo one image:
     *
     * new Zoomer({
     *   trigger: document.querySelector('.link'),
     *   image: 'https://www.url.tld/full-size-image.jpg',
     * });
     *
     * @demo gallery of images:
     *
     * new Zoomer({
     *   gallery: 'specific-name',
     *   images: [
     *     {
     *       'thumb': '/path/thumnail-image.jpg',
     *       'large': '/path/full-size-image.jpg',
     *       'title': 'Optional image alt param',
     *     },
     *     ...
     *   ],
     * });
     *
     */
    
    // import ZoomerOverlayer from './ZoomerOverlayer';
    
    const Zoomer = function(settings = {}) {
      const defaults = {
        downloadButton: true, // show download button
        generateOverlayerOnLoad: false, // generate overlayer dom content on page load
    
        scaleWithBrowser: true, // boolean to scale real img size or with browser width
        startZoomPercentage: 30, // start zoom percentage
        minScale: .2, // minimum scale size
        maxScale: 3.5, // maximum scale size
        blockScrollClass: 'zoomeractive', // class that is placed on the html element to block scrolling
    
        // - required:
        // trigger: node element to launch the zoomer
        // image: string to image (URL or file path)
        // — or:
        // gallery: string to 'ID' the gallery
        // images: array of images (with thumb & large)
      };
    
      this.settings = {
        ...defaults,
        ...settings,
      };
    
      this.el = {};
      this.init();
    };
    
    Zoomer.prototype.init = function() {
      this.getElements();
    
      if (!(this.isArray(this.images) && this.images.length > 0)) {
        return;
      }
    
      this.overlayer = new ZoomerOverlayer({
        images: this.images,
        downloadButton: this.settings.downloadButton,
        scaleWithBrowser: this.settings.scaleWithBrowser,
        startZoomPercentage: this.settings.startZoomPercentage,
        minScale: this.settings.minScale,
        maxScale: this.settings.maxScale,
        blockScrollClass: this.settings.blockScrollClass,
      });
    
      if (this.settings.generateOverlayerOnLoad === true) {
        this.overlayer.generate();
      }
    
      this.addEvents();
    };
    
    Zoomer.prototype.getElements = function() {
      if (this.isNode(this.settings.trigger) && this.isString(this.settings.image)) {
        this.el.triggers = [this.settings.trigger];
        this.images = [{
          large: this.settings.image,
          title: this.isString(this.settings.trigger.dataset.zoomerTitle) ? this.settings.trigger.dataset.zoomerTitle : (this.settings.trigger.title ?? ''),
        }];
      } else if (this.isString(this.settings.gallery)) {
        this.el.triggers = [...document.querySelectorAll(`[data-zoomer-gallery="${this.settings.gallery}"]`)];
        if (this.isArray(this.settings.images) && this.settings.images.length > 0) {
          this.images = this.settings.images;
        } else {
          this.el.triggers = [...document.querySelectorAll(`[data-zoomer-gallery="${this.settings.gallery}"]`)];
          this.images = [];
          this.el.triggers.forEach(trigger => {
            if (this.isString(trigger.dataset.zoomerImageThumbnail) && this.isString(trigger.dataset.zoomerImageLarge)) {
              const thumb = trigger.dataset.zoomerImageThumbnail;
              const large = trigger.dataset.zoomerImageLarge;
              const title = this.isString(trigger.dataset.zoomerTitle) ? trigger.dataset.zoomerTitle : (trigger.title ?? '');
              this.images.push({ thumb, large, title });
            }
          });
        }
      }
    };
    
    Zoomer.prototype.addEvents = function() {
      if (this.isArray(this.el.triggers)) {
        this.el.triggers.forEach((trigger, triggerIndex) => {
          trigger.addEventListener('click', e => {
            e.preventDefault();
            this.open(trigger.dataset.zoomerIndex ?? (1 + triggerIndex));
          });
        });
      }
    
      document.addEventListener('keyup', e => {
        if (this.overlayer && e.key === 'Escape') {
          this.overlayer.hide();
        }
      });
    };
    
    Zoomer.prototype.open = function(number = 1) {
      if (!this.overlayer || !this.overlayer.el.wrapper) {
        this.overlayer.generate();
      }
    
      if (!this.overlayer) {
        return;
      }
    
      this.overlayer.show(number);
    };
    
    Zoomer.prototype.close = function() {
      if (!this.overlayer) {
        return;
      }
    
      this.overlayer.hide();
    };
    
    Zoomer.prototype.scaleTo = function(percentage) {
      if (percentage < 0 || percentage > 100) {
        return;
      }
    
      this.overlayer.scaleTo(percentage);
    };
    
    Zoomer.prototype.isString = function(v) {
      return (typeof v === 'string' || v instanceof String) && v.length > 0;
    };
    
    Zoomer.prototype.isArray = function(v) {
      return Array.isArray(v);
    };
    
    Zoomer.prototype.isNode = function(v) {
      return v && v.nodeType && v.parentNode;
    };
    
    window.Zoomer = Zoomer;
    // export default Zoomer;
    
  • URL: /components/raw/zoomer/Zoomer.js
  • Filesystem Path: ../src/04_organisms/zoomer/Zoomer.js
  • Size: 4.6 KB
  • Content:
    /**
     * Zoomer init code
     * This code just does the startups of Zoomer galleries.
     */
    
    const initSingleZoomers = () => {
      [...document.querySelectorAll('[data-zoomer]')].forEach(el => {
        if (el.dataset.zoomer !== 'gallery') {
          new Zoomer({
            trigger: el,
            image: el.dataset.zoomer,
          });
        }
      });
    };
    
    const initGalleryZoomers = () => {
      const selector = '[data-zoomer="gallery"][data-zoomer-gallery][data-zoomer-image-thumbnail][data-zoomer-image-large]'; // don't change! All data elements are required - if it would only be '[data-zoomer="gallery"]' it might duplicate galleries!
      const galleries = [];
    
      [...document.querySelectorAll(selector)].forEach(el => {
        galleries[el.dataset.zoomerGallery] = el.dataset.zoomerGallery;
      });
    
      Object.keys(galleries).forEach(gallery => new Zoomer({ gallery }));
    };
    
    const initOldZoomtoolZoomers = () => {
      const selectors = {
        wrapper: '.section', // maybe better: '.image-thumb-grid'
        links: 'a.zoom-tool', // <a href="#zoom-tool-01" class="zoom-thumb image-thumb trigger__open-overlayer zoom-tool">
        image: 'img[data-large][data-small]', // <img ... class="zoomtool-capable" rel="zoom-product" data-...>
      };
    
      [...document.querySelectorAll(selectors.wrapper)].forEach((galleryWrapper, galleryIndex) => {
        const galleryName = `original-zoomer-updated--${1 + galleryIndex}`;
        const images = [];
    
        [...galleryWrapper.querySelectorAll(selectors.links)].forEach((link, linkIndex) => {
          const image = link.querySelector(selectors.image);
          if (image && image.parentNode) {
            images.push({
              'thumb': image.dataset.small,
              'large': image.dataset.large,
              'title': image.alt ?? '',
            });
    
            link.dataset.zoomer = 'gallery';
            link.dataset.zoomerGallery = galleryName;
            link.dataset.zoomerItem = 1 + linkIndex;
          }
        });
    
        if (galleryName.length && images.length) {
          new Zoomer({ gallery: galleryName, images });
        }
      });
    };
    
    document.addEventListener('DOMContentLoaded', () => {
      if (!window.Zoomer) {
        return;
      }
    
      initSingleZoomers();
      initGalleryZoomers();
      initOldZoomtoolZoomers();
    });
    
  • URL: /components/raw/zoomer/ZoomerInit.js
  • Filesystem Path: ../src/04_organisms/zoomer/ZoomerInit.js
  • Size: 2.2 KB
  • Content:
    // ZoomerOverlayer is external JS file that is required by Zoomer.js
    
    // import ZoomerScaler from './ZoomerScaler';
    
    const ZoomerOverlayer = function(settings = {}) {
      const defaults = {
        images: [],
        scaleWithBrowser: false,
        startZoomPercentage: 50,
        minScale: .1,
        maxScale: 2,
        downloadButton: false,
        blockScrollClass: 'zoomeractive',
      };
    
      this.settings = {
        ...defaults,
        ...settings,
      };
    
      this.el = {};
      this.generated = false;
      this.activeVisual = -1;
    };
    
    ZoomerOverlayer.prototype.generate = function() {
      if (this.generated || this.el.wrapper || !this.settings.images || this.settings.images.length <= 0) {
        return;
      }
    
      this.el.wrapper = document.createElement('div');
      this.el.wrapper.classList.add('zoomer');
      this.el.wrapper.classList.toggle('zoomer--fullscale', !this.settings.scaleWithBrowser);
    
      this.el.inner = document.createElement('div');
      this.el.inner.classList.add('zoomer__inner');
    
      this._generateHeader(this.el.inner);
      this._generateVisual(this.el.inner);
      this._generateThumbs(this.el.inner);
    
      this.scaleTo(this.settings.startZoomPercentage);
    
      this.el.wrapper.appendChild(this.el.inner);
      document.body.appendChild(this.el.wrapper);
    
      this.addEvents();
    
      this.generated = true;
    };
    
    ZoomerOverlayer.prototype.addEvents = function() {
      if (this.el && this.el.visual && this.el.visual.wrapper && this.el.visual.inner) {
        this.el.visual.wrapper.addEventListener('wheel', e => {
          if (!this.scaler) {
            return;
          }
    
          e.preventDefault();
          const newValue = this.scaler.getValue() + (e.deltaY / 50);
          this.scaler.scaleTo(newValue);
        });
    
        this.el.visual.wrapper.addEventListener('mousedown', e => this._startMove(e));
        this.el.visual.wrapper.addEventListener('mousemove', e => this._isMoving(e));
        this.el.visual.wrapper.addEventListener('mouseup', () => this._endMove());
        this.el.visual.wrapper.addEventListener('mouseleave', () => this._endMove());
    
        this.el.visual.wrapper.addEventListener('touchstart', e => this._startMove(e));
        this.el.visual.wrapper.addEventListener('touchmove', e => this._isMoving(e));
        this.el.visual.wrapper.addEventListener('touchend', () => this._endMove());
      }
    };
    
    ZoomerOverlayer.prototype._generateHeader = function(wrapperEl) {
      if (!this.el) {
        return;
      }
    
      this.el.header = {};
    
      this.scaler = new ZoomerScaler({
        onUpdate: percentage => this.scaleTo(percentage),
      });
    
      if (this.settings.downloadButton) {
        this.el.download = document.createElement('a');
        this.el.download.href = '#';
        this.el.download.setAttribute('download', true);
        this.el.download.target = '_blank';
        this.el.download.classList.add('zoomer-header__download');
        this.el.download.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none" viewBox="0 0 16 16"><path fill="currentColor" fill-rule="evenodd" d="M8.53 11.78a.75.75 0 0 1-1.06 0l-2.5-2.5a.75.75 0 0 1 1.06-1.06l1.22 1.22V1.75a.75.75 0 0 1 1.5 0v7.69l1.22-1.22a.75.75 0 1 1 1.06 1.06zM1.75 13.5a.75.75 0 0 0 0 1.5h12.5a.75.75 0 0 0 0-1.5z" clip-rule="evenodd"/></svg>';
      }
    
      this.el.close = document.createElement('button');
      this.el.close.classList.add('zoomer-header__close');
      this.el.close.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none" viewBox="0 0 16 16"><path fill="currentColor" fill-rule="evenodd" d="M3.47 3.47a.75.75 0 0 1 1.06 0L8 6.94l3.47-3.47a.75.75 0 1 1 1.06 1.06L9.06 8l3.47 3.47a.75.75 0 1 1-1.06 1.06L8 9.06l-3.47 3.47a.75.75 0 0 1-1.06-1.06L6.94 8 3.47 4.53a.75.75 0 0 1 0-1.06" clip-rule="evenodd"/></svg>';
      this.el.close.addEventListener('click', () => this.hide());
    
      this.el.header.inner = document.createElement('div');
      this.el.header.inner.classList.add('zoomer-header__inner');
      this.el.header.inner.appendChild(this.scaler.getElement());
    
      if (this.settings.downloadButton && this.el.download) {
        this.el.header.inner.appendChild(this.el.download);
      }
    
      this.el.header.inner.appendChild(this.el.close);
    
      this.el.header.wrapper = document.createElement('div');
      this.el.header.wrapper.classList.add('zoomer-header');
      this.el.header.wrapper.appendChild(this.el.header.inner);
    
      if (wrapperEl) {
        wrapperEl.appendChild(this.el.header.wrapper);
      }
    };
    
    ZoomerOverlayer.prototype._generateVisual = function(wrapperEl) {
      this.el.visual = {};
    
      this.el.visual.wrapper = document.createElement('div');
      this.el.visual.wrapper.classList.add('zoomer-visual');
    
      this.el.visual.inner = document.createElement('div');
      this.el.visual.inner.classList.add('zoomer-visual__inner');
      this.el.visual.wrapper.appendChild(this.el.visual.inner);
    
      this.el.visual.image = document.createElement('img');
      this.el.visual.image.setAttribute('draggable', false);
      this.el.visual.inner.appendChild(this.el.visual.image);
    
      if (wrapperEl) {
        wrapperEl.appendChild(this.el.visual.wrapper);
      }
    };
    
    ZoomerOverlayer.prototype._generateThumbs = function(wrapperEl) {
      if (!this.el || this.settings.images.length <= 1) {
        return;
      }
    
      this.el.thumbs = {};
    
      this.el.thumbs.wrapper = document.createElement('div');
      this.el.thumbs.wrapper.classList.add('zoomer-thumbs');
      this.el.thumbs.inner = document.createElement('div');
      this.el.thumbs.inner.classList.add('zoomer-thumbs__inner');
      this.el.thumbs.wrapper.appendChild(this.el.thumbs.inner);
    
      this.el.thumbs.sliderList = document.createElement('ul');
    
      this.el.navLinks = [];
      this.settings.images.forEach((image, index) => {
        const img = document.createElement('img');
        img.src = image.thumb;
        img.alt = '';
    
        const link = document.createElement('button');
        link.classList.add('zoomer-thumbs__link');
        link.addEventListener('click', () => this.show(1 + index));
        link.appendChild(img);
        this.el.navLinks.push(link);
    
        const li = document.createElement('li');
        li.appendChild(link);
    
        this.el.thumbs.sliderList.appendChild(li);
      });
    
      this.el.thumbs.slider = document.createElement('div');
      this.el.thumbs.slider.classList.add('zoomer-thumbs__slider');
      this.el.thumbs.slider.appendChild(this.el.thumbs.sliderList);
      this.el.thumbs.inner.appendChild(this.el.thumbs.slider);
    
      if (wrapperEl) {
        wrapperEl.appendChild(this.el.thumbs.wrapper);
      }
    };
    
    ZoomerOverlayer.prototype.show = function(number = 1) {
      if (!this.el.wrapper) {
        return;
      }
    
      document.documentElement.classList.add(this.settings.blockScrollClass);
    
      this.resetMoveTo();
      this.scaler.scaleTo(this.settings.startZoomPercentage);
      this.el.wrapper.classList.add('zoomer--visible');
      this.activeVisual = number;
    
      this.updateVisual(number);
      this.activateThumb(number);
    };
    
    ZoomerOverlayer.prototype.hide = function() {
      if (!this.el.wrapper) {
        return;
      }
    
      this.el.wrapper.classList.remove('zoomer--visible');
      this.clearVisual();
      this.activateThumb(false);
    
      document.documentElement.classList.remove(this.settings.blockScrollClass);
    };
    
    ZoomerOverlayer.prototype.clearVisual = function() {
      if (!this.el.visual || !this.el.visual.inner) {
        return;
      }
    
      this.el.visual.wrapper.classList.remove('zoomer-visual--visible');
      this.el.visual.image.setAttribute('src', '');
      this.el.visual.image.setAttribute('alt', '');
    };
    
    ZoomerOverlayer.prototype.updateVisual = function(number = 1) {
      const index = number - 1;
    
      if (!this.settings.images || !this.settings.images[index]) {
        throw new Error(`Zoomer: failed to add visual (number: ${number})`);
      }
    
      this.el.visual.image.setAttribute('src', this.settings.images[index].large);
      this.el.visual.image.setAttribute('alt', this.settings.images[index].title ?? '');
      this.el.visual.wrapper.classList.add('zoomer-visual--visible');
    
      if (this.el.download) {
        this.el.download.href = `${this.settings.images[index].large}?force=1`;
      }
    };
    
    ZoomerOverlayer.prototype.activateThumb = function(number = 1) {
      if (!this.el.navLinks) {
        return;
      }
    
      this.el.navLinks.forEach((link, linkIndex) => {
        link.classList.toggle('zoomer-thumbs__link--active', linkIndex === number - 1);
      });
    };
    
    ZoomerOverlayer.prototype.scaleTo = function(percentage) {
      let minScale = this.settings.minScale;
      let maxScale = this.settings.maxScale;
      let scaleCalc = (maxScale - minScale) / 100;
    
      const scale = minScale + (scaleCalc * percentage);
      this.el.wrapper.style.setProperty("--zoomer-scale", scale);
    };
    
    ZoomerOverlayer.prototype.resetMoveTo = function() {
      this._xPerc = this.settings.scaleWithBrowser ? 0 : -50;
      this._yPerc = this.settings.scaleWithBrowser ? 0 : -50;
      this.moveTo(this._xPerc, this._yPerc);
    };
    
    ZoomerOverlayer.prototype.moveTo = function(xPerc, yPerc) {
      if ([xPerc, yPerc].includes(NaN)) {
        xPerc = this.settings.scaleWithBrowser ? 0 : -50;
        yPerc = this.settings.scaleWithBrowser ? 0 : -50;
      }
    
      xPerc = parseFloat(xPerc);
      yPerc = parseFloat(yPerc);
      // xPerc = xPerc < -100 ? -100 : (xPerc > 0 ? 0 : xPerc);
      // yPerc = yPerc < -100 ? -100 : (yPerc > 0 ? 0 : yPerc);
    
      this.el.wrapper.style.setProperty("--zoomer-xperc", `${xPerc}%`);
      this.el.wrapper.style.setProperty("--zoomer-yperc", `${yPerc}%`);
    };
    
    ZoomerOverlayer.prototype._startMove = function(e) {
      this.isScaling = e.touches && e.touches.length === 2;
    
      if (this.isScaling) {
        this._startDist = this._getTouchDistance(e);
        this._startScale = this.scaler.getValue();
        this._screenW = this.el.visual.wrapper.clientWidth;
        this._startPerc = this._startDist * 100 / this._screenW;
        return;
      }
    
      if (!this.isScaling) {
        this.isMoving = true;
    
        const offsetX = e.touches && e.touches[0] ? e.touches[0].clientX : e.offsetX;
        const offsetY = e.touches && e.touches[0] ? e.touches[0].clientY : e.offsetY;
    
        this._moveBoxRect = this.el.visual.inner.getBoundingClientRect();
        this._movingStartXPerc = ((offsetX / (this._moveBoxRect.width / 100)));
        this._movingStartYPerc = ((offsetY / (this._moveBoxRect.height / 100)));
    
        const xPerc = parseFloat(this.el.wrapper.style.getPropertyValue('--zoomer-xperc'));
        const yPerc = parseFloat(this.el.wrapper.style.getPropertyValue('--zoomer-yperc'));
    
        this._xPerc = xPerc; // this._xPerc = xPerc >= -100 && xPerc <= 0 ? xPerc : -50;
        this._yPerc = yPerc; // this._yPerc = yPerc >= -100 && yPerc <= 0 ? yPerc : -50;
      }
    };
    
    ZoomerOverlayer.prototype._isMoving = function(e) {
      if (this.isScaling) {
        const dist = this._getTouchDistance(e);
        const pinchPerc = dist * 100 / this._screenW;
        const pinchDiff = pinchPerc - this._startPerc;
        const scaleToPerc = this._startScale + pinchDiff;
    
        this.scaler.scaleTo(scaleToPerc);
        return;
      }
    
      if (!this.isMoving || !this._moveBoxRect) {
        return;
      }
    
      // if (e && e.stopPropagation) {
      //   e.stopPropagation();
      // }
    
      const offsetX = e.touches && e.touches[0] ? e.touches[0].clientX : e.offsetX;
      const offsetY = e.touches && e.touches[0] ? e.touches[0].clientY : e.offsetY;
    
      const percentageX = ((offsetX / (this._moveBoxRect.width / 100)));
      const percentageY = ((offsetY / (this._moveBoxRect.height / 100)));
    
      this._movingCurrentXPerc = this._movingStartXPerc - percentageX;
      this._movingCurrentYPerc = this._movingStartYPerc - percentageY;
    
      this.moveTo(this._xPerc - this._movingCurrentXPerc, this._yPerc - this._movingCurrentYPerc);
    };
    
    ZoomerOverlayer.prototype._endMove = function() {
      this.isMoving = false;
      this.isScaling = false;
    };
    
    ZoomerOverlayer.prototype._getTouchDistance = function(e) {
      if (!(e.touches && e.touches.length === 2)) {
        return 0;
      }
    
      return Math.hypot(
        e.touches[0].pageX - e.touches[1].pageX,
        e.touches[0].pageY - e.touches[1].pageY
      );
    }
    
    // window.ZoomerOverlayer = ZoomerOverlayer;
    // export default ZoomerOverlayer;
    
  • URL: /components/raw/zoomer/ZoomerOverlayer.js
  • Filesystem Path: ../src/04_organisms/zoomer/ZoomerOverlayer.js
  • Size: 11.7 KB
  • Content:
    // ZoomerScaler is external JS file that is required by ZoomerOverlayer.js
    
    const ZoomerScaler = function(settings = {}) {
      this.defaultSettings = {
        startValue: 50,
        clickSteps: 25,
        scaleOutIcon: '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none" viewBox="0 0 16 16"><path fill="currentColor" fill-rule="evenodd" d="M1.75 8a.75.75 0 0 1 .75-.75h11a.75.75 0 0 1 0 1.5h-11A.75.75 0 0 1 1.75 8" clip-rule="evenodd"/></svg>',
        scaleInIcon: '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none" viewBox="0 0 16 16"><path fill="currentColor" fill-rule="evenodd" d="M8 1.75a.75.75 0 0 1 .75.75v4.75h4.75a.75.75 0 0 1 0 1.5H8.75v4.75a.75.75 0 0 1-1.5 0V8.75H2.5a.75.75 0 0 1 0-1.5h4.75V2.5A.75.75 0 0 1 8 1.75" clip-rule="evenodd"/></svg>',
      };
    
      this.settings = {
        ...this.defaultSettings,
        ...settings,
      };
    
      this.el = {};
      this.init();
    };
    
    ZoomerScaler.prototype.init = function() {
      this.validateSettings();
      this.generateElement();
    };
    
    ZoomerScaler.prototype.validateSettings = function() {
      this.settings.startValue = parseInt(this.settings.startValue);
      this.settings.startValue = (this.settings.startValue < 0 || this.settings.startValue > 100) ? this.defaultSettings.startValue : this.settings.startValue;
    
      this.settings.clickSteps = parseInt(this.settings.clickSteps);
      this.settings.clickSteps = (this.settings.clickSteps < .1 || this.settings.clickSteps > 50) ? this.defaultSettings.clickSteps : this.settings.clickSteps;
    
      if (typeof this.settings.scaleOutIcon !== typeof '') {
        this.settings.scaleOutIcon = '-';
      }
    
      if (typeof this.settings.scaleInIcon !== typeof '') {
        this.settings.scaleInIcon = '+';
      }
    };
    
    ZoomerScaler.prototype.generateElement = function() {
      this.el.range = document.createElement('input');
      this.el.range.type = 'range';
      this.el.range.min = 0;
      this.el.range.max = 100;
      this.el.range.value = this.settings.startValue;
      this.el.range.classList.add('zoomer-scale__range');
      this.el.range.addEventListener('input', () => this.scaleTo(this.el.range.value));
    
      this.el.scaleOutBtn = document.createElement('button');
      this.el.scaleOutBtn.classList.add('zoomer-scale__out');
      this.el.scaleOutBtn.innerHTML = this.settings.scaleOutIcon;
      this.el.scaleOutBtn.addEventListener('click', () => this.scaleOut());
    
      this.el.scaleInBtn = document.createElement('button');
      this.el.scaleInBtn.classList.add('zoomer-scale__out');
      this.el.scaleInBtn.innerHTML = this.settings.scaleInIcon;
      this.el.scaleInBtn.addEventListener('click', () => this.scaleIn());
    
      this.el.wrapper = document.createElement('div');
      this.el.wrapper.classList.add('zoomer-scale');
      this.el.wrapper.appendChild(this.el.scaleOutBtn);
      this.el.wrapper.appendChild(this.el.range);
      this.el.wrapper.appendChild(this.el.scaleInBtn);
    };
    
    ZoomerScaler.prototype.reset = function() {
      this.scaleTo(this.settings.startValue);
    };
    
    ZoomerScaler.prototype.getValue = function() {
      if (!this.el || !this.el.range) {
        return -1;
      }
    
      return parseInt(this.el.range.value);
    };
    
    ZoomerScaler.prototype.scaleOut = function() {
      if (!(this.el && this.el.range)) {
        throw new Error('ZoomerScaler can not scale out');
      }
    
      this.scaleTo(parseInt(this.el.range.value) - this.settings.clickSteps);
    };
    
    ZoomerScaler.prototype.scaleIn = function() {
      if (!(this.el && this.el.range)) {
        throw new Error('ZoomerScaler can not scale in');
      }
    
      this.scaleTo(parseInt(this.el.range.value) + this.settings.clickSteps);
    };
    
    ZoomerScaler.prototype.scaleTo = function(newValue) {
      if (!(this.el && this.el.range)) {
        return;
      }
    
      this.el.range.value = newValue;
    
      if (typeof this.settings.onUpdate === typeof function() {}) {
        this.settings.onUpdate(parseInt(this.el.range.value));
      }
    };
    
    ZoomerScaler.prototype.getElement = function() {
      if (!(this.el && this.el.wrapper)) {
        throw new Error('ZoomerScaler can not get wrapper');
      }
    
      return this.el.wrapper;
    };
    
    // window.ZoomerScaler = ZoomerScaler;
    // export default ZoomerScaler;
    
  • URL: /components/raw/zoomer/ZoomerScaler.js
  • Filesystem Path: ../src/04_organisms/zoomer/ZoomerScaler.js
  • Size: 4 KB
  • Content:
    .zoomer-header {
      background-color: var(--zoomer--border-color, white);
      padding-bottom: var(--zoomer--border-size);
    
      &__inner {
        display: flex;
        justify-content: space-between;
        align-items: center;
        gap: var(--gap--4);
    
        margin: 0 auto;
        padding: var(--gap--2) 0;
        max-width: var(--zoomer--header-width);
    
        @media (min-width: 768px) {
          justify-content: flex-start;
          gap: var(--gap--20);
        }
    
        & > * {
          flex: 0 1 auto;
        }
      }
    
      &__download,
      &__close {
        color: var(--color--action);
        transition: opacity var(--zoomer--transition-speed) var(--zoomer--transition-ease);
        cursor: pointer;
    
        &:hover {
          opacity: .5;
        }
      }
    
      &__close {
        @media (min-width: 768px) {
          margin-left: auto;
        }
      }
    
      svg {
        display: block;
        width: var(--zoomer--icon-size);
        height: var(--zoomer--icon-size);
      }
    }
    
  • URL: /components/raw/zoomer/zoomer-header.scss
  • Filesystem Path: ../src/04_organisms/zoomer/zoomer-header.scss
  • Size: 884 Bytes
  • Content:
    @mixin zoomerScaleRangeStyle {
      width: var(--zoomer--scale-size);
      height: var(--zoomer--scale-size);
    
      border-radius: 50%;
      background: var(--color--action);
    
      box-shadow: none;
      border: none;
      pointer-events: auto;
      appearance: none;
    }
    
    .zoomer-scale {
      display: flex;
      justify-content: center;
      align-items: center;
      gap: var(--gap--4);
    
      height: var(--zoomer--scale-size);
    
      &__range,
      input[type=range] {
        appearance: none;
    
        display: block;
        width: var(--zoomer--scale-width, 150px);
        height: 4px;
    
        margin: 0;
        padding: 0;
    
        background-color: #dfdfdf;
    
        border: none;
        border-radius: 0;
    
        accent-color: var(--color--action);
        cursor: pointer;
    
        // ⚠️ dont use comma's
        &::-webkit-slider-thumb { @include zoomerScaleRangeStyle(); }
        &::-moz-range-thumb { @include zoomerScaleRangeStyle(); }
        &::-ms-thumb { @include zoomerScaleRangeStyle(); }
      }
    
      &__in,
      &__out {
        color: var(--color--neutrals-10);
        transition: color var(--zoomer--transition-speed) var(--zoomer--transition-ease);
        cursor: pointer;
    
        &:hover {
          color: var(--color--neutrals-5);
        }
      }
    }
    
  • URL: /components/raw/zoomer/zoomer-scale.scss
  • Filesystem Path: ../src/04_organisms/zoomer/zoomer-scale.scss
  • Size: 1.1 KB
  • Content:
    .zoomer-thumbs {
      position: absolute;
      right: var(--gap--2);
      bottom: var(--gap--2);
      left: var(--gap--2);
      z-index: 1;
    
      &__inner {
        position: relative;
        max-width: var(--zoomer--thumbs-width);
        margin: 0 auto;
    
        background-color: var(--zoomer--bg-color);
        border: 1px solid var(--color--neutrals-2);
      }
    
      &__slider {
        display: block;
        width: 100%;
        overflow-x: auto;
    
        ul {
          display: flex;
          justify-content: flex-start;
          align-items: center;
          gap: var(--gap--4);
    
          margin: 0 !important;
          padding: 0;
    
          list-style: none;
    
          li {
            flex: 0 0 auto; // 20%;
          }
        }
      }
    
      &__link {
        display: flex;
        justify-content: center;
        align-items: center;
    
        padding: var(--gap--4);
    
        border-bottom: 5px solid transparent;
        transition: border-bottom var(--zoomer--transition-speed) var(--zoomer--transition-ease);
    
        img {
          width: 100px;
          transform: translateY(5px);
          transition: transform var(--zoomer--transition-speed) var(--zoomer--transition-ease);
        }
    
        &:hover,
        &.zoomer-thumbs__link--active {
          border-bottom: 5px solid var(--color--theme, #000);
    
          img {
            transform: translateY(0);
          }
        }
    
        &.zoomer-thumbs__link--active {
          cursor: default;
        }
      }
    }
    
  • URL: /components/raw/zoomer/zoomer-thumbs.scss
  • Filesystem Path: ../src/04_organisms/zoomer/zoomer-thumbs.scss
  • Size: 1.3 KB
  • Content:
    .zoomer-visual {
      position: relative;
    
      display: block;
      background-color: var(--zoomer--bg-color, white);
      overflow: hidden;
    
      opacity: 0;
      transition: opacity var(--zoomer--transition-speed) var(--zoomer--transition-ease);
    
      &--visible {
        opacity: 1;
      }
    
      &__inner {
        display: flex;
        justify-content: center;
        align-items: center;
    
        width: 100%;
        height: 100%;
    
        cursor: move;
    
        * {
          pointer-events: none;
        }
      }
    
      img {
        flex: 0 0 100%;
    
        display: block;
        width: auto;
        height: auto;
        max-width: 100%;
        max-height: 100%;
        object-fit: contain;
    
        margin: 0;
        user-select: none;
    
        transform-origin: 50% 50%;
        transform: translate(var(--zoomer-xperc, 0), var(--zoomer-yperc, 0)) scale(var(--zoomer-scale, .5));
    
        .zoomer--fullscale & {
          position: absolute;
          top: 50%;
          left: 50%;
          z-index: 1;
    
          max-width: unset;
          max-height: unset;
          object-fit: unset;
    
          transform: translate(var(--zoomer-xperc, -50%), var(--zoomer-yperc, -50%)) scale(var(--zoomer-scale, .5));
        }
      }
    }
    
  • URL: /components/raw/zoomer/zoomer-visual.scss
  • Filesystem Path: ../src/04_organisms/zoomer/zoomer-visual.scss
  • Size: 1.1 KB
  • Content:
    :root {
      --zoomer--bg-color: var(--color--neutrals-0);
    
      --zoomer--border-size: var(--gap--4);
      --zoomer--border-color: #F9F9F9;
    
      --zoomer--header-width: var(--section--8); // before: 1000px
      --zoomer--thumbs-width: var(--section--8); // before: 1200px
    
      --zoomer--icon-size: 20px;
      --zoomer--scale-size: 18px;
      --zoomer--scale-width: min(180px, 20vw);
    
      --zoomer--transition-ease: ease-out;
      --zoomer--transition-speed: 150ms;
    }
    
    html.zoomeractive,
    html.zoomeractive body {
      overflow: hidden !important;
    }
    
    .zoomer {
      display: none;
      width: 100vw;
      height: 100dvh;
    
      margin: 0;
      padding: 0;
    
      background-color: var(--zoomer--bg-color, white);
      border: var(--zoomer--border-size) solid var(--zoomer--border-color, white);
      overflow: hidden;
      touch-action: pan-x pan-y;
    
      &--visible {
        position: fixed;
        top: 0;
        right: 0;
        bottom: 0;
        left: 0;
        z-index: 99999;
    
        display: block;
      }
    
      &__inner {
        display: flex;
        justify-content: stretch;
        align-items: stretch;
        flex-direction: column;
    
        height: 100%;
        background: url(https://www.pioneerdj.com/Content/img/loaders/loading_fff.gif) no-repeat 50% 50% / 100px;
    
        & > * {
          flex: 0 1 auto;
        }
    
        .zoomer-header {
          flex: 0 0 auto;
        }
    
        .zoomer-visual {
          flex: 1 1 100%;
        }
      }
    }
    
  • URL: /components/raw/zoomer/zoomer-wrapper.scss
  • Filesystem Path: ../src/04_organisms/zoomer/zoomer-wrapper.scss
  • Size: 1.3 KB

Clean new version