
        function initImageZoom(_options) {
                var options = $extend({
                        rel: 'imagezoom'
                }, _options || {});
                var elements = $$(document.links).filter(function(el) {
                        if ((el.rel) && (el.rel.indexOf(options.rel) != -1))
                                return true;
                        else
                                return false;
                });
                for (var i = 0; i < elements.length; i++) {
                        var el = elements[i];
                        el.addEvent("click", function() {
                                this.blur();
                                var sEl = this;
                                var imgCap = "";
                                if (this.getElements("img").length > 0)
                                        sEl = this.getElements("img")[0];
                                if ((sEl.alt) && (sEl.alt != ""))
                                        imgCap = sEl.alt;
                                else if (sEl.title)
                                        imgCap = sEl.title;
                                else if (sEl.parentNode.title)
                                        imgCap = sEl.parentNode.title;
                                var _options = $extend({
                                        image: this.href,
                                        caption: imgCap,
                                        startElement: sEl
                                }, options || {});
                                _options.image = this.href;
                                _options.caption = imgCap;
                                var imagezoom = new Imagezoom(_options);
                                imagezoom.preloadImage();
                                imagezoom.show();
                                return false;
                        });
                }
        }

        var Imagezoom = function(_options) {
                var options = $extend({
                        image: true,
                        caption: "",
                        enableCaptions: true,
                        startElement: false,
                        x: 10,
                        y: 10,
                        initWidth: 50,
                        initHeight: 50,
                        draggable: true,
                        loadImage: "img/white.jpg",
                        loadDelay: 100,
                        duration: 750,
                        closeDuration: 500,
                        transition: Fx.Transitions.Cubic.easeOut,
                        startOpacity: 0.0,
                        closeText: 'Close',
                        rel: 'imagezoom',
                        showCaptionBar: false,
                        overlay: true,
                        overlayColor: "#000",
                        overlayOpacity: .75
                }, _options || {});

                var box = document.createElement("div");
                var instance = this;

                /* shadow divs */
                var tl = document.createElement("div");
                tl.className = "s s_tl";
                var tr = document.createElement("div");
                tr.className = "s s_tr";
                var bl = document.createElement("div");
                bl.className = "s s_bl";
                var br = document.createElement("div");
                br.className = "s s_br";
                var top = document.createElement("div");
                top.className = "s s_top";
                var bottom = document.createElement("div");
                bottom.className = "s s_bottom";
                var left = document.createElement("div");
                left.className = "s s_left";
                var right = document.createElement("div");
                right.className = "s s_right";

                this.preloadImage = function() {
                        if (options.image != false) {
                                var img = new Image();
                                img.src = options.image;
                                img.style.visibility = "hidden";
                                img.style.position = "absolute";
                                img.style.top = "-9999999999px";
                                img.setAttribute("id", "imagezoom-" + options.image);
                                $$('body')[0].appendChild(img);
                        }
                }

                this.getImage = function() {
                        if (($('imagezoom-' + options.image)) && ($('imagezoom-' + options.image).width != "0")) {
                                var img = $('imagezoom-' + options.image).clone();
                                img.setAttribute("id", "");
                                img.style.position = "relative";
                                img.style.top = "0px";
                                img.style.visibility = "visible";
                        } else {
                                instance.preloadImage();
                                window.setTimeout(function() {
                                        instance.getImage();
                                }, 50);
                        }
                        return img;
                }

                this.show = function() {
                        if (options.image != false) {
                                box.style.position = "absolute";
                                box.style.overflow = "hidden";
                                box.setAttribute("id", "imagezoom-open-" + options.image);

                                if (options.startElement != false)
                                        options.startElement.blur();

                                var x = options.x;
                                var y = options.y;
                                var boxWidth = options.initWidth;
                                var boxHeight = options.initHeight;
                                if (options.startElement != false) {
                                        x = options.startElement.getPosition().x;
                                        y = options.startElement.getPosition().y;
                                        boxWidth = options.startElement.offsetWidth;
                                        boxHeight = options.startElement.offsetHeight;
                                }
                                box.style.left = x + "px";
                                box.style.top = y + "px";
                                box.style.width = boxWidth + "px";
                                box.style.height = boxHeight + "px";

                                var fx = new Fx.Morph(box);
                                fx.set({opacity: options.startOpacity});

                                box.className = "imagezoom";
                                $$('body')[0].appendChild(box);
                                box.style.cursor = "pointer";
                                box.addEvent("click", function() {
                                        var fx = new Fx.Morph(box, {duration: 200});
                                        fx.start({opacity: 0}).chain(function() {
                                                $$('body')[0].removeChild(box);
                                        });
                                });

                                this.loadImage();
                        }
                }

                this.loadImage = function() {
                        if (box.getElements(".loading").length == 0) {
                                var loading = new Image();
                                loading.src = options.loadImage;
                                loading.className = "loading";
                                box.appendChild(loading);
                        }
                        if ($('imagezoom-' + options.image)) {
                                var el = $('imagezoom-' + options.image);
                                if (el.width != "0") {
                                        var newEl = new Image();
                                        newEl.src = options.image;
                                        window.setTimeout(function() { instance.insertImage(newEl) }, options.loadDelay);
                                } else {
                                        window.setTimeout(function() { instance.loadImage(); }, 50);
                                }
                        } else {
                                instance.preloadImage();
                                window.setTimeout(function() { instance.loadImage(); }, 50);
                        }
                }

                this.insertImage = function(img) {
                        box.removeEvents("click");
                        box.style.cursor = "default";
                        box.style.overflow = "visible";
                        var w = img.width;
                        var h = img.height;
                        img.style.width = w + "px";
                        img.style.height = h + "px";
                        img.className = 'image';
                        var ptop = (window.getSize().y / 2) + window.getScroll().y - (h/2);
                        var pleft = (window.getSize().x / 2) + window.getScroll().x - (w/2);
                        var fx = new Fx.Morph(box, {duration: options.duration, transition: options.transition});
                        fx.start({
                                top: ptop,
                                left: pleft,
                                width: w,
                                height: h,
                                opacity: 1
                        }).chain(function() {
                                if (options.overlay == true) {
                                        if (!$('imagezoom_overlay')) {
                                                var overlay = $(document.createElement("div"));
                                                overlay.setAttribute("id", "imagezoom_overlay");
                                                overlay.style.backgroundColor = options.overlayColor;
                                                overlay.setOpacity(0);
                                                $$('body')[0].appendChild(overlay);
                                        } else {
                                                var overlay = $('imagezoom_overlay');
                                        }
                                        overlay.style.width = window.getScrollSize().x + "px";
                                        overlay.style.height = window.getScrollSize().y + "px";
                                        var overlayfx = new Fx.Morph(overlay, {duration: 600});
                                        overlayfx.start({
                                                opacity: options.overlayOpacity
                                        });
                                }
                                var close = $(document.createElement("div"));
                                close.innerHTML = "<span>" + options.closeText + "</span>";
                                close.className = "close";
                                close.addEvent("click", function() {
                                        instance.close(true);
                                });
                                var loading = box.getElements(".loading");
                                if (loading.length > 0)
                                        box.removeChild(loading[0]);
                                var elements = [close, tl, tr, bl, br, top, bottom, left, right, img];
                                for (var i = 0; i < elements.length; i++) {
                                        var elFx = new Fx.Morph(elements[i], {duration: 600});
                                        elFx.set({opacity: 0});
                                        box.adopt(elements[i]);
                                        elFx.start({opacity: 1});
                                }
                                var caption;
                                if ((options.caption != "") && (options.enableCaptions == true)) {
                                        caption = document.createElement("div");
                                        caption.className = "caption";
                                        caption.innerHTML = "<p>" + options.caption + "</p>";
                                        box.appendChild(caption);
                                }
                                instance.addSetNavigation();
                                if (box.getElements(".caption").length > 0) {
                                        caption = box.getElements(".caption")[0];
                                        var cfx = new Fx.Morph(caption, {duration: 200});
                                        cfx.set({opacity: 0});
                                        if (options.showCaptionBar == true) {
                                                caption.className += " visibleCaption";
                                                var cStartFx = new Fx.Morph(caption, {duration: 600});
                                                cStartFx.start({
                                                        opacity: 1
                                                });
                                        }
                                        box.addEvent("mouseenter", function() {
                                                cfx.start({opacity: 1}).chain(function() { caption.className += " visibleCaption"; });
                                        });
                                        box.addEvent("mouseleave", function() {
                                                cfx.start({opacity: 0}).chain(function() { caption.className = caption.className.replace(/visibleCaption/g, ""); });
                                        });
                                        close.addEvent("mouseenter", function() {
                                                cfx.start({opacity: 0}).chain(function() { caption.className = caption.className.replace(/visibleCaption/g, ""); });
                                        });
                                        box.getElements(".image")[0].addEvent("click", function() {
                                                var action = "show";
                                                if (caption.className.indexOf("visibleCaption") != -1)
                                                        action = "hide";
                                                if (action == "show")
                                                        cfx.start({opacity: 1}).chain(function() { caption.className += " visibleCaption"; });
                                                else
                                                        cfx.start({opacity: 0}).chain(function() { caption.className = caption.className.replace(/visibleCaption/g, ""); });
                                        });
                                }
                                top.style.width = box.offsetWidth + "px";
                                bottom.style.width = box.offsetWidth + "px";
                                left.style.height = box.offsetHeight + "px";
                                right.style.height = box.offsetHeight + "px";
                                if (options.draggable == true)
                                        var move = new Drag.Move(box, {handle: img});
                        });
                }

                this.addSetNavigation = function() {
                        var links = $$(document.links).filter(function(link) {
                                if ((link.rel) && (link.rel.indexOf(options.rel) != -1))
                                        return true;
                                else
                                        return false;
                        });
                        var set = false;
                        for (var i = 0; i < links.length; i++) {
                                if ((links[i].href.indexOf(options.image) != -1) && (links[i].rel) && (links[i].rel.indexOf(options.rel + '[' != -1))) {
                                        var rel = links[i].getAttribute("rel");
                                        set = instance.scanRel("after", options.rel + "[", this.scanRel("before", "]", rel));
                                }
                        }
                        if (set != false) {
                                var prevLink = false;
                                var nextLink = false;
                                var setLinks = new Array();
                                for (i = 0; i < links.length; i++) {
                                        if (links[i].rel.indexOf(options.rel + "[" + set + "]") != -1) {
                                                setLinks[setLinks.length] = links[i];
                                        }
                                }
                                for (i = 0; i < setLinks.length; i++) {
                                        var link = setLinks[i];
                                        if ((link.href.indexOf(options.image) != -1) && (link.rel) && (link.rel.indexOf(options.rel != -1))) {
                                                if (i != 0)
                                                        prevLink = setLinks[i - 1];
                                                if (i != setLinks.length - 1)
                                                        nextLink = setLinks[i + 1];
                                        }
                                }
                                if ((prevLink != false) || (nextLink != false)) {
                                        if (box.getElements(".caption").length == 0) {
                                                var caption = document.createElement("div");
                                                caption.className = "caption";
                                                box.appendChild(caption);
                                        } else {
                                                var caption = box.getElements(".caption")[0];
                                        }
                                }
                                if (prevLink != false) {
                                        var previousButton = $(document.createElement("div"));
                                        previousButton.className = "previous";
                                        var prevCap = '';
                                        if (prevLink.title)
                                                prevCap = prevLink.title;
                                        var prevEl = prevLink;
                                        if (prevLink.getElements("img").length > 0)
                                                prevEl = prevLink.getElements("img")[0];
                                        previousButton.addEvent("click", function() {
                                                var newOptions = $unlink(options);
                                                var imagezoomPrev = new Imagezoom($extend(newOptions, {
                                                        image: prevLink.href,
                                                        caption: prevCap,
                                                        rel: options.rel,
                                                        startElement: prevEl,
                                                        showCaptionBar: true
                                                }));
                                                instance.close();
                                                imagezoomPrev.show();
                                        });
                                        caption.appendChild(previousButton);
                                }
                                if (nextLink != false) {
                                        var nextButton = $(document.createElement("div"));
                                        nextButton.className = "next";
                                        var nextCap = '';
                                        if (nextLink.title)
                                                nextCap = nextLink.title;
                                        var nextEl = nextLink;
                                        if (nextLink.getElements("img").length > 0)
                                                nextEl = nextLink.getElements("img")[0];
                                        nextButton.addEvent("click", function() {
                                                var newOptions = $unlink(options);
                                                var imagezoomNext = new Imagezoom($extend(newOptions, {
                                                        image: nextLink.href,
                                                        caption: nextCap,
                                                        rel: options.rel,
                                                        startElement: nextEl,
                                                        showCaptionBar: true
                                                }));
                                                instance.close();
                                                imagezoomNext.show();
                                        });
                                        caption.appendChild(nextButton);
                                }
                        }
                }

                this.scanRel = function(where, needle, string) {
                        var newstring = '';
                        if (where == "after") {
                                var startpos = string.indexOf(needle) + needle.length;
                                var endpos = string.length;
                        } else if (where == "before") {
                                var startpos = 0;
                                var endpos = string.indexOf(needle);
                        }
                        for (var i = startpos; i < endpos; i++) {
                                newstring += string.charAt(i);
                        }
                        return newstring;
                }

                this.close = function(hideOverlay) {
                        var img = box.getElements(".image")[0];
                        box.removeChild(img);
                        var close = box.getElements(".close")[0];
                        box.removeChild(close);
                        var caption = box.getElements(".caption");
                        if (caption.length > 0)
                                box.removeChild(caption[0]);
                        var s = box.getElements(".s");
                        for (var i = 0; i < s.length; i++)
                                box.removeChild(s[i]);
                        var x = options.x;
                        var y = options.y;
                        var boxWidth = options.initWidth;
                        var boxHeight = options.initHeight;
                        if (options.startElement != false) {
                                x = options.startElement.getPosition().x;
                                y = options.startElement.getPosition().y;
                                boxWidth = options.startElement.offsetWidth;
                                boxHeight = options.startElement.offsetHeight;
                        }
                        if ((hideOverlay == true) && ($('imagezoom_overlay'))) {
                                var oFx = new Fx.Morph($('imagezoom_overlay'), {duration: options.closeDuration});
                                oFx.start({opacity: 0}).chain(function() {
                                        $$('body')[0].removeChild($('imagezoom_overlay'));
                                });
                        }
                        var fx = new Fx.Morph(box, {duration: options.closeDuration});
                        fx.start({
                                left: x,
                                top: y,
                                width: boxWidth,
                                height: boxHeight,
                                opacity: options.startOpacity
                        }).chain(function() {
                                fx.start({
                                        opacity: 0
                                }).chain(function() {
                                        $$('body')[0].removeChild(box);
                                });
                        });
                }
        }
