/* jQuery Map Plugin
 * Version 0.5
 * Author Abel Mohler
 * Developed for Kukio July 2009
 * Released with the MIT License: http://www.opensource.org/licenses/mit-license.php
 */
//(function(a){a.fn.mapbox=function(c,i){var e={zoom:true,pan:true,defaultLayer:0,layerSplit:4,mapContent:".mapcontent",defaultX:null,defaultY:null,callBefore:function(n,m,l,k){},callAfter:function(n,m,l,k){},beforeZoom:function(n,m,l,k){},afterZoom:function(n,m,l,k){},mousewheel:false};if(typeof i=="function"){c.callAfter=i}var d;if(typeof c=="string"){d=c}c=a.extend(e,c||{});a(this).css({overflow:"hidden",position:"relative"});function h(o){if(!c.zoom){return}if(o===0){return}else{o=o||1}var s=a(this).find(">div"),C=s.length-1,A=a(this).find(".current-map-layer");if(typeof c.beforeZoom=="function"){c.beforeZoom(A[0],this.xPos,this.yPos,this)}var B=this.visible,G=B;B+=(o/c.layerSplit);if(B<0){B=0}if(B>C){B=C}G=Math.ceil(B);this.visible=B;var y=A.width(),u=A.height();var k=((a(this).width()/2)+this.xPos)/y,x=((a(this).height()/2)+this.yPos)/u;if(c.layerSplit>1&&G>0){var l=B-(G-1),w=s.eq(G)[0].defaultWidth,v=s.eq(G)[0].defaultHeight,r=s.eq(G-1).width(),q=s.eq(G-1).height();var p=w-r,n=v-q,m=r+(p*l),D=q+(n*l);s.eq(G).width(m).find(".map-layer-mask").width(m).height(D);s.eq(G).height(D).find(c.mapContent).width(m).height(D)}var z=(s.eq(G).width()*k)-(a(this).width()/2),t=(s.eq(G).height()*x)-(a(this).height()/2);z=0-z;t=0-t;var F=a(this).width()-s.eq(G).width(),E=a(this).height()-s.eq(G).height();if(z>0){z=0}if(t>0){t=0}if(z<F){z=F}if(t<E){t=E}this.xPos=0-z;this.yPos=0-t;s.removeClass("current-map-layer").hide();s.eq(G).css({left:z+"px",top:t+"px",display:"block"}).addClass("current-map-layer");if(typeof c.afterZoom=="function"){c.afterZoom(s.eq(G)[0],this.xPos,this.yPos,this)}}function j(t,s,o){o=o||a(this).find(".current-map-layer");var m=0,l=0,p=a(this).width(),q=a(this).height(),u=a(o).width(),k=a(o).height();if(p<u){m=p-u}if(q<k){l=q-k}var n=0-(this.xPos+t),r=0-(this.yPos+s);n=(n>0)?0:n;n=(n<m)?m:n;r=(r>0)?0:r;r=(r<l)?l:r;this.xPos=0-n;this.yPos=0-r;a(o).css({left:n+"px",top:r+"px"})}function g(k,o,l){l=l||a(this).find(".current-map-layer");k=0-k;o=0-o;var n=0-(a(l).width()-a(this).width());var m=0-(a(l).height()-a(this).height());if(k>0){k=0}if(o>0){o=0}if(k<n){k=n}if(o<m){o=m}this.xPos=0-k;this.yPos=0-o;a(l).css({left:k+"px",top:o+"px"})}function f(k){k=k.replace(/px/,"");k=0-k;return k}var b={zoom:function(k){k=k||1;h.call(this,k)},back:function(k){k=k||1;h.call(this,0-k)},left:function(k){k=k||10;j.call(this,0-k,0)},right:function(k){k=k||10;j.call(this,k,0)},up:function(k){k=k||10;j.call(this,0,0-k)},down:function(k){k=k||10;j.call(this,0,k)},center:function(l){l=l||{x:a(this).find(".current-map-layer").width()/2,y:a(this).find(".current-map-layer").height()/2};var k=a(this).find(".current-map-layer");var n=l.x-(a(this).width()/2),m=l.y-(a(this).height()/2);g.call(this,n,m,k[0])},zoomTo:function(l){var k=Math.round((l-this.visible)/(1/this.layerSplit));h.call(this,k)}};return this.each(function(){if(typeof d=="string"){var u=b[d];c.layerSplit=this.layerSplit||c.layerSplit;u.call(this,i)}else{this.visible=c.defaultLayer,this.layerSplit=c.layerSplit;var t=this,o=a(this).find(">div"),s=a(this).height(),q=a(this).width(),p=false,r=true;o.css({position:"absolute"}).eq(c.defaultLayer).css({display:"block",left:"",top:""}).addClass("current-map-layer").find(c.mapContent).css({position:"absolute",left:"0",top:"0",height:s+"px",width:"100%"});o.each(function(){this.defaultWidth=a(this).width();this.defaultHeight=a(this).height();a(this).find(c.mapContent).css({position:"absolute",top:"0",left:"0"});if(a(this).find(c.mapContent).length>0){a(this).find(">img").css({width:"100%",position:"absolute",left:"0",top:"0"}).after('<div class="map-layer-mask"></div>')}});a(this).find(".map-layer-mask").css({position:"absolute",left:"0",top:"0",background:"white",opacity:"0",filter:"alpha(opacity=0)"});if(c.defaultLayer>0){o.eq(c.defaultLayer).find(".map-layer-mask").width(o.eq(c.defaultLayer).width()).height(o.eq(c.defaultLayer).height());o.eq(c.defaultLayer).find(c.mapContent).width(o.eq(c.defaultLayer).width()).height(o.eq(c.defaultLayer).height())}a(this).find(">div:not(.current-map-layer)").hide();if(c.defaultX==null){c.defaultX=Math.floor((q/2)-(a(this).find(".current-map-layer").width()/2));if(c.defaultX>0){c.defaultX=0}}if(c.defaultY==null){c.defaultY=Math.floor((s/2)-(a(this).find(".current-map-layer").height()/2));if(c.defaultY>0){c.defaultY=0}}this.xPos=0-c.defaultX;this.yPos=0-c.defaultY;this.layerSplit=c.layerSplit;var n=c.defaultX;var m=c.defaultY;var l;var k;a(this).find(".current-map-layer").css({left:c.defaultX+"px",top:c.defaultY+"px"});a(this).mousedown(function(){var w=a(this).find(".current-map-layer");var v=w[0].style.left,z=w[0].style.top;v=f(v);z=f(z);c.callBefore(w,v,z,t);p=true;r=true;return false});a(document).mouseup(function(){var w=a(t).find(".current-map-layer");var v=w[0].style.left,z=w[0].style.top;v=f(v);z=f(z);c.callAfter(w,v,z,t);p=false;return false});a(document).mousemove(function(A){var x=a(t).find(".current-map-layer");if(p&&c.pan){if(r){l=A.clientX;k=A.clientY;n=x[0].style.left.replace(/px/,"");m=x[0].style.top.replace(/px/,"");r=false}var z=0,y=0;if(q<x.width()){z=q-x.width()}if(s<x.height()){y=s-x.height()}var w=n-(l-A.clientX);w=(w>0)?0:w;w=(w<z)?z:w;var v=m-(k-A.clientY);v=(v>0)?0:v;v=(v<y)?y:v;x.css({left:w+"px",top:v+"px"});t.xPos=f(x[0].style.left);t.yPos=f(x[0].style.top)}});if(c.mousewheel&&typeof a.fn.mousewheel!="undefined"){a(t).mousewheel(function(v,w){h.call(this,w)});a(this).hover(function(){document.body.style.overflow="hidden"},function(){document.body.style.overflow=null})}a(window).load(function(){o.each(function(){var v=a(this).find("img")[0];if(typeof v=="object"){a("<img>").attr("src",v.src)}})})}})}})(jQuery);

