<script type="text/javascript" charset="utf-8">
  /**
   * A reusable HTML Import to enable zooming on images.
   *
   * To use, simply include this HTML Import and add the class 'zoom' to any
   * images you want zoomable.
   *
   *     <link rel='import' type='text/html' href='/res/imp/zoom.html'>
   *
   *     <img src="http://..." class="zoom"/>
   *
   * Any number of images on a page can be zoomable.
   *
   * If you want to display the rgb colors of the pixel at the center of the
   * zoom then add an id of 'zoomHex' to any element that supports
   * textContent, such as a div, p, span, etc.
   *
   *     <p id=zoomHex></p>
   *
   * Note that HTML Imports need to be polyfilled in the near term.
   */
  (function () {
    function onLoad() {
      var PIXELS       = 20; // The number of pixels in width and height in a zoom.
      var clientX      = 0;
      var clientY      = 0;
      var lastClientX  = 0;
      var lastClientY  = 0;
      var ctx          = null; // The 2D canvas context of the zoom.
      var currentImage = null; // The img node we are zooming for, otherwise null.
      var hex          = document.getElementById('zoomHex');
      var canvasCopy   = null;
      function zoomMove(e) {
        clientX = e.clientX;
        clientY = e.clientY;
      }
      function zoomMouseDown(e) {
        e.preventDefault();
        // Only do zooming on the primary mouse button.
        if (e.button != 0) {
          return
        }
        currentImage = e.target;
        clientX = e.clientX;
        clientY = e.clientY;
        lastClientX = clientX-1;
        lastClientY = clientY-1;
        document.body.style.cursor = 'crosshair';
        canvas = document.createElement('canvas');
        canvas.width = 1024;
        canvas.height = 1024;
        canvas.classList.add('zoomCanvas');
        ctx = canvas.getContext('2d');
        ctx.imageSmoothingEnabled = false;
        this.parentNode.insertBefore(canvas, this);
        // Copy the image over to a canvas so we can read RGBA values for each point.
        if (hex) {
          canvasCopy = document.createElement('canvas');
          canvasCopy.width = currentImage.width;
          canvasCopy.height = currentImage.height;
          canvasCopy.id = 'zoomCopy';
          canvasCopy.getContext('2d').drawImage(currentImage, 0, 0, currentImage.width, currentImage.height);
          this.parentNode.insertBefore(canvasCopy, this);
        }
        document.body.addEventListener('pointermove',   zoomMove,     true);
        document.body.addEventListener('pointerup',     zoomFinished);
        document.body.addEventListener('pointerleave',  zoomFinished);
        // Kick off the drawing.
        setTimeout(drawZoom, 1);
      }
      function hexify(i) {
        var s = i.toString(16).toUpperCase();
        // Pad out to two hex digits if necessary.
        if (s.length < 2) {
          s = '0' + s;
        }
        return s;
      }
      function drawZoom() {
        if (currentImage) {
          // Only draw if the mouse has moved from the last time we drew.
          if (lastClientX != clientX || lastClientY != clientY) {
            ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
            var x = clientX - currentImage.x;
            var y = clientY - currentImage.y;
            var dx = Math.floor(ctx.canvas.width/PIXELS);
            var dy = Math.floor(ctx.canvas.height/PIXELS);
            ctx.lineWidth = 1;
            ctx.strokeStyle = '#000';
            // Draw out each pixel as a rect on the target canvas, as this works around
            // FireFox doing a blur as it copies from one canvas to another.
            var colors = canvasCopy.getContext('2d').getImageData(x, y, PIXELS, PIXELS).data;
            for (var i=0; i<PIXELS; i++) {
              for (var j=0; j<PIXELS; j++) {
                var offset = (j*PIXELS+i)*4; // Offset into the colors array.
                ctx.fillStyle = 'rgba(' + colors[offset] + ', ' + colors[offset+1] + ', ' + colors[offset+2] + ', ' + colors[offset+3]/255.0 + ')';
                ctx.fillRect(i*dx, j*dy, dx-1, dy-1);
                // Box and label one selected pixel with its rgba values.
                if (hex && i==PIXELS/2 && j == PIXELS/2) {
                  ctx.strokeRect(i*dx, j*dy, dx-1, dy-1);
                  hex.textContent = 'rgba('
                    + colors[offset] + ', '
                    + colors[offset+1] + ', '
                    + colors[offset+2] + ', '
                    + colors[offset+3] + ') '
                    + hexify(colors[offset])
                    + hexify(colors[offset+1])
                    + hexify(colors[offset+2])
                    + hexify(colors[offset+3]);
                }
              }
            }
            lastClientX = clientX;
            lastClientY = clientY;
          }
          setTimeout(drawZoom, 1000/30);
        }
      }
      function zoomFinished() {
        currentImage = null;
        if (hex) {
          hex.textContent = '';
        }
        document.body.style.cursor = 'default';
        ctx.canvas.parentNode.removeChild(ctx.canvas);
        canvasCopy.parentNode.removeChild(canvasCopy);
        document.body.removeEventListener('pointermove',  zoomMove,     true);
        document.body.removeEventListener('pointerup',    zoomFinished);
        document.body.removeEventListener('pointerleave', zoomFinished);
      }

      var zoomables = document.body.querySelectorAll('.zoom');
      for (var i=0; i<zoomables.length; i++) {
        zoomables[i].addEventListener('pointerdown', zoomMouseDown);
      }
    }

    // If loaded via HTML Imports then DOMContentLoaded will be long done.
    if (document.readyState != "loading") {
      onLoad();
    } else {
      this.addEventListener('DOMContentLoaded', onLoad);
    }
  })();
</script>

<style type="text/css" media="screen">
  .zoom {
    cursor: crosshair;
  }

  .zoomCanvas {
    position: absolute;
    width: vmin;
    height: vmin;
    top: 3em;
    right: 1em;
    z-index: -1;
  }

  #zoomCopy {
    display: none;
  }

  #zoomHex {
    text-shadow: 1px 1px #eee;
  }
</style>

