/*
* MojoZoom 0.1.4 - JavaScript Image Zoom
* Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
* Licensed under the MPL License [http://www.nihilogic.dk/licenses/mpl-license.txt]
*/

var MojoZoom = (function() {

    var $ = function(id) { return document.getElementById(id); };
    var dc = function(tag) { return document.createElement(tag); };

    var defaultWidth = 256;
    var defaultHeight = 256;

    function addEvent(element, ev, handler) {
        var doHandler = function(e) {
            return handler(e || window.event);
        }
        if (element.addEventListener) {
            element.addEventListener(ev, doHandler, false);
        } else if (element.attachEvent) {
            element.attachEvent("on" + ev, doHandler);
        }
    }

    function getElementPos(element) {
        var x = element.offsetLeft;
        var y = element.offsetTop;
        var parent = element.offsetParent;
        while (parent) {
            x += parent.offsetLeft;
            y += parent.offsetTop;
            parent = parent.offsetParent;
        }
        return {
            x: x,
            y: y
        }
    }

    function getEventMousePos(element, e) {
        var scrollX = document.body.scrollLeft || document.documentElement.scrollLeft;
        var scrollY = document.body.scrollTop || document.documentElement.scrollTop;

        if (e.currentTarget) {
            var pos = getElementPos(element);
            return {
                x: e.clientX - pos.x + scrollX,
                y: e.clientY - pos.y + scrollY
            }
        }
        return {
            x: e.offsetX,
            y: e.offsetY
        }
    }

    function makeZoomable(img, zoomSrc, zoomImgCtr, zoomWidth, zoomHeight, alwaysShow) {
        // make sure the image is loaded, if not then add an onload event and return
        if (!img.complete && !img.__mojoZoomQueued) {
            addEvent(img, "load", function() {
                img.__mojoZoomQueued = true;
                setTimeout(function() {
                    makeZoomable(img, zoomSrc, zoomImgCtr, zoomWidth, zoomHeight, alwaysShow);
                }, 1);
            });
            return;
        }

        img.__mojoZoomQueued = false;

        // Wrap everything in a timeout.
        // this fixes a problem where, if makeZoomable is called a second time after changing the src,
        // FF would not have figured out the new offsetHeight of the image yet. A small timeout helps though it's rather hackish.
        setTimeout(function() {

            // sorry
            var isIE = !!document.all && !!window.attachEvent && !window.opera;

            var w = img.offsetWidth;
            var h = img.offsetHeight;

            var oldParent = img.parentNode;
            if (oldParent.nodeName != "A") {
                var linkParent = dc("a");
                linkParent.setAttribute("href", zoomSrc);
                oldParent.replaceChild(linkParent, img);
                linkParent.appendChild(img);
            } else {
                var linkParent = oldParent;
            }

            linkParent.style.position = "relative";
            linkParent.style.display = "block";
            linkParent.style.width = w + "px";
            linkParent.style.height = h + "px";

            var imgLeft = img.offsetLeft;
            var imgTop = img.offsetTop;

            var zoom = dc("div");
            zoom.className = "mojozoom_marker";

            var zoomImg = dc("img");
            zoomImg.className = "mojozoom_img";

            zoomImg.style.position = "absolute";
            zoomImg.style.left = "-9999px";
            zoomImg.style.top = "-9999px";

            document.body.appendChild(zoomImg);

            var parent = img.parentNode;

            var ctr = dc("div");
            with (ctr.style) {
                position = "absolute";
                left = imgLeft + "px";
                top = imgTop + "px";
                width = w + "px";
                height = h + "px";
                overflow = "hidden";
                display = "none";
            }

            ctr.appendChild(zoom);
            parent.appendChild(ctr);

            var zoomInput = parent;

            // clear old overlay
            if (img.__mojoZoomOverlay)
                parent.removeChild(img.__mojoZoomOverlay);
            img.__mojoZoomOverlay = ctr;

            // clear old high-res image
            if (img.__mojoZoomImage && img.__mojoZoomImage.parentNode)
                img.__mojoZoomImage.parentNode.removeChild(img.__mojoZoomImage);
            img.__mojoZoomImage = zoomImg;

            var useDefaultCtr = false;
            if (!zoomImgCtr) {
                zoomImgCtr = dc("div");
                zoomImgCtr.className = "mojozoom_imgctr";

                var imgPos = getElementPos(img);
                zoomImgCtr.style.left = w + imgPos.x + "px";
                zoomImgCtr.style.top = imgPos.y + "px";

                zoomImgCtr.style.width = (zoomWidth ? zoomWidth : defaultWidth) + "px";
                zoomImgCtr.style.height = (zoomHeight ? zoomHeight : defaultHeight) + "px";

                document.body.appendChild(zoomImgCtr);
                useDefaultCtr = true;
            }
            zoomImgCtr.style.overflow = "hidden";

            if (!alwaysShow) {
                zoomImgCtr.style.visibility = "hidden";
            }

            addEvent(zoomImg, "load", function() {

                // bail out if img has been removed from dom
                if (!zoomImg.parentNode) return;

                var zoomWidth = zoomImg.offsetWidth;
                var zoomHeight = zoomImg.offsetHeight;

                var ctrWidth = zoomImgCtr.offsetWidth;
                var ctrHeight = zoomImgCtr.offsetHeight;

                var ratioW = zoomWidth / w;
                var ratioH = zoomHeight / h;

                var markerWidth = Math.round(ctrWidth / ratioW);
                var markerHeight = Math.round(ctrHeight / ratioH);

                document.body.removeChild(zoomImg);
                zoomImgCtr.appendChild(zoomImg);




                var zoomFill = dc("div");
                zoomFill.className = "mojozoom_fill";
                zoom.appendChild(zoomFill);

                var zoomBorder = dc("div");
                zoomBorder.className = "mojozoom_border";
                zoom.appendChild(zoomBorder);

                zoom.style.width = markerWidth + "px";
                zoom.style.height = markerHeight + "px";


                if (alwaysShow) {
                    zoom.style.left = "0px";
                    zoom.style.top = "0px";

                    zoomImg.style.left = "0px";
                    zoomImg.style.top = "0px";
                }

                var isInImage = false;

                if (!alwaysShow) {
                    addEvent(zoomInput, "mouseout",
					function(e) {
					    var target = e.target || e.srcElement;
					    if (!target) return;
					    if (target.nodeName != "DIV") return;
					    var relTarget = e.relatedTarget || e.toElement;
					    if (!relTarget) return;
					    while (relTarget != target && relTarget.nodeName != "BODY" && relTarget.parentNode) {
					        relTarget = relTarget.parentNode;
					    }
					    if (relTarget != target) {
					        isInImage = false;
					        ctr.style.display = "none";
					        zoomImgCtr.style.visibility = "hidden";
					    }
					}
				);
                    // a bit of a hack, mouseout is sometimes not caught if moving mouse really fast
                    addEvent(document.body, "mouseover",
					function(e) {
					    if (isInImage && !(e.toElement == zoomBorder || e.target == zoomBorder)) {
					        ctr.style.display = "none";
					        zoomImgCtr.style.visibility = "hidden";
					        isInImage = false;
					    }
					}
				);
                }

                addEvent(zoomInput, "mousemove",
				function(e) {
				    isInImage = true;

				    var imgPos = getElementPos(img);

				    if (useDefaultCtr) {
				        zoomImgCtr.style.left = w + imgPos.x + "px";
				        zoomImgCtr.style.top = imgPos.y + "px";
				    }
				    ctr.style.display = "block";
				    zoomImgCtr.style.visibility = "visible";

				    var pos = getEventMousePos(zoomInput, e);
				    if (e.srcElement && isIE) {
				        if (e.srcElement == zoom) return;
				        if (e.srcElement != zoomInput) {
				            var zoomImgPos = getElementPos(e.srcElement);
				            pos.x -= (imgPos.x - zoomImgPos.x);
				            pos.y -= (imgPos.y - zoomImgPos.y);
				        }
				    }
				    var x = markerWidth / 2;
				    var y = markerHeight / 2;

				    if (!isIE) {
				        pos.x -= imgLeft;
				        pos.y -= imgTop;
				    }

				    if (pos.x < x) pos.x = x;
				    if (pos.x > w - x) pos.x = w - x;
				    if (pos.y < y) pos.y = y;
				    if (pos.y > h - y) pos.y = h - y;

				    var left = ((pos.x - x) | 0);
				    var top = ((pos.y - y) | 0);

				    zoom.style.left = left + "px";
				    zoom.style.top = top + "px";

				    zoomImg.style.left = -((pos.x * ratioW - ctrWidth / 2) | 0) + "px";
				    zoomImg.style.top = -((pos.y * ratioH - ctrHeight / 2) | 0) + "px";
				}
			);
            });

            // I've no idea. Simply setting the src will make IE screw it self into a 100% CPU fest. In a timeout, it's ok.
            setTimeout(function() {
                zoomImg.src = zoomSrc;
            }, 1);

        }, 1);
    }

    function init() {
        var images = document.getElementsByTagName("img");
        for (var i = 0; i < images.length; i++) {
            var img = images[i];
            var zoomSrc = img.getAttribute("data-zoomsrc");
            if (zoomSrc) {
                makeZoomable(img, zoomSrc, document.getElementById(img.getAttribute("id") + "_zoom"), null, null, img.getAttribute("data-zoomalwaysshow") == "true");
            }
        }
    }

    return {
        addEvent: addEvent,
        init: init,
        makeZoomable: makeZoomable
    };

})();

MojoZoom.addEvent(window, "load", MojoZoom.init);