/* jQuery Map Plugin
 * Version 0.5.1
 * Author Abel Mohler
 * Developed for Kukio July 2009
 * Released with the MIT License: http://www.opensource.org/licenses/mit-license.php
 */
(function($) {// jQuery.noConflict compliant
    $.fn.mapbox = function(o, callback) {
        var defaults = {
            zoom: true,
            pan: true,
            defaultLayer: 0,
            layerSplit: 4,
            mapContent: ".mapcontent",
            defaultX: null,
            defaultY: null,
            callBefore: function(layer, xcoord, ycoord, viewport) {},
            callAfter: function(layer, xcoord, ycoord, viewport) {},
            beforeZoom: function(layer, xcoord, ycoord, viewport) {},
            afterZoom: function(layer, xcoord, ycoord, viewport) {},
            mousewheel: false //requires mousewheel event plugin: http://plugins.jquery.com/project/mousewheel
        }

        if(typeof callback == "function") {
            o.callAfter = callback;
        }
        var command;
        if(typeof o == "string") {
            command = o;//command passes "methods" such as "zoom", "left", etc.
        }

        o = $.extend(defaults, o || {});//inherit properties

        $(this).css({
            overflow: "hidden",
            position: "relative"
        });

        function _zoom(distance) {
            if(!o.zoom) return;
            if(distance === 0) return;
                else distance = distance || 1;

            var layers = $(this).find(">div"), limit = layers.length - 1, current = $(this).find(".current-map-layer");
            if(typeof o.beforeZoom == "function") {
                o.beforeZoom(current[0], this.xPos, this.yPos, this);
            }

            var move = this.visible, eq = move;
            move += (distance / o.layerSplit);
            if(move < 0) move = 0;
            if(move > limit) move = limit;
            eq = Math.ceil(move);
            this.visible = move;

            var oldWidth = current.width(), oldHeight = current.height();
            var xPercent = (($(this).width() / 2) + this.xPos) / oldWidth,
            yPercent = (($(this).height() / 2) + this.yPos) / oldHeight;

            if (o.layerSplit > 1 && eq > 0) {
                var percent = move - (eq -1), thisX = layers.eq(eq)[0].defaultWidth, thisY = layers.eq(eq)[0].defaultHeight, lastX = layers.eq(eq - 1).width(), lastY = layers.eq(eq - 1).height();
                var differenceX = thisX - lastX, differenceY = thisY - lastY, totalWidth = lastX + (differenceX * percent), totalHeight = lastY + (differenceY * percent);

                layers.eq(eq).width(totalWidth).find(".map-layer-mask").width(totalWidth).height(totalHeight);
                layers.eq(eq).height(totalHeight).find(o.mapContent).width(totalWidth).height(totalHeight);
            }

            //left and top adjustment for new zoom level
            var newLeft = (layers.eq(eq).width() * xPercent) - ($(this).width() / 2),
            newTop = (layers.eq(eq).height() * yPercent) - ($(this).height() / 2);

            newLeft = 0 - newLeft;
            newTop = 0 - newTop;

            var limitX = $(this).width() - layers.eq(eq).width(),
            limitY = $(this).height() - layers.eq(eq).height();

            if(newLeft > 0) newLeft = 0;
            if(newTop > 0) newTop = 0;
            if(newLeft < limitX) newLeft = limitX;
            if(newTop < limitY) newTop = limitY;

            this.xPos = 0 - newLeft;
            this.yPos = 0 - newTop;

            layers.removeClass("current-map-layer").hide();
            layers.eq(eq).css({
                left: newLeft + "px",
                top: newTop + "px",
                display: "block"
            }).addClass("current-map-layer");

            if(typeof o.afterZoom == "function") {
                o.afterZoom(layers.eq(eq)[0], this.xPos, this.yPos, this);
            }
        }

        function _move(x, y, node) {
            node = node || $(this).find(".current-map-layer");
            var limitX = 0, limitY = 0, mapWidth = $(this).width(), mapHeight = $(this).height(),
            nodeWidth = $(node).width(), nodeHeight = $(node).height();

            if(mapWidth < nodeWidth) limitX = mapWidth - nodeWidth;
            if(mapHeight < nodeHeight) limitY = mapHeight - nodeHeight;

            var left = 0 - (this.xPos + x), top = 0 - (this.yPos + y);

            left = (left > 0) ? 0 : left;
            left = (left < limitX) ? limitX : left;
            top = (top > 0) ? 0 : top;
            top = (top < limitY) ? limitY : top;

            this.xPos = 0 - left;
            this.yPos = 0 - top;

            $(node).css({
                left: left + "px",
                top: top + "px"
            });
        }

        function _position(x, y, node) {
            node = node || $(this).find(".current-map-layer");

            x = 0 - x;
            y = 0 - y;

            var limitX = 0 - ($(node).width() - $(this).width());
            var limitY = 0 - ($(node).height() - $(this).height());

            if(x > 0) x = 0;
            if(y > 0) y = 0;
            if(x < limitX) x = limitX;
            if(y < limitY) y = limitY;

            this.xPos = 0 - x;
            this.yPos = 0 - y;

            $(node).css({
                left: x + "px",
                top: y + "px"
            });
        }

        function _makeCoords(s) {
            s = s.replace(/px/, "");
            s = 0 - s;
            return s;
        }

        var method = {//public methods
            zoom: function(distance) {
                distance = distance || 1;
                _zoom.call(this, distance);
            },
            back: function(distance) {
                distance = distance || 1;
                _zoom.call(this, 0 - distance);
            },
            left: function(amount) {
                amount = amount || 10;
                _move.call(this, 0 - amount, 0);
            },
            right: function(amount) {
                amount = amount || 10;
                _move.call(this, amount, 0);
            },
            up: function(amount) {
                amount = amount || 10;
                _move.call(this, 0, 0 - amount);
            },
            down: function(amount) {
                amount = amount || 10;
                _move.call(this, 0, amount);
            },
            center: function(coords) {
                coords = coords || {
                    x: $(this).find(".current-map-layer").width() / 2,
                    y: $(this).find(".current-map-layer").height() / 2
                }
                var node = $(this).find(".current-map-layer");
                var newX = coords.x - ($(this).width() / 2), newY = coords.y - ($(this).height() / 2);
                _position.call(this, newX, newY, node[0]);
            },
            zoomTo: function(level) {
                var distance = Math.round((level - this.visible) / (1 / this.layerSplit));
                _zoom.call(this, distance);
            }
        }

        return this.each(function() {
            if(typeof command == "string") {//execute public methods if called
                var execute = method[command];
                o.layerSplit = this.layerSplit || o.layerSplit;
                execute.call(this, callback);
            }
            else {
                this.visible = o.defaultLayer, this.layerSplit = o.layerSplit;//magic
                var viewport = this, layers = $(this).find(">div"), mapHeight = $(this).height(), mapWidth = $(this).width(), mapmove = false, first = true;
                layers.css({
                    position: "absolute"
                }).eq(o.defaultLayer).css({
                    display: "block",
                    left: "",
                    top: ""
                }).addClass("current-map-layer").find(o.mapContent).css({
                    position: "absolute",
                    left: "0",
                    top: "0",
                    height: mapHeight + "px",
                    width: "100%"
                });

                layers.each(function() {
                    this.defaultWidth = $(this).width();
                    this.defaultHeight = $(this).height();
                    $(this).find(o.mapContent).css({
                        position: "absolute",
                        top: "0",
                        left: "0"
                    });
                    if($(this).find(o.mapContent).length > 0) $(this).find(">img").css({
                        width: "100%",
                        position: "absolute",
                        left: "0",
                        top: "0"
                    }).after('<div class="map-layer-mask"></div>')
                });

                $(this).find(".map-layer-mask").css({
                    position: "absolute",
                    left: "0",
                    top: "0",
                    background: "white",// omg, horrible hack,
                    opacity: "0",// but only way IE will not freak out when
                    filter: "alpha(opacity=0)"// mouseup over IMG tag occurs after mousemove event
                });

                if (o.defaultLayer > 0) {
                    layers.eq(o.defaultLayer).find(".map-layer-mask").width(layers.eq(o.defaultLayer).width()).height(layers.eq(o.defaultLayer).height());
                    layers.eq(o.defaultLayer).find(o.mapContent).width(layers.eq(o.defaultLayer).width()).height(layers.eq(o.defaultLayer).height());
                }

                $(this).find(">div:not(.current-map-layer)").hide();
                if(o.defaultX == null) {
                    o.defaultX = Math.floor((mapWidth / 2) - ($(this).find(".current-map-layer").width() / 2));
                    if(o.defaultX > 0) o.defaultX = 0;
                }
                if(o.defaultY == null) {
                    o.defaultY = Math.floor((mapHeight / 2) - ($(this).find(".current-map-layer").height() / 2));
                    if(o.defaultY > 0) o.defaultY = 0;
                }

                this.xPos = 0 - o.defaultX;
                this.yPos = 0 - o.defaultY;
                this.layerSplit = o.layerSplit;

                var mapStartX = o.defaultX;
                var mapStartY = o.defaultY;
                var clientStartX;
                var clientStartY;

                $(this).find(".current-map-layer").css({
                    left: o.defaultX + "px",
                    top: o.defaultY + "px"
                });

                /**
                 * Event Handling and Callbacks
                 */

                $(this).mousedown(function() {
                    var layer = $(this).find(".current-map-layer");
                    var x = layer[0].style.left, y = layer[0].style.top;
                    x = _makeCoords(x);
                    y = _makeCoords(y);
                    o.callBefore(layer, x, y, viewport);
                    mapmove = true;
                    first = true;
                    return false;//otherwise dragging on IMG elements etc inside the map will cause problems
                });

                /*$(this).find("img").hover(function() {
                    mapmove = false;
                }, function() {
                    mapmove = true;
                });*/

                $(viewport).mouseup(function() {
                    var layer = $(viewport).find(".current-map-layer");
                    var x = layer[0].style.left, y = layer[0].style.top;
                    x = _makeCoords(x);
                    y = _makeCoords(y);
                    o.callAfter(layer, x, y, viewport);
                    mapmove = false;
                    return false;
                });

                $(viewport).mousemove(function(e) {
                    var layer = $(viewport).find(".current-map-layer");
                    if(mapmove && o.pan) {
                        if(first) {
                            clientStartX = e.clientX;
                            clientStartY = e.clientY;
                            mapStartX = layer[0].style.left.replace(/px/, "");
                            mapStartY = layer[0].style.top.replace(/px/, "");
                            first = false;
                        }
                        var limitX = 0, limitY = 0;
                        if(mapWidth < layer.width()) limitX = mapWidth - layer.width();
                        if(mapHeight < layer.height()) limitY = mapHeight - layer.height();
                        var mapX = mapStartX - (clientStartX - e.clientX);
                        mapX = (mapX > 0) ? 0 : mapX;
                        mapX = (mapX < limitX) ? limitX : mapX;
                        var mapY = mapStartY - (clientStartY - e.clientY);
                        mapY = (mapY > 0) ? 0 : mapY;
                        mapY = (mapY < limitY) ? limitY : mapY;
                        layer.css({
                            left: mapX + "px",
                            top: mapY + "px"
                        });
                        viewport.xPos = _makeCoords(layer[0].style.left);
                        viewport.yPos = _makeCoords(layer[0].style.top);
                    }
                });

                if(o.mousewheel && typeof $.fn.mousewheel != "undefined") {
                    $(viewport).mousewheel(function(e, d) {
                        _zoom.call(this, d);
                        return false;//for some reason this did not occur to me, hence the commented function below
                    });
                    /*$(this).hover(function() {
                        document.body.style.overflow = "hidden";
                    }, function() {
                        document.body.style.overflow = null;
                    });*/
                }

                /**
                 *  End Event Handling and Callbacks
                 */

                //deferred, load images in hidden layers
                $(window).load(function() {
                    layers.each(function() {
                        var img = $(this).find("img")[0];
                        if(typeof img == "object") $("<img>").attr("src", img.src);
                    });
                });
            }
        });

    }
})(jQuery);