;(function ($){
  
  /**
   * jQuery plugin that allows an image to "zoom" in place by wrapping
   * it in a clipping div and animating its size and position on clicking
   * a control. Pass in two arrays specifying the inital (zoomed out)
   * width and height and final (zoomed in) width and height:
   *
   *   $("img.zoomable").zoomable([100, 100], [400, 400]);
   *
   * @param array
   * @param array
   * @return jQuery
   */
  $.fn.zoomable = function (di, df){
    return $(this).each(function (){
      
      var $self = $(this);
      
      // it seems like we should be able to get these dimensions from
      // the DOM, but Safari tends to erroneously report image sizes
      // before the DOM is really REALLY loaded
      var wi = di[0],
          hi = di[1],
          wf = df[0],
          hf = df[1],
          xf = Math.floor((wi - wf) / 2),
          yf = Math.floor((hi - hf) / 2);
      
      /* Animates the zooming of $el to a given width and position. */
      function zoom($el, width, left, top){
        $el.animate({
          width: width + "px",
          left:  left + "px",
          top:   top + "px"
        }, 300);
      }

      /* Zooms a given image to its maximum size. */
      function zoomIn(){
        var $img = $(this).siblings("img:first");
        
        // zoom, enable dragging, and change the icon
        zoom($img, wf, xf, yf);
        $img.draggable('enable');
        $(this).children("img").attr({ src: "/images/mag-minus.png", title: "Zoom out" });
      }

      function zoomOut(){
        var $img = $(this).siblings("img:first");

        // zoom, disable dragging, and change the icon
        zoom($img, wi, 0, 0);
        $img.draggable('disable');
        $(this).children("img").attr({ src: "/images/mag-plus.png", title: "Zoom out" });
      }

      // provides clipping of the zoomed image
      var $clip = $("<div>").addClass("clip").css({ width: wi, height: hi });

      // container for the zoom icon
      var $zoomer = $("<div>")
        .addClass("zoomer")
        .toggle(zoomIn, zoomOut)
        .html($("<img>").attr({ src: "/images/mag-plus.png", title: "Zoom in" }));

      $(this)
        .draggable({
          scroll: false,
          drag: function (ev, ui){
            var $clip = $(ui.helper).closest(".clip");
            var max = { x: 0, y: 0 };
            var min = { x: $clip.width() - wf, y: $clip.height() - hf };

            // bounds checking
            ui.position.left = Math.max(Math.min(ui.position.left, max.x), min.x);
            ui.position.top  = Math.max(Math.min(ui.position.top, max.y), min.y);
          }
        })
        .draggable('disable')
        .wrap($clip)
        .before($zoomer);
    });
  };
})(jQuery);
