﻿// -----------------------------------------------------------------------
// eros@recoding.it
// magnifier 0.5
//
// 15/07/2009 - Major corrections, added parameters
// 13/07/2009 - Initial sketch
//
// requires jQuery 1.3.x
//------------------------------------------------------------------------
(function($) {
    $.fn.magnifier = function(options) {
        var opt = $.extend({}, $.fn.magnifier.defaults, options);
        if (options && options.styleNavigator) { opt.styleNavigator = $.extend({}, $.fn.magnifier.defaults.styleNavigator, options.styleNavigator); }
        if (options && options.styleMiniature) { opt.styleMiniature = $.extend({}, $.fn.magnifier.defaults.styleMiniature, options.styleMiniature); }
        
        if (!/(^x[0-9]+$)|(^[0-9]+px$)/.test(opt.fullSizeX)) 
        {
            opt.fullSizeX = $.fn.magnifier.defaults.fullSizeX;
        }
        
        if (!/(^x[0-9]+$)|(^[0-9]+px$)/.test(opt.fullSizeY)) 
        {
            opt.fullSizeY = $.fn.magnifier.defaults.fullSizeY;
        }
    
        if (!/top-left|top-right|bottom-left|bottom-right/.test(opt.position)) 
        {
            opt.position = "bottom-right";
        }
        
        var manageFullimage = function(fi, $fullC, $minC) {
            // Recorrect width and height
            $fullC.css({
                width: Math.min(fi.width, $fullC.width()),
                height: Math.min(fi.height, $fullC.height())
            }).find("#loading").remove();
        
            var xRatio = fi.width / $minC.width();
            var yRatio = fi.height / $minC.height();
            var zWidth = parseInt((($fullC.width() * $minC.width()) / fi.width), 10);
            var zHeight = parseInt((($fullC.height() * $minC.height()) / fi.height), 10);
            
            $(fi).css({ position: "relative" }).appendTo($fullC);
            
            if ($minC.find("#zoomEye").length == 0) 
            {
                var $zoomEye = $("<div id='zoomEye' />").css({ border: opt.styleNavigator.border,
                                                               width: zWidth + "px", 
                                                               height: zHeight + "px",
                                                               position: "absolute" });
                
                $minC
                .mousemove( function(e) {
                    e.preventDefault();
                    var leftZoomeye = (e.clientX - $(this).offset().left + $(document).scrollLeft()) - (zWidth / 2);
                    var topZoomeye = (e.clientY - $(this).offset().top + $(document).scrollTop()) - (zHeight / 2);
                    
                    if (leftZoomeye < 0) { leftZoomeye = 0; }
                    if (topZoomeye < 0) { topZoomeye = 0; }
                    if ((leftZoomeye + zWidth) > $minC.width()) { leftZoomeye = $minC.width() - zWidth; }
                    if ((topZoomeye + zHeight) > $minC.height()) { topZoomeye = $minC.height() - zHeight; }
                    
                    if ($(this).data("ondrag")) { 
                        var yNew = e.clientY - $(this).data("y");
                        var xNew = e.clientX - $(this).data("x");
                        
                        if (xNew + $(this).width() > $fullC.width()) { xNew = $fullC.width() - $(this).width(); }
                        if (yNew + $(this).height() > $fullC.height()) { yNew = $fullC.height() - $(this).height(); }
                        if (xNew < 0) { xNew = 0; }
                        if (yNew < 0) { yNew = 0; }
                        
                        $(this).css({ top: yNew, left: xNew }); 
                    }
                    else {
                        $zoomEye.css({ top: topZoomeye, left: leftZoomeye });
                        $(fi).css({ top: -(topZoomeye * parseInt(yRatio, 10)), left: -(leftZoomeye * parseInt(xRatio, 10)) });
                    }
                }).mousedown( function(e) {
                    e.preventDefault();
                    $.browser.mozilla ? this.style.cursor = "-moz-grabbing" : this.style.cursor = "all-scroll";
                    $(this).data("ondrag", true).data("x", e.clientX - $minC.position().left).data("y", e.clientY - $minC.position().top);
                }).mouseup( function(e) {
                    e.preventDefault();
                    $.browser.mozilla ? this.style.cursor = "-moz-grab" : this.style.cursor = "default";
                    $(this).data("ondrag", false);
                }).mouseleave( function(e) {
                    e.target = this;
                    e.stopPropagation();
                    e.preventDefault();
                    $.browser.mozilla ? this.style.cursor = "-moz-grab" : this.style.cursor = "default";
                    $(this).data("ondrag", false);
                }).append($zoomEye);
            }
        };
        
        var manageMinimage = function(img) {
            var fi = new Image();
            
            var $minC = $("<div />").css({ overflow: "hidden", 
                                           border: opt.styleMiniature.border,
                                           width: img.width() + "px", height: img.height() + "px",
                                          
										   position: "absolute",
                                           zIndex: 10000 });
                                                      
            switch(opt.position) {
                case "top-left": 
                    $minC.css({ top: 0, left: 0 });
                    break;
                case "top-right": 
                    $minC.css({ top: 0, right: 0 });
                    break;
                case "bottom-right": 
                    $minC.css({ bottom: 0, right: 0 });
                    break;
                case "bottom-left": 
                    $minC.css({ bottom: 0, left: 0 });
                    break;
            }

            var width;                 
            var height;
            
            if (/^x[0-9]+$/.test(opt.fullSizeX)) { width = img.width() * opt.fullSizeX.replace("x", "") + "px"; }
            else { width = opt.fullSizeX; }
            
            if (/^x[0-9]+$/.test(opt.fullSizeY)) { height = img.height() * opt.fullSizeY.replace("x", "") + "px"; }
            else { height = opt.fullSizeY; }
            
            var $fullC = $("<div />").css({ border: "solid 1px #dedede", 
                                            overflow: "hidden", 
                                            width: width, height: height,
                                            position: "relative" }).html("<span id='loading' style='display:block; text-align:center; position: absolute; width:100%;'>" + opt.loadingMessage + "</span>");
            
            $fullC.appendTo( opt.appendTo === "" ? img.parent() : $(opt.appendTo + ":first") );
            $fullC.append($minC);
            $minC.html(img);
            
            fi.src = img.attr("fullsize");
            if (!fi.complete) { $(fi).load( function() { manageFullimage(fi, $fullC, $minC); }); }
            else { manageFullimage(fi, $fullC, $minC); }
        };
        
        this.each( function() {
            if (!$(this)[0].complete) { $(this).load( function() { manageMinimage($(this)); }); }
            else { manageMinimage($(this)); }
        });
    }
    
    $.fn.magnifier.defaults = {
        styleNavigator: { border: "solid 1px #ffffff" },
        styleMiniature: { border: "solid 2px #ababab" },
        appendTo: "",
        position: "bottom-right",
        loadingMessage: "Chargement ...",
        fullSizeX: "x4",
        fullSizeY: "x4"
    }
})(jQuery)
