/* DotCom Interactive Core Library of functions

version:        1.4
last modified:  25/03/2009 14:26:49
released under: http://fragged.org/js/dci_core.js
dependencies: 	mootools 1.2.1 (core+more)

copyright (c) 2008, 2009 by Dimitar Christoff <dimitar@dci.uk.net>

use and modify as you see fit, credit me if you wish

*/

// import our voting script module...
//new Asset.javascript("/js/moo_rating.js");

// general variables we set to do with tooltips and images
var delayTimer, imagePath = "/assets/images/", pdown = new Asset.image(imagePath + "point_down.png");

// compatibility with mootools 1.11

Window.implement({
	$E: function(s) {
		return this.document.getElement(s);
	}
});

// element extending functions
Element.implement({
    getText: function(){
		var tag = this.getTag();
		if (['style', 'script'].contains(tag)){
			if (window.ie){
				if (tag == 'style') return this.styleSheet.cssText;
				else if (tag ==  'script') return this.getProperty('text');
			} else {
				return this.innerHTML;
			}
		}
		return ($pick(this.innerText, this.textContent));
	},
    showProgress: function(options) {
        options = $merge({
            count: 0,
            total: 10,
            message: "",
            className: "progress",
            backgroundPosition: 200, // start pos
            tween: true // animate or static
        }, options);

        // calculate % of progress
        var percent = options.total / 100, donePercent = (options.count / percent).round(), BGoffset = options.backgroundPosition - (donePercent*2).round();
        donePercent = (isNaN(donePercent)) ? "0" : donePercent;
        // set inline message
        this.set({
            styles: {
                "background-position": "-" + options.backgroundPosition + "px"
            },
            html: "&nbsp; " + options.count + " of " + options.total + " " + options.message + " ("+donePercent+"%)",
            "class": options.className
        });

        if (options.tween)
            new Fx.Tween(this, {
                duration: 500,
                transition: Fx.Transitions.Cubic.easeIn
            }).start("background-position", "-" + BGoffset);
        else
            this.setStyle("background-position", "-" + BGoffset + "px");

        this.store("percent", donePercent);
        return this;
    },
    smartDispose: function() {
        // dispose of an element and its dropShadow (if there is one)
        var rel = this.get("data-related");
	    if ($(rel)) {
	        $(rel).dispose();
	    }
		this.dispose();
	}, // end smartDispose
	dropShadow: function(options) {
	    // creates a shadow effect to a rectangular element

	    // define defaults
        var options = $merge({
            id: "dropShadow" + $random(100,1000),
            x: 3, // offset from parent
            y: 3,
            border: "1px solid #000",
            background: "#555",
            opacity: .5,
            zIndex: this.getStyle("z-index").toInt() - 1 // behind parent
        }, options);

        // only apply shadow on absolutely positioned elements
        if (this.getStyle("position") != "absolute")
            return this;

        var c = this.getCoordinates();

        new Element("div", {
            id: options.id,
            styles: {
                position: "absolute",
                left: c.left + options.x,
                top: c.top + options.y,
                width: c.width,
                height: c.height,
                background: options.background,
                zIndex: options.zIndex
            },
            opacity: 0
        }).injectBefore(this).fade(0, options.opacity);

        // store the shadow id into the element
        this.set("data-related", options.id);

        return this;
    }, // end dropShadow
	Bubble: function(message,options) {
        // open up a  bubble popup for text

        var bubbleOptions = $merge({
            y: 64,					// offset (substracted from element top)
            x: 10, 					// offset to element left
            fadeFrom: 0,			// fade start value
            fadeUntil: .95,			// fade end
            shadowFadeFrom: 0,
            shadowFadeUntil: .5,
            directionX: 2,			// shadow offset X from bubble
            directionY: 2,			// shadow offset Y
            delayShort: 1000,
            delayLong: 5000
        }, options)

        $clear(delayTimer);
        if ($("myBubble")) {
            $("myBubble").dispose();
            $("myBubbles").dispose();
        }

        var coords  = this.getPosition();
        var bubbles = new Element("div", {
            "styles": {
                "position": "absolute",
                "top": coords.y-bubbleOptions.y+bubbleOptions.directionY,
                "left": coords.x+bubbleOptions.x+bubbleOptions.directionX
            },
            "id": "myBubbles",
            "opacity": bubbleOptions.shadowFadeFrom,
            "z-index": 100000001

        }).inject(document.body).fade(bubbleOptions.shadowFadeFrom,bubbleOptions.shadowFadeUntil);
        var bubble = new Element("div", {
            "styles": {
                "position": "absolute",
                "top": coords.y-bubbleOptions.y,
                "left": coords.x+bubbleOptions.x
            },
            "id": "myBubble",
            "opacity": bubbleOptions.fadeFrom,
            "html": message,
            "z-index": 100000002,
            "events": {
                "mouseenter": function() {
                    $clear(delayTimer);
                    this.setOpacity(1);
                },
                "mouseleave": function() {
                    this.setOpacity(bubbleOptions.fadeUntil);
                    delayTimer = (function() {
                        if (bubbleOptions.fadeFrom == bubbleOptions.fadeUntil && $("myBubble")) {
                            $("myBubble").dispose();
                            $("myBubbles").dispose();
                        }
                        else {
                            if ($("myBubble")) {
                                $("myBubble").fade(bubbleOptions.fadeFrom);
                                $("myBubbles").fade(bubbleOptions.shadowFadeFrom);
                                if ($("closeBubble"))
                                    $("closeBubble").dispose();
                                (function() {
                                    $("myBubble").dispose();
                                    $("myBubbles").dispose();
                                }).delay(500);
                            }
                        }
                    }).delay(bubbleOptions.delayShort);
                }
            }
        }).inject(document.body).fade(bubbleOptions.fadeUntil);


        new Element("img", {
            "src": imagePath + "close.gif",
            "id": "closeBubble",
            "events": {
                "mouseenter": function() {
                    this.set("opacity", 1);
                },
                "mouseleave": function() {
                    this.set("opacity", .7);
                },
                "click": function() {
                    $clear(delayTimer);
                    if (bubbleOptions.fadeFrom == bubbleOptions.fadeUntil && $("myBubble")) {
                        $("myBubble").dispose();
                        $("myBubbles").dispose();
                    }
                    else {
                        $("myBubble").fade(bubbleOptions.fadeFrom).removeEvents();
                        $("myBubbles").fade(bubbleOptions.shadowFadeFrom);
                        if ($("closeBubble"))
                           $("closeBubble").dispose();
                        (function() {
                            $("myBubble").dispose();
                            $("myBubbles").dispose();
                        }).delay(500);
                    }
                } // click
            },
            "styles": {
                "position": "absolute",
                "top": 2,
                "left": 148,
                "opacity": .7
            },
            "class": "cur"
        }).injectInside(bubble);

        delayTimer = (function() {
            if (bubbleOptions.fadeFrom == bubbleOptions.fadeUntil && $("myBubble")) {
                $("myBubble").dispose();
                $("myBubbles").dispose();
            }
            else {
                if ($("myBubble")) {
                    $("myBubble").fade(bubbleOptions.fadeFrom).removeEvents();
                    $("myBubbles").fade(bubbleOptions.shadowFadeFrom);
                    if ($("closeBubble"))
                        $("closeBubble").dispose();
                    (function() {
                        $("myBubble").dispose();
                        $("myBubbles").dispose();
                    }).delay(500);
                }
            }
        }).delay(bubbleOptions.delayLong);

        return this;
    },
    tooltip: function(message, options) {
    	// a quick 'facebook' style tooltip
    	// function version 2.1, 16/09/2008 13:57:28

    	if (!$type(message))
    	    return false;

        var options = $merge({
            eventStart: "mouseenter",
            eventEnd: "mouseleave",
            topOffset: 20,
            opacity: 1
        }, options);

        var el = this;
        var coords = el.getCoordinates();
        var c = el.getPosition();

        if ($("pointerDown"))
            $("pointerDown").dispose();



        var pointer = new Element("div", {
            styles: {
                position: "absolute",
                height: 21,
                top: coords.top - options.topOffset,
                left: -200,
                "text-align": "center",
                "z-index": 1000000000,
                "line-height": "9px",
                margin: 0,
                padding: 0
            },
            id: "pointerDown"
        });

        var tipbody = new Element("div", {
            styles: {
                background: "#000000",
                color: "#ffffe5",
                padding: 2,
                "padding-bottom": 3,
                "padding-left": 9,
                "padding-right": 9,
                "width": "auto",
                "display": "inline",
                "margin-left": "auto",
                "margin-right": "auto",
                overflow: "hidden",
                opacity: options.opacity,
                "font-size": "10px",
                "font-family": "verdana",
                "line-height": "9px"
            },
            html: message.replace(/ /g, "&nbsp;")
        }).inject(pointer);
        pointer.inject(document.body);

        var pointy = pdown.clone().inject(new Element("div", {
            styles: {
                "margin-top": (Browser.Engine.trident) ? 0 : 5,
                opacity: options.opacity
            }
        }).injectAfter(tipbody));

        this.addEvent(options.eventEnd, function() {
            if ($("pointerDown")) {
                $("pointerDown").dispose();
                el.removeEvent(options.eventEnd);
            }
        });

        // var tipWidth = tipbody.getCoordinates();
        var t = tipbody.getSize();
        if (Browser.Engine.trident4 && t.x == 0) {
        	pwidth = 90;

        	var lefty = coords.left + (coords.width / 2).round() - (pwidth / 2).round();
        	pointer.setStyles({"left":  lefty, "width": pwidth});
        	// again, needs to be visible to calc width sometimes in ie6
        	var t = tipbody.getSize();
        	pointer.setStyles({"left":  lefty, "width": t.x});
        }
        else {
	        var lefty = coords.left + (coords.width / 2).round() - (t.x / 2).round();
	        pointer.setStyles({"left":  lefty, "width": t.x});
        }

        return this;
    },
    slidingTip: function(what, options) {
        // apple style tooltip
        var _this = this, coords = _this.getCoordinates(), options = $merge({
            eventEnd: "mouseleave",
            eventEndTrigger: _this,     // parent element or self
            topOffset: 90,             // offset when in full view
            topStartOffset: 100,        // offset for animation start
            opacity: .8,                // target opacity in full view
            className: "tooltip",       // linked to css
            morphOptions: {
                duration: 300,
                transition: Fx.Transitions.Sine.easeOut
            },
            delay: 0,                    // can dispose on a timer, in seconds
            id: "tid" + $random(100, 1000)
        }, options);

        // we only need one tip instance per parent element.
        if ($type(this.tip) != "element") {
            this.tip = new Element("div", {
                "class": options.className
                // id: options.id,
            });
        }

        // if it's an existing one, with an implicit id, pick it up
        if ($(options.id))
            this.tip = $(options.id);

        // set initial options and html
        this.tip.set({
            opacity: 0,
            html: "<div style='padding:20px'>" + what + "</div>",
            styles: {
                left: coords.left + coords.width / 2
            }
        }).inject(document.body).removeEvents();

        // show it. cancel any previous animation instances for tip
        if ($type(this.morph) == "object")
           this.morph.cancel();
        else
            this.morph = new Fx.Morph(this.tip, options.morphOptions);

        // show it. really.
        this.morph.start({
            opacity: options.opacity,
            top: [coords.top - _this.tip.getSize().y - options.topStartOffset, coords.top - options.topOffset]
        }).chain(function() {
            // once done, decide how to exit
            if (options.delay == 0) {
                // based on an event.
                options.eventEndTrigger.addEvent(options.eventEnd, function() {
                    _this.morph.cancel();
                    _this.slidingTipaway();
                });
            }
            else {
                // based on a timed delay
                (function() {
                    _this.slidingTipaway();
                }).delay(options.delay);
            }
        });

        // define the tooltip close animation morph object
        var closeAnimation = {
            opacity: 0,
            top: coords.top - _this.tip.getSize().y - options.topStartOffset
        }

        // ... and save it within the parent element
        this.store("closeAnimation", closeAnimation);

        return this;
    },
    slidingTipaway: function() {
        // animate an slidingTip, opposite on in method.
        if (this.tip) {
            this.morph.start(this.retrieve("closeAnimation"));
        }

        return this;
    },
	polka: function() {
		// draw polka dots over an element to make it 'unavailable'.
		var _this = this;
		var coords = this.getCoordinates();
		new Element("div", {
			"class": "polka",
			styles: {
				width: coords.width-2,
				height: coords.height-2,
				position: "absolute",
				left: coords.left+1,
				top: coords.top+1,
				"background-image": "url("+imagePath+"polka.gif)",
				"z-index": 1000,
				opacity: .7
			},
			events: {
				click: function() {
					_this.getElement(".polka").dispose();
					_this.dispose();
					// reposition the rest.

					$$(".polka").each(function(el) {
						var c = el.getParent().getPosition();
						el.setStyles({
							top: c.y+1,
							left: c.x+1
						});
					})
				}
			}
		}).inject(this);
		return this;
	}
}); // end element.implement


var toggleModal = function(backgroundColour, options) {
    // modal view for the whole screen
    // ver 2.02 17/10/2008 03:42:06
    // returns the $("modal") div as element.
    if ($("modal")) {
        $("modal").dispose();
        return false;
    }

    var options = $merge({
        zIndex: 10000000,
        opacity: .01,
        events: $empty()
    }, options);

    if (!$type(backgroundColour) && !$("modal"))
        return false;

    return new Element("div", {
        id: "modal",
        styles: {
            position: "absolute",
            top: 0,
            left: 0,
            width: window.getScrollWidth(),
            height: window.getScrollHeight(),
            background: backgroundColour,
            "z-index": options.zIndex
        },
        opacity: options.opacity,
        events: options.events
    }).inject(document.body);
} // end toggleModal

var centerBox = function(width, height) {
    // returns a coordinates JSON for positioning of a box in the centre of the browser
    var winSize = window.getSize();
    var winScroll = window.getScroll();
    var windowHeight = window.getScrollHeight()-1;

    var coords = {
        y: winScroll.y + (winSize.y / 2) - (height / 2),
        x: winSize.x / 2 - width / 2,
        width: width,
        height: height
    }

    if (coords.y + height + 20 > windowHeight)
        coords.y = windowHeight - 20 - height;

    if (coords.y <= 0) {
        coords.y = 20;
    }

    return coords;
}

window.addEvent("domready", function() {
    // the DCI largerbox: an Apple.com style slimbox

    $$("a.fullImage").addEvents({
        // works on image links wih the class 'fullImage'
        click: function(e) {
            this.fireEvent("mouseleave");

            // only one instance and do not go over other modals...
            if ($("largerBox") || $("modal"))
                return false;

            var _this = this, myevents;
            var e = new Event(e).stop(); // stop default. can use e.preventDefault also but this has
                                         // issues in IE6

            toggleModal("#fff");

            var coords = this.getFirst().getCoordinates();


            new Asset.image(this.get("href"), {
                onload: function() {
                    var image = centerBox(this.width, this.height);

                    this.set({
                        id: "largerBox",
                        styles: {
                            "z-index": 1000000000,
                            position: "absolute",
                            top: coords.top,
                            left: coords.left,
                            width: coords.width,
                            height: coords.height
                        },
                        "class": "cur",
                        events: {
                            click: function() {
                                $clear(myevents);
                                this.fireEvent("mouseleave");

                                // close animation
                                var myEffect = new Fx.Morph($("largerBox"), {
                                    transition: Fx.Transitions.Sine.easeOut,
                                    duration: 150
                                }).start({
                                    width: coords.width,
                                    height: coords.height,
                                    left: coords.left,
                                    top: coords.top,
                                    "border-width": 0,
                                    opacity: .4
                                });

                                this.fade(0);

                                var _this = this;
                                (function() {
                                    _this.dispose();
                                    toggleModal();
                                }).delay(500);
                            }
                        }
                    }).inject(document.body).makeDraggable();

                    $clear(initCheck);

                    var myEffect = new Fx.Morph($("largerBox"), {
                        transition: Fx.Transitions.Sine.easeOut,
                        duration: 300
                    }).start({
                        width: image.width,
                        height: image.height,
                        left: image.x,
                        top: image.y,
                        "border-width": "3px"
                    });

                    var __this = this;

                    (function() {
                        __this.addEvents({
                            mouseenter: function() {
                                __this.tooltip("click to close");
                            }
                        });
                    }).delay(300);

                    myevents = (function() {
                        __this.fireEvent("mouseenter");
                    }).delay(1000);
                }
            });

            var initCheck = (function() {
                _this.set("href", "#").removeEvents();
                _this.getFirst().removeEvents();
                if (!$("largerBox"))
                    toggleModal();
            }).delay(3500);
        },
        mouseenter: function() {
            /*
            this.getFirst().tooltip("click to enlarge", {
                opacity: .8
            });*/
        }

    });

    var labels = {
        setLabels: function() {
            $$("code").each(function(el) {
                // attach a label in the top-left corner
                var $coords = el.getCoordinates();
                var blockQuote = el.getParent().getParent();
                var $coords = blockQuote.getCoordinates();
                var foo = new Element("div", {
                    styles: {
                        border: "1px solid #727F8A",
                        background: "#ffffe5",
                        color: "#444",
                        "font-size": "9px",
                        "font-weight": 600,
                        "letter-spacing": 2,
                        "text-transform": "uppercase",
                        height: 14,
                        padding: 1,
                        "padding-top": 0,
                        position: "absolute",
                        "z-index": 1000000000,
                        left: $coords.left + 6,
                        top: $coords.top - 12
                    },
                    "class": "codeLabel",
                    text: el.className
                }).inject(document.body);

                foo.clone().set({
                    styles: {
                        left: $coords.left + 10,
                        top: $coords.top - 8,
                        opacity: .4,
                        background: "#000",
                        border: 0
                    }
                }).injectBefore(foo);

                var c2c = new Element("div", {
                    styles: {
                        border: "1px solid #727F8A",
                        background: "#ffffe5",
                        color: "#444",
                        "font-size": "9px",
                        "font-weight": 600,
                        "letter-spacing": 2,
                        "text-transform": "uppercase",
                        height: 14,
                        padding: 1,
                        "padding-top": 0,
                        position: "absolute",
                        left: $coords.right - 70,
                        top: $coords.top - 12
                    },
                    "class": "codeLabel cur",
                    text: "copy"
                }).inject(document.body).addEvents({
                    click: function() {
                        clipboard(el.get("text"));
                    }
                });

                c2c.clone().set({
                    styles: {
                        left: $coords.right - 66,
                        top: $coords.top - 8,
                        opacity: .4,
                        background: "#000",
                        border: 0
                    }
                }).injectBefore(c2c);

                var foo2 = new Element("div", {
                    styles: {
                        border: "1px solid #727F8A",
                        background: "#ffffe5",
                        color: "#444",
                        "font-size": "9px",
                        "font-weight": 600,
                        "letter-spacing": 2,
                        "text-transform": "uppercase",
                        height: 14,
                        padding: 1,
                        "padding-top": 0,
                        position: "absolute",
                        left: $coords.right - 20,
                        top: $coords.top - 12
                    },
                    "class": "codeLabel cur",
                    text: "+"
                }).inject(document.body).addEvents({
                    click: function() {
                        this.fireEvent("mouseleave");
                        var oldStyles = blockQuote.getStyles("width", "position", "z-index", "height", "left", "top");
                        if ($("codeBox") || $("modal"))
                            return false;

                        var _this = this, myevents;
                        toggleModal("#555", {
                            zIndex: 1000,
                            events: {
                                click: function() {
                                    $("modal").dispose();
                                    blockQuote.setStyles(oldStyles).set("id", "");
                                    window.doresize = true;
                                    labels.moveLabels();
                                    blockQuote.removeEvents();
                                }
                            }
                        });

                        var coords = blockQuote.getCoordinates();

                        var winSize = window.getSize();
                        var winScroll = window.getScroll();
                        var windowHeight = window.getScrollHeight()-1;

                        blockQuote.set({
                            id: "codeBox",
                            styles: {
                                position: "absolute",
                                left: blockQuote.left,
                                top: blockQuote.top,
                                "z-index": 1000000000-1
                            },
                            events: {
                                click: function(e) {
                                    e.stopPropagation();
                                }
                            }
                        });


                        blockQuoteHeight = blockQuote.getStyle("height").toInt();
                        var code = {
                            y: winScroll.y + (winSize.y / 2) - (blockQuoteHeight / 2),
                            x: winSize.x / 2 - 800 / 2,
                            width: 800,
                            height: (blockQuoteHeight > winSize.y) ? winSize.y - 40 : blockQuoteHeight
                        }

                        if (code.y + blockQuoteHeight + 20 > windowHeight)
                            code.y = windowHeight - 20 - blockQuoteHeight;

                        if (code.y <= 0)
                            code.y = 20;

                        var myEffect = new Fx.Morph(blockQuote, {
                            transition: Fx.Transitions.Sine.easeOut,
                            duration: 300
                        }).start({
                            width: code.width,
                            height: code.height,
                            left: code.x,
                            top: code.y,
                            "border-width": 0,
                            opacity: 1
                        }).chain(function() {
                            $$("div.codeLabel").dispose();
                            window.doresize = false;
                            blockQuote.addEvent("click", function() {
                                $("modal").fireEvent("click");
                            });
                        });

                    },
                    mouseenter: function() {
                        this.tooltip("expand code");
                    }
                });

                foo2.clone().set({
                    styles: {
                        left: $coords.right - 16,
                        top: $coords.top - 8,
                        opacity: .4,
                        background: "#000",
                        border: 0
                    }
                }).injectBefore(foo2);

            });

        },
        moveLabels: function() {
            if (window.doresize == false)
                return false;
            $$("div.codeLabel").dispose();
            this.setLabels();
        },
        init: function() {
            this.moveLabels();
            window.addEvent("resize", function() {
                labels.moveLabels()
            });
        }
    }

    labels.init();

    (function() {
        $$(".dismiss").fade(0);
    }).delay(10000);

    (function() {
        $$(".dismiss").dispose();
        labels.moveLabels();
    }).delay(10500);

    // tooltips on tags
    $$("strong.tag").addEvents({
        mouseenter: function() {
            this.tooltip("google " + this.get("text"), {opacity: .8});
        },
        click: function() {
            window.open("http://www.google.com/search?q="+ this.get("text"));
        }
    }).addClass("cur");


    // hidden emails
    $$("a.mailLink").each(function(el) {
        var mailProperties = JSON.decode(el.get("title"));
        el.set({
            "href": "mailto:" + mailProperties.user + "@" + mailProperties.domain + "?subject="+ mailProperties.subject,
            "title": "Send a mail to "+ mailProperties.user + "@" + mailProperties.domain
        });
    });

});


var C = {
    // console wrapper
    debug: true, // global debug on|off
    quietDismiss: false, // may want to just drop, or alert instead
    log: function() {
        if (!C.debug) return false;


        if (typeof console == 'object' && typeof console.log != "undefined")
            console.log.apply(this, arguments);
        else
            if (!C.quietDismiss) {
                var result = "";
                for (var i = 0, l = arguments.length; i < l; i++)
                    result += arguments[i] + " ("+typeof arguments[i]+") ";

                alert(result);
            }
    }
} // end console wrapper.

var clipboard = function(text2copy) {
    // this for ie...
    /*if(window.clipboardData && clipboardData.setData )	{
	    clipboardData.setData("text", escape(text2copy));
	    return false;
	}*/

    // else, use flash object instead.
    var clipObject = '<embed src="/_clipboard.swf" FlashVars="clipboard='+encodeURIComponent(text2copy)+'" width="0" height="0" type="application/x-shockwave-flash"></embed>';


    if ($("flashcopier"))
        $("flashcopier").set("html", clipObject);
    else
        new Element("div", {
            id: "flashcopier",
            styles: {
                position: "absolute",
                top: -1,
                left: -1,
                width: 1,
                height: 1
            },
            html: clipObject
        }).inject(document.body);

};
