var PERSONAS_URLS = {
   'win_bundle'     : 'http://releases.mozilla.com/personas/win32/en-US/Firefox%20Setup%203.5.1.exe',
   'mac_bundle'     : 'http://releases.mozilla.com/personas/mac/en-US/Firefox%203.5.1.dmg',
   'linux_bundle'   : 'http://releases.mozilla.com/personas/linux-i686/en-US/firefox-3.5.1.tar.bz2',
   'addon'          : 'https://addons.mozilla.org/services/install.php?addon_id=personas'
}

var PERSONAS_ENABLED = true;

if (self != top) {
    PERSONAS_ENABLED = false;
}

function receiveMessage(event) {
  if (event.origin == 'http://www.mozilla.com' &&
      event.data == 'activatePersonas') {
      PERSONAS_ENABLED = true;
    }
}

window.addEventListener("message", receiveMessage, false)

/**
    Bubbles up persona event to tell Firefox to load a persona
**/
function dispatchPersonaEvent(aType, aNode)
{
    var aliases = {'PreviewPersona': 'PreviewBrowserTheme',
                   'ResetPersona': 'ResetBrowserThemePreview',
                   'SelectPersona': 'InstallBrowserTheme'};
    try {
        if (!aNode.hasAttribute("persona"))
			return;

    $(aNode).attr("data-browsertheme", $(aNode).attr("persona"));

    if(aType == 'SelectPersona') {
        var persona = JSON.parse($(aNode).attr("persona"));
        $.cookie("installed-persona", persona.id, {'path': '/'});
    }

    var aliasEvent = aliases[aType];
    var events = [aType, aliasEvent];

    for(var i=0; i<events.length; i++) {
      var event = events[i];
      var eventObject = document.createEvent("Events");
      eventObject.initEvent(event, true, false);
      aNode.dispatchEvent(eventObject);
    }
    } catch(e) { }
}

$.chooseLocale = function (currentLang) {
    $('#language-chooser').change(function() {
        var newLang = $("#language option:selected").attr('value');
        location.href = location.href.replace(currentLang, newLang);
    });
    $('#language-chooser input[type=submit]').remove();
}

$.fn.slider = function (options) {

    var settings = jQuery.extend({
        "slides"        : ".slides li",
        "nav"           : ".slideshow-nav",
        "viewport"      : ".slides",
        "previous"      : ".slideshow-previous",
        "next"          : ".slideshow-next",
        "nextImg"       : "/static/img/nav-next.png",
        "nextOverImg"   : "/static/img/nav-next-over.png",
        "prevOverImg"   : "/static/img/nav-prev-over.png",
        "prevImg"       : "/static/img/nav-prev.png"
    }, options);

    return this.each(function() {
        var that = this;
        var items = jQuery(this).find(settings['slides']);
        var index = 0;
        var viewportWidth = jQuery(this).find(settings['slides']+":first").css("width");
        viewportWidth = viewportWidth.substring(0,viewportWidth.length-2);
        var numItems = jQuery(this).find(settings['slides']).length-1;

        jQuery("<img>").attr("src", settings['nextOverImg']);
        jQuery("<img>").attr("src", settings['prevOverImg']);

        if(index == 0) {
            $(this).find(settings['previous']).addClass('disabled');
        }

        jQuery(this).find(settings['next']).click(function() {
            if(numItems != index) {
                jQuery(that).find(settings['viewport']).animate({left:"-="+viewportWidth+"px"});
                index++;
                setNav(index);
            }

            if(index == numItems) {
                jQuery(that).find(settings['next']).addClass('disabled');

            }

            if(index != 0) {
                jQuery(that).find(settings['previous']).removeClass('disabled');
            }

            return false;
        });

        jQuery(this).find(settings['previous']).click(function() {
            if(index != 0) {
                jQuery(that).find(settings['viewport']).animate({left:"+="+viewportWidth});
                index--;
                setNav(index);
            }

            if(index == 0) {
                jQuery(that).find(settings['previous']).addClass('disabled');
            } else {
                jQuery(that).find(settings['next']).removeClass('disabled');
            }

            return false;
        });

        jQuery(this).find(settings['nav']+' li a').click(function(event) {
            var value = Number(this.innerHTML)-1;
            var diff = index - value;
            if(diff != 0) {
                jQuery(that).find(settings['viewport']).animate({left:"+="+diff*viewportWidth+"px"});
                setNav(value);
                index = value;
            }

            if(index == 0) {
                jQuery(that).find(settings['previous']).addClass('disabled');
            } else if (index < numItems) {
                jQuery(that).find(settings['next']).removeClass('disabled');
                jQuery(that).find(settings['previous']).removeClass('disabled');
            } else {
                jQuery(that).find(settings['next']).addClass('disabled');
                jQuery(that).find(settings['previous']).removeClass('disabled');
            }


            return false;
        });

        jQuery(this).find(settings['next']).hover(
            function() {
                if(index != numItems) {
                    jQuery(this).children('img').attr('src', settings['nextOverImg']);
                }
            },
            function() {
                jQuery(this).children('img').attr('src', settings['nextImg']);
            }
        );

        jQuery(this).find(settings['previous']).hover(
            function() {
                if(index != 0) {
                    jQuery(this).children('img').attr('src', settings['prevOverImg']);
                }
            },
            function() {
                jQuery(this).children('img').attr('src', settings['prevImg']);
            }
        );

        function setNav(newIndex) {
            jQuery(that).find(settings['nav'] + ' li a.active').removeClass('active');
            jQuery(that).find(settings['nav'] + ' li a:eq('+newIndex+')').addClass('active');
        }
    });

};

/**
    Shows/hides 'theme your browser...' popup when mousing over bg image on homepage
**/
$.fn.popup = function() {
    jQuery(this).hover(function() {
        jQuery("#info").css({"position":"relative", "left":"0px"});
    },
    function() {
        jQuery("#info").css({"position":"absolute", "left":"-2000px"});
    });
};

/**
    Binds click and hover events to the element.
    Click - bubbles up ResetPersona event
    Mouseenter - bubbles up PreviewPersona
    Mouseleave - bubbles up ResetPersona
**/
$.fn.previewPersona = function(resetOnClick, installOnClick) {
    if(resetOnClick) {
        jQuery(this).click(function(event) {
            dispatchPersonaEvent('ResetPersona', event.originalTarget);
        });
    }

    if(installOnClick) {
        jQuery(this).click(function(event) {
            dispatchPersonaEvent('SelectPersona', event.originalTarget);
        });
    }

    jQuery(this).mouseenter(function(event) {
        dispatchPersonaEvent('PreviewPersona', event.currentTarget);
    });

    jQuery(this).mouseleave(function(event) {
        dispatchPersonaEvent('ResetPersona', event.currentTarget);
    });
};

/**
    Changes the innerhtml of the download button if the user is not using Firefox
**/
$.fn.personasDownload = function(options) {
    if(!jQuery.browser.mozilla || (navigator.userAgent.indexOf('Camino') != -1)) {
        jQuery(jQuery(this).find('span')[0]).html(options["bundle-text"]);

        var downloadUrl = jQuery.os.mac ? PERSONAS_URLS['mac_bundle'] :
            jQuery.os.win ? PERSONAS_URLS['win_bundle'] : PERSONAS_URLS['linux_bundle'];
        jQuery(this).attr("href", downloadUrl);

        if(options.hasFAQLink) {
            jQuery(this).parents('.get-personas').find('.platforms-note').remove();
        }
    } else {
        if($.is36OrGreater()) {
            jQuery(jQuery(this).find('span')[0]).html(STRINGS.getPersonasPlus);
        } else {

            if(options.hasFAQLink) {
                jQuery(this).parents('.get-personas').find('.platforms-note').remove();
            }
        }
        jQuery(this).click(function() {
            window.location = "https://addons.mozilla.org/services/install.php?addon_id=personas&src"+options.src;
            return false;
        });
    }
};

$.personasCheck = function () {
    var versionCompare = new VersionCompare();

    //FF 3.6 has lightweight themes (aka personas)
    if($.hasPersonas()) {
        $("#header .get-personas .wrapper").remove();
        $("#header .get-personas .platforms-note").remove();
        $("#header .get-personas div").html('<p class="ready-to-go"><span>'+
            STRINGS.readyToGo +
            '</span><span class="info">'+
            STRINGS.instructions+
            '</span></p>');
    }
};

$.welcomeMessage = function() {
    if($.cookie("noWelcomeMessage")) {
        return;
    }

    if(!$.hasPersonasAddon()) {
        $("#welcome-message").show();
        $.cookie("noWelcomeMessage", true, { expires: 900, path: '/'});

        $("#welcome-message .hide").click(function() {
            $("#welcome-message").hide();
        });
    }
}

$.is36OrGreater = function () {
    var versionCompare = new VersionCompare();
    if($.isFirefox() &&
        versionCompare.compareVersions($.browser.version,
                                      '1.9.2') > -1) {
        return true;
    }
    return false;
}

$.personasPlusContent = function () {
    if($.hasPersonasAddon()) {
        $(".featured-personas li:hidden").show();
        $(".movers li:hidden").show();
    }
};

$.plusUpsell = function () {
    if($.is36OrGreater() && !$.hasPersonasAddon()) {
        $("#plus-upsell").show();
    }
};

$.fn.ie6Warning = function(options) {
    if(jQuery.browser.msie && jQuery.browser.version == 6.0) {
        var message = options['message'].replace("%LINK%", PERSONAS_URLS['win_bundle']);
        jQuery(this).prepend(message);
    }
};

$.fn.personasButton = function(options) {
    var setCookie = false;
    if(jQuery.browser.mozilla) {
        if(jQuery.hasPersonas()) {
            jQuery(this).html(options['hasPersonas']);
            jQuery(this).hover(
                function(event) {
                    dispatchPersonaEvent('PreviewPersona', event.currentTarget);
                },
                function(event) {
                    dispatchPersonaEvent('ResetPersona', event.currentTarget);
                }
            );
            jQuery(this).click(function(event) {
                dispatchPersonaEvent('SelectPersona', event.currentTarget);
            });
        } else {
            jQuery(this).html(options['hasFirefox']);
            jQuery(this).attr("href", PERSONAS_URLS['addon']+'&src='+options.src);
            jQuery(this).click(function() {
                window.location = PERSONAS_URLS['addon']+'&src='+options.src;
            });
            setCookie = true;
        }
    } else {
        jQuery(this).html(options['noFirefox']);
        var downloadUrl = jQuery.os.mac ? PERSONAS_URLS['mac_bundle'] : jQuery.os.win ? PERSONAS_URLS['win_bundle'] : PERSONAS_URLS['linux_bundle'];
        jQuery(this).attr("href", downloadUrl);
        setCookie = true;
    }

    if(setCookie) {
        var personaJson = jQuery(this).attr('persona');
        $.cookie('initial_persona', personaJson, { expires: 1, path: '/'});
    }
};

$.hasPersonasAddon = function () {

    var body = document.getElementsByTagName("body")[0];
    var status = document.getElementById("status");

    try {
        var event = document.createEvent("Events");
        event.initEvent("CheckPersonas", true, false);
        body.dispatchEvent(event);
    } catch(e) {}

    return body.getAttribute("personas") == "true";
};

$.hasPersonas = function() {
    var versionCompare = new VersionCompare();

    //FF 3.6 has lightweight themes (aka personas)
    if((versionCompare.compareVersions($.browser.version,
                                      '1.9.2') > -1) && $.browser.mozilla) {
      return true;
    }

    return $.hasPersonasAddon();
};

$.fn.previewInteraction = function () {
    var hasPersonas = $.hasPersonas();
    return this.each(function() {
        var url = $(this).find('a').attr('href');
        var html = '<p class="actions">';

        if(hasPersonas) {
            html += ' <a class="wear-it" href="'+url+'">' + STRINGS.wearIt + '</a> ';
        }

        html += '<a class="details" href="'+url+'">'+STRINGS.details+'</a></p>';
        $(this).append(html);

        var persona = this;

        $(this).find('.wear-it').click(function(event) {
            dispatchPersonaEvent('SelectPersona', persona);
            window.location = url;
            return false;
        });

        $(this).find('.details').hover(
            function() {
                $(persona).addClass('details-over');
            },
            function() {
                $(persona).removeClass('details-over');
            }
        );
    });
};

$.postInstall = function(config) {
    var personaId = $.cookie("installed-persona");

    if(!personaId || config.id != personaId) {
        return;
    }

    $("#buttons").remove();
    $("#remove").show();
    $("#maincontent > .details").remove();

    if(!$.hasPersonasAddon()) {
        $(".persona-upsell").show();
    } else {
        $(".amo-upsell").show();
    }

    $("#maincontent .subheader h3").html(config.title);
    $.cookie("installed-persona", null, {'path':'/'});
}

$.homepageHeader = function() {
    if($.isFirefox()) {
        $("#header .intro h2").addClass("non-firefox")
            .html(STRINGS.nonFirefoxHeader);
    }
};

$.gettingStarted = function() {
    if($.is36OrGreater() && !$.hasPersonasAddon()) {
        $("#non-36-getting-started").hide();
        $("#firefox-36-getting-started").show();
    }
};

$.isFirefox = function() {
    return navigator.userAgent.match(/Firefox|Namoroka|Minefield/);
};

$.firefoxSubheader = function() {
    if($.isFirefox()) {
        $("#header h3").html(STRINGS.firefoxSubheader);
    }
};

$.faq = function() {
    if($.is36OrGreater() && !$.hasPersonasAddon()) {
        $(".firefox-36").show();
        $(".non-firefox-36").remove();
    } else {
        $(".firefox-36").remove();
    }
};

function VersionCompare() {
    /**
     * Mozilla-style version numbers comparison in Javascript
     * (JS-translated version of PHP versioncompare component)
     * @return -1: a<b, 0: a==b, 1: a>b
     */
    this.compareVersions = function(a,b) {
        var al = a.split('.');
        var bl = b.split('.');

        for (var i=0; i<al.length || i<bl.length; i++) {
            var ap = (i<al.length ? al[i] : null);
            var bp = (i<bl.length ? bl[i] : null);

            var r = this.compareVersionParts(ap,bp);
            if (r != 0)
                return r;
        }

        return 0;
    }

    /**
     * helper function: compare a single version part
     */
    this.compareVersionParts = function(ap,bp) {
        var avp = this.parseVersionPart(ap);
        var bvp = this.parseVersionPart(bp);

        var r = this.cmp(avp['numA'],bvp['numA']);
        if (r) return r;

        r = this.strcmp(avp['strB'],bvp['strB']);
        if (r) return r;

        r = this.cmp(avp['numC'],bvp['numC']);
        if (r) return r;

        return this.strcmp(avp['extraD'],bvp['extraD']);
    }

    /**
     * helper function: parse a version part
     */
    this.parseVersionPart = function(p) {
        if (p == '*') {
            return {
                'numA'   : Number.MAX_VALUE,
                'strB'   : '',
                'numC'   : 0,
                'extraD' : ''
                };
        }

        var pattern = /^([-\d]*)([^-\d]*)([-\d]*)(.*)$/;
        var m = pattern.exec(p);

        var r = {
            'numA'  : parseInt(m[1]),
            'strB'   : m[2],
            'numC'   : parseInt(m[3]),
            'extraD' : m[4]
            };

        if (r['strB'] == '+') {
            r['numA']++;
            r['strB'] = 'pre';
        }

        return r;
    }

    /**
     * helper function: compare numeric version parts
     */
    this.cmp = function(an,bn) {
        if (isNaN(an)) an = 0;
        if (isNaN(bn)) bn = 0;

        if (an < bn)
            return -1;

        if (an > bn)
            return 1;

        return 0;
    }

    /**
     * helper function: compare string version parts
     */
    this.strcmp = function(as,bs) {
        if (as == bs)
            return 0;

        // any string comes *before* the empty string
        if (as == '')
            return 1;

        if (bs == '')
            return -1;

        // normal string comparison for non-empty strings (like strcmp)
        if (as < bs)
            return -1;
        else if(as > bs)
            return 1;
        else
            return 0;
    }
}
/**
 *
 * Color picker
 * Author: Stefan Petre www.eyecon.ro
 *
 */
(function ($) {
	var ColorPicker = function () {
		var
			ids = {},
			inAction,
			charMin = 65,
			visible,
			tpl = '<div class="colorpicker"><div class="colorpicker_color"><div><div></div></div></div><div class="colorpicker_hue"><div></div></div><div class="colorpicker_new_color"></div><div class="colorpicker_current_color"></div><div class="colorpicker_hex"><input type="text" maxlength="6" size="6" /></div><div class="colorpicker_rgb_r colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_rgb_g colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_rgb_b colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_hsb_h colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_hsb_s colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_hsb_b colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_submit"></div></div>',
			defaults = {
				eventName: 'click',
				onShow: function () {},
				onBeforeShow: function(){},
				onHide: function () {},
				onChange: function () {},
				onSubmit: function () {},
				color: 'ff0000',
				livePreview: true,
				flat: false
			},
			fillRGBFields = function  (hsb, cal) {
				var rgb = HSBToRGB(hsb);
				$(cal).data('colorpicker').fields
					.eq(1).val(rgb.r).end()
					.eq(2).val(rgb.g).end()
					.eq(3).val(rgb.b).end();
			},
			fillHSBFields = function  (hsb, cal) {
				$(cal).data('colorpicker').fields
					.eq(4).val(hsb.h).end()
					.eq(5).val(hsb.s).end()
					.eq(6).val(hsb.b).end();
			},
			fillHexFields = function (hsb, cal) {
				$(cal).data('colorpicker').fields
					.eq(0).val(HSBToHex(hsb)).end();
			},
			setSelector = function (hsb, cal) {
				$(cal).data('colorpicker').selector.css('backgroundColor', '#' + HSBToHex({h: hsb.h, s: 100, b: 100}));
				$(cal).data('colorpicker').selectorIndic.css({
					left: parseInt(150 * hsb.s/100, 10),
					top: parseInt(150 * (100-hsb.b)/100, 10)
				});
			},
			setHue = function (hsb, cal) {
				$(cal).data('colorpicker').hue.css('top', parseInt(150 - 150 * hsb.h/360, 10));
			},
			setCurrentColor = function (hsb, cal) {
				$(cal).data('colorpicker').currentColor.css('backgroundColor', '#' + HSBToHex(hsb));
			},
			setNewColor = function (hsb, cal) {
				$(cal).data('colorpicker').newColor.css('backgroundColor', '#' + HSBToHex(hsb));
			},
			keyDown = function (ev) {
				var pressedKey = ev.charCode || ev.keyCode || -1;
				if ((pressedKey > charMin && pressedKey <= 90) || pressedKey == 32) {
					return false;
				}
				var cal = $(this).parent().parent();
				if (cal.data('colorpicker').livePreview === true) {
					change.apply(this);
				}
			},
			change = function (ev) {
				var cal = $(this).parent().parent(), col;
				if (this.parentNode.className.indexOf('_hex') > 0) {
					cal.data('colorpicker').color = col = HexToHSB(fixHex(this.value));
				} else if (this.parentNode.className.indexOf('_hsb') > 0) {
					cal.data('colorpicker').color = col = fixHSB({
						h: parseInt(cal.data('colorpicker').fields.eq(4).val(), 10),
						s: parseInt(cal.data('colorpicker').fields.eq(5).val(), 10),
						b: parseInt(cal.data('colorpicker').fields.eq(6).val(), 10)
					});
				} else {
					cal.data('colorpicker').color = col = RGBToHSB(fixRGB({
						r: parseInt(cal.data('colorpicker').fields.eq(1).val(), 10),
						g: parseInt(cal.data('colorpicker').fields.eq(2).val(), 10),
						b: parseInt(cal.data('colorpicker').fields.eq(3).val(), 10)
					}));
				}
				if (ev) {
					fillRGBFields(col, cal.get(0));
					fillHexFields(col, cal.get(0));
					fillHSBFields(col, cal.get(0));
				}
				setSelector(col, cal.get(0));
				setHue(col, cal.get(0));
				setNewColor(col, cal.get(0));
				cal.data('colorpicker').onChange.apply(cal, [col, HSBToHex(col), HSBToRGB(col)]);
			},
			blur = function (ev) {
				var cal = $(this).parent().parent();
				cal.data('colorpicker').fields.parent().removeClass('colorpicker_focus')
			},
			focus = function () {
				charMin = this.parentNode.className.indexOf('_hex') > 0 ? 70 : 65;
				$(this).parent().parent().data('colorpicker').fields.parent().removeClass('colorpicker_focus');
				$(this).parent().addClass('colorpicker_focus');
			},
			downIncrement = function (ev) {
				var field = $(this).parent().find('input').focus();
				var current = {
					el: $(this).parent().addClass('colorpicker_slider'),
					max: this.parentNode.className.indexOf('_hsb_h') > 0 ? 360 : (this.parentNode.className.indexOf('_hsb') > 0 ? 100 : 255),
					y: ev.pageY,
					field: field,
					val: parseInt(field.val(), 10),
					preview: $(this).parent().parent().data('colorpicker').livePreview
				};
				$(document).bind('mouseup', current, upIncrement);
				$(document).bind('mousemove', current, moveIncrement);
			},
			moveIncrement = function (ev) {
				ev.data.field.val(Math.max(0, Math.min(ev.data.max, parseInt(ev.data.val + ev.pageY - ev.data.y, 10))));
				if (ev.data.preview) {
					change.apply(ev.data.field.get(0), [true]);
				}
				return false;
			},
			upIncrement = function (ev) {
				change.apply(ev.data.field.get(0), [true]);
				ev.data.el.removeClass('colorpicker_slider').find('input').focus();
				$(document).unbind('mouseup', upIncrement);
				$(document).unbind('mousemove', moveIncrement);
				return false;
			},
			downHue = function (ev) {
				var current = {
					cal: $(this).parent(),
					y: $(this).offset().top
				};
				current.preview = current.cal.data('colorpicker').livePreview;
				$(document).bind('mouseup', current, upHue);
				$(document).bind('mousemove', current, moveHue);
			},
			moveHue = function (ev) {
				change.apply(
					ev.data.cal.data('colorpicker')
						.fields
						.eq(4)
						.val(parseInt(360*(150 - Math.max(0,Math.min(150,(ev.pageY - ev.data.y))))/150, 10))
						.get(0),
					[ev.data.preview]
				);
				return false;
			},
			upHue = function (ev) {
				fillRGBFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0));
				fillHexFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0));
				$(document).unbind('mouseup', upHue);
				$(document).unbind('mousemove', moveHue);
				return false;
			},
			downSelector = function (ev) {
				var current = {
					cal: $(this).parent(),
					pos: $(this).offset()
				};

				current.preview = current.cal.data('colorpicker').livePreview;

				change.apply(
					current.cal.data('colorpicker')
						.fields
						.eq(6)
						.val(parseInt(100*(150 - Math.max(0,Math.min(150,(ev.pageY - current.pos.top))))/150, 10))
						.end()
						.eq(5)
						.val(parseInt(100*(Math.max(0,Math.min(150,(ev.pageX - current.pos.left))))/150, 10))
						.get(0),
					[current.preview]
				);

				$(document).bind('mouseup', current, upSelector);
				$(document).bind('mousemove', current, moveSelector);
			},
			moveSelector = function (ev) {
				change.apply(
					ev.data.cal.data('colorpicker')
						.fields
						.eq(6)
						.val(parseInt(100*(150 - Math.max(0,Math.min(150,(ev.pageY - ev.data.pos.top))))/150, 10))
						.end()
						.eq(5)
						.val(parseInt(100*(Math.max(0,Math.min(150,(ev.pageX - ev.data.pos.left))))/150, 10))
						.get(0),
					[ev.data.preview]
				);
				return false;
			},
			upSelector = function (ev) {
				fillRGBFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0));
				fillHexFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0));
				$(document).unbind('mouseup', upSelector);
				$(document).unbind('mousemove', moveSelector);
				return false;
			},
			enterSubmit = function (ev) {
				$(this).addClass('colorpicker_focus');
			},
			leaveSubmit = function (ev) {
				$(this).removeClass('colorpicker_focus');
			},
			clickSubmit = function (ev) {
				var cal = $(this).parent();
				var col = cal.data('colorpicker').color;
				cal.data('colorpicker').origColor = col;
				setCurrentColor(col, cal.get(0));
				cal.data('colorpicker').onSubmit(col, HSBToHex(col), HSBToRGB(col));
			},
			show = function (ev) {
				var cal = $('#' + $(this).data('colorpickerId'));
				cal.data('colorpicker').onBeforeShow.apply(this, [cal.get(0)]);
				var pos = $(this).offset();
				var viewPort = getViewport();
				var top = pos.top + this.offsetHeight;
				var left = pos.left;
				if (top + 176 > viewPort.t + viewPort.h) {
					top -= this.offsetHeight + 176;
				}
				if (left + 356 > viewPort.l + viewPort.w) {
					left -= 356;
				}
				cal.css({left: left + 'px', top: top + 'px'});
				if (cal.data('colorpicker').onShow.apply(this, [cal.get(0)]) != false) {
					cal.show();
				}
				$(document).bind('mousedown', {cal: cal}, hide);
				return false;
			},
			hide = function (ev) {
				if (!isChildOf(ev.data.cal.get(0), ev.target, ev.data.cal.get(0))) {
					if (ev.data.cal.data('colorpicker').onHide.apply(this, [ev.data.cal.get(0)]) != false) {
						ev.data.cal.hide();
					}
					$(document).unbind('mousedown', hide);
				}
			},
			isChildOf = function(parentEl, el, container) {
				if (parentEl == el) {
					return true;
				}
				if (parentEl.contains) {
					return parentEl.contains(el);
				}
				if ( parentEl.compareDocumentPosition ) {
					return !!(parentEl.compareDocumentPosition(el) & 16);
				}
				var prEl = el.parentNode;
				while(prEl && prEl != container) {
					if (prEl == parentEl)
						return true;
					prEl = prEl.parentNode;
				}
				return false;
			},
			getViewport = function () {
				var m = document.compatMode == 'CSS1Compat';
				return {
					l : window.pageXOffset || (m ? document.documentElement.scrollLeft : document.body.scrollLeft),
					t : window.pageYOffset || (m ? document.documentElement.scrollTop : document.body.scrollTop),
					w : window.innerWidth || (m ? document.documentElement.clientWidth : document.body.clientWidth),
					h : window.innerHeight || (m ? document.documentElement.clientHeight : document.body.clientHeight)
				};
			},
			fixHSB = function (hsb) {
				return {
					h: Math.min(360, Math.max(0, hsb.h)),
					s: Math.min(100, Math.max(0, hsb.s)),
					b: Math.min(100, Math.max(0, hsb.b))
				};
			},
			fixRGB = function (rgb) {
				return {
					r: Math.min(255, Math.max(0, rgb.r)),
					g: Math.min(255, Math.max(0, rgb.g)),
					b: Math.min(255, Math.max(0, rgb.b))
				};
			},
			fixHex = function (hex) {
				var len = 6 - hex.length;
				if (len > 0) {
					var o = [];
					for (var i=0; i<len; i++) {
						o.push('0');
					}
					o.push(hex);
					hex = o.join('');
				}
				return hex;
			},
			HexToRGB = function (hex) {
				var hex = parseInt(((hex.indexOf('#') > -1) ? hex.substring(1) : hex), 16);
				return {r: hex >> 16, g: (hex & 0x00FF00) >> 8, b: (hex & 0x0000FF)};
			},
			HexToHSB = function (hex) {
				return RGBToHSB(HexToRGB(hex));
			},
			RGBToHSB = function (rgb) {
				var hsb = {};
				hsb.b = Math.max(Math.max(rgb.r,rgb.g),rgb.b);
				hsb.s = (hsb.b <= 0) ? 0 : Math.round(100*(hsb.b - Math.min(Math.min(rgb.r,rgb.g),rgb.b))/hsb.b);
				hsb.b = Math.round((hsb.b /255)*100);
				if((rgb.r==rgb.g) && (rgb.g==rgb.b)) hsb.h = 0;
				else if(rgb.r>=rgb.g && rgb.g>=rgb.b) hsb.h = 60*(rgb.g-rgb.b)/(rgb.r-rgb.b);
				else if(rgb.g>=rgb.r && rgb.r>=rgb.b) hsb.h = 60  + 60*(rgb.g-rgb.r)/(rgb.g-rgb.b);
				else if(rgb.g>=rgb.b && rgb.b>=rgb.r) hsb.h = 120 + 60*(rgb.b-rgb.r)/(rgb.g-rgb.r);
				else if(rgb.b>=rgb.g && rgb.g>=rgb.r) hsb.h = 180 + 60*(rgb.b-rgb.g)/(rgb.b-rgb.r);
				else if(rgb.b>=rgb.r && rgb.r>=rgb.g) hsb.h = 240 + 60*(rgb.r-rgb.g)/(rgb.b-rgb.g);
				else if(rgb.r>=rgb.b && rgb.b>=rgb.g) hsb.h = 300 + 60*(rgb.r-rgb.b)/(rgb.r-rgb.g);
				else hsb.h = 0;
				hsb.h = Math.round(hsb.h);
				return hsb;
			},
			HSBToRGB = function (hsb) {
				var rgb = {};
				var h = Math.round(hsb.h);
				var s = Math.round(hsb.s*255/100);
				var v = Math.round(hsb.b*255/100);
				if(s == 0) {
					rgb.r = rgb.g = rgb.b = v;
				} else {
					var t1 = v;
					var t2 = (255-s)*v/255;
					var t3 = (t1-t2)*(h%60)/60;
					if(h==360) h = 0;
					if(h<60) {rgb.r=t1;	rgb.b=t2; rgb.g=t2+t3}
					else if(h<120) {rgb.g=t1; rgb.b=t2;	rgb.r=t1-t3}
					else if(h<180) {rgb.g=t1; rgb.r=t2;	rgb.b=t2+t3}
					else if(h<240) {rgb.b=t1; rgb.r=t2;	rgb.g=t1-t3}
					else if(h<300) {rgb.b=t1; rgb.g=t2;	rgb.r=t2+t3}
					else if(h<360) {rgb.r=t1; rgb.g=t2;	rgb.b=t1-t3}
					else {rgb.r=0; rgb.g=0;	rgb.b=0}
				}
				return {r:Math.round(rgb.r), g:Math.round(rgb.g), b:Math.round(rgb.b)};
			},
			RGBToHex = function (rgb) {
				var hex = [
					rgb.r.toString(16),
					rgb.g.toString(16),
					rgb.b.toString(16)
				];
				$.each(hex, function (nr, val) {
					if (val.length == 1) {
						hex[nr] = '0' + val;
					}
				});
				return hex.join('');
			},
			HSBToHex = function (hsb) {
				return RGBToHex(HSBToRGB(hsb));
			};
		return {
			init: function (options) {
				options = $.extend({}, defaults, options||{});
				if (typeof options.color == 'string') {
					options.color = HexToHSB(options.color);
				} else if (options.color.r != undefined && options.color.g != undefined && options.color.b != undefined) {
					options.color = RGBToHSB(options.color);
				} else if (options.color.h != undefined && options.color.s != undefined && options.color.b != undefined) {
					options.color = fixHSB(options.color);
				} else {
					return this;
				}
				options.origColor = options.color;
				return this.each(function () {
					if (!$(this).data('colorpickerId')) {
						var id = 'collorpicker_' + parseInt(Math.random() * 1000);
						$(this).data('colorpickerId', id);
						var cal = $(tpl).attr('id', id);
						if (options.flat) {
							cal.appendTo(this).show();
						} else {
							cal.appendTo(document.body);
						}
						options.fields = cal
											.find('input')
												.bind('keydown', keyDown)
												.bind('change', change)
												.bind('blur', blur)
												.bind('focus', focus);
						cal.find('span').bind('mousedown', downIncrement);
						options.selector = cal.find('div.colorpicker_color').bind('mousedown', downSelector);
						options.selectorIndic = options.selector.find('div div');
						options.hue = cal.find('div.colorpicker_hue div');
						cal.find('div.colorpicker_hue').bind('mousedown', downHue);
						options.newColor = cal.find('div.colorpicker_new_color');
						options.currentColor = cal.find('div.colorpicker_current_color');
						cal.data('colorpicker', options);
						cal.find('div.colorpicker_submit')
							.bind('mouseenter', enterSubmit)
							.bind('mouseleave', leaveSubmit)
							.bind('click', clickSubmit);
						fillRGBFields(options.color, cal.get(0));
						fillHSBFields(options.color, cal.get(0));
						fillHexFields(options.color, cal.get(0));
						setHue(options.color, cal.get(0));
						setSelector(options.color, cal.get(0));
						setCurrentColor(options.color, cal.get(0));
						setNewColor(options.color, cal.get(0));
						if (options.flat) {
							cal.css({
								position: 'relative',
								display: 'block'
							});
						} else {
							$(this).bind(options.eventName, show);
						}
					}
				});
			},
			showPicker: function() {
				return this.each( function () {
					if ($(this).data('colorpickerId')) {
						show.apply(this);
					}
				});
			},
			hidePicker: function() {
				return this.each( function () {
					if ($(this).data('colorpickerId')) {
						$('#' + $(this).data('colorpickerId')).hide();
					}
				});
			},
			setColor: function(col) {
				if (typeof col == 'string') {
					col = HexToHSB(col);
				} else if (col.r != undefined && col.g != undefined && col.b != undefined) {
					col = RGBToHSB(col);
				} else if (col.h != undefined && col.s != undefined && col.b != undefined) {
					col = fixHSB(col);
				} else {
					return this;
				}
				return this.each(function(){
					if ($(this).data('colorpickerId')) {
						var cal = $('#' + $(this).data('colorpickerId'));
						cal.data('colorpicker').color = col;
						cal.data('colorpicker').origColor = col;
						fillRGBFields(col, cal.get(0));
						fillHSBFields(col, cal.get(0));
						fillHexFields(col, cal.get(0));
						setHue(col, cal.get(0));
						setSelector(col, cal.get(0));
						setCurrentColor(col, cal.get(0));
						setNewColor(col, cal.get(0));
					}
				});
			}
		};
	}();
	$.fn.extend({
		ColorPicker: ColorPicker.init,
		ColorPickerHide: ColorPicker.hide,
		ColorPickerShow: ColorPicker.show,
		ColorPickerSetColor: ColorPicker.setColor
	});
})(jQuery);

/**
 *
 * Zoomimage
 * Author: Stefan Petre www.eyecon.ro
 *
 */
(function($){
	var EYE = window.EYE = function() {
		var _registered = {
			init: []
		};
		return {
			init: function() {
				$.each(_registered.init, function(nr, fn){
					fn.call();
				});
			},
			extend: function(prop) {
				for (var i in prop) {
					if (prop[i] != undefined) {
						this[i] = prop[i];
					}
				}
			},
			register: function(fn, type) {
				if (!_registered[type]) {
					_registered[type] = [];
				}
				_registered[type].push(fn);
			}
		};
	}();
	$(EYE.init);
})(jQuery);

/**
 *
 * Utilities
 * Author: Stefan Petre www.eyecon.ro
 *
 */
(function($) {
EYE.extend({
	getPosition : function(e, forceIt)
	{
		var x = 0;
		var y = 0;
		var es = e.style;
		var restoreStyles = false;
		if (forceIt && jQuery.curCSS(e,'display') == 'none') {
			var oldVisibility = es.visibility;
			var oldPosition = es.position;
			restoreStyles = true;
			es.visibility = 'hidden';
			es.display = 'block';
			es.position = 'absolute';
		}
		var el = e;
		if (el.getBoundingClientRect) { // IE
			var box = el.getBoundingClientRect();
			x = box.left + Math.max(document.documentElement.scrollLeft, document.body.scrollLeft) - 2;
			y = box.top + Math.max(document.documentElement.scrollTop, document.body.scrollTop) - 2;
		} else {
			x = el.offsetLeft;
			y = el.offsetTop;
			el = el.offsetParent;
			if (e != el) {
				while (el) {
					x += el.offsetLeft;
					y += el.offsetTop;
					el = el.offsetParent;
				}
			}
			if (jQuery.browser.safari && jQuery.curCSS(e, 'position') == 'absolute' ) {
				x -= document.body.offsetLeft;
				y -= document.body.offsetTop;
			}
			el = e.parentNode;
			while (el && el.tagName.toUpperCase() != 'BODY' && el.tagName.toUpperCase() != 'HTML')
			{
				if (jQuery.curCSS(el, 'display') != 'inline') {
					x -= el.scrollLeft;
					y -= el.scrollTop;
				}
				el = el.parentNode;
			}
		}
		if (restoreStyles == true) {
			es.display = 'none';
			es.position = oldPosition;
			es.visibility = oldVisibility;
		}
		return {x:x, y:y};
	},
	getSize : function(e)
	{
		var w = parseInt(jQuery.curCSS(e,'width'), 10);
		var h = parseInt(jQuery.curCSS(e,'height'), 10);
		var wb = 0;
		var hb = 0;
		if (jQuery.curCSS(e, 'display') != 'none') {
			wb = e.offsetWidth;
			hb = e.offsetHeight;
		} else {
			var es = e.style;
			var oldVisibility = es.visibility;
			var oldPosition = es.position;
			es.visibility = 'hidden';
			es.display = 'block';
			es.position = 'absolute';
			wb = e.offsetWidth;
			hb = e.offsetHeight;
			es.display = 'none';
			es.position = oldPosition;
			es.visibility = oldVisibility;
		}
		return {w:w, h:h, wb:wb, hb:hb};
	},
	getClient : function(e)
	{
		var h, w;
		if (e) {
			w = e.clientWidth;
			h = e.clientHeight;
		} else {
			var de = document.documentElement;
			w = window.innerWidth || self.innerWidth || (de&&de.clientWidth) || document.body.clientWidth;
			h = window.innerHeight || self.innerHeight || (de&&de.clientHeight) || document.body.clientHeight;
		}
		return {w:w,h:h};
	},
	getScroll : function (e)
	{
		var t=0, l=0, w=0, h=0, iw=0, ih=0;
		if (e && e.nodeName.toLowerCase() != 'body') {
			t = e.scrollTop;
			l = e.scrollLeft;
			w = e.scrollWidth;
			h = e.scrollHeight;
		} else  {
			if (document.documentElement) {
				t = document.documentElement.scrollTop;
				l = document.documentElement.scrollLeft;
				w = document.documentElement.scrollWidth;
				h = document.documentElement.scrollHeight;
			} else if (document.body) {
				t = document.body.scrollTop;
				l = document.body.scrollLeft;
				w = document.body.scrollWidth;
				h = document.body.scrollHeight;
			}
			if (typeof pageYOffset != 'undefined') {
				t = pageYOffset;
				l = pageXOffset;
			}
			iw = self.innerWidth||document.documentElement.clientWidth||document.body.clientWidth||0;
			ih = self.innerHeight||document.documentElement.clientHeight||document.body.clientHeight||0;
		}
		return { t: t, l: l, w: w, h: h, iw: iw, ih: ih };
	},
	getMargins : function(e, toInteger)
	{
		var t = jQuery.curCSS(e,'marginTop') || '';
		var r = jQuery.curCSS(e,'marginRight') || '';
		var b = jQuery.curCSS(e,'marginBottom') || '';
		var l = jQuery.curCSS(e,'marginLeft') || '';
		if (toInteger)
			return {
				t: parseInt(t, 10)||0,
				r: parseInt(r, 10)||0,
				b: parseInt(b, 10)||0,
				l: parseInt(l, 10)
			};
		else
			return {t: t, r: r,	b: b, l: l};
	},
	getPadding : function(e, toInteger)
	{
		var t = jQuery.curCSS(e,'paddingTop') || '';
		var r = jQuery.curCSS(e,'paddingRight') || '';
		var b = jQuery.curCSS(e,'paddingBottom') || '';
		var l = jQuery.curCSS(e,'paddingLeft') || '';
		if (toInteger)
			return {
				t: parseInt(t, 10)||0,
				r: parseInt(r, 10)||0,
				b: parseInt(b, 10)||0,
				l: parseInt(l, 10)
			};
		else
			return {t: t, r: r,	b: b, l: l};
	},
	getBorder : function(e, toInteger)
	{
		var t = jQuery.curCSS(e,'borderTopWidth') || '';
		var r = jQuery.curCSS(e,'borderRightWidth') || '';
		var b = jQuery.curCSS(e,'borderBottomWidth') || '';
		var l = jQuery.curCSS(e,'borderLeftWidth') || '';
		if (toInteger)
			return {
				t: parseInt(t, 10)||0,
				r: parseInt(r, 10)||0,
				b: parseInt(b, 10)||0,
				l: parseInt(l, 10)||0
			};
		else
			return {t: t, r: r,	b: b, l: l};
	},
	traverseDOM : function(nodeEl, func)
	{
		func(nodeEl);
		nodeEl = nodeEl.firstChild;
		while(nodeEl){
			EYE.traverseDOM(nodeEl, func);
			nodeEl = nodeEl.nextSibling;
		}
	},
	getInnerWidth :  function(el, scroll) {
		var offsetW = el.offsetWidth;
		return scroll ? Math.max(el.scrollWidth,offsetW) - offsetW + el.clientWidth:el.clientWidth;
	},
	getInnerHeight : function(el, scroll) {
		var offsetH = el.offsetHeight;
		return scroll ? Math.max(el.scrollHeight,offsetH) - offsetH + el.clientHeight:el.clientHeight;
	},
	getExtraWidth : function(el) {
		if($.boxModel)
			return (parseInt($.curCSS(el, 'paddingLeft'))||0)
				+ (parseInt($.curCSS(el, 'paddingRight'))||0)
				+ (parseInt($.curCSS(el, 'borderLeftWidth'))||0)
				+ (parseInt($.curCSS(el, 'borderRightWidth'))||0);
		return 0;
	},
	getExtraHeight : function(el) {
		if($.boxModel)
			return (parseInt($.curCSS(el, 'paddingTop'))||0)
				+ (parseInt($.curCSS(el, 'paddingBottom'))||0)
				+ (parseInt($.curCSS(el, 'borderTopWidth'))||0)
				+ (parseInt($.curCSS(el, 'borderBottomWidth'))||0);
		return 0;
	},
	isChildOf: function(parentEl, el, container) {
		if (parentEl == el) {
			return true;
		}
		if (!el || !el.nodeType || el.nodeType != 1) {
			return false;
		}
		if (parentEl.contains && !$.browser.safari) {
			return parentEl.contains(el);
		}
		if ( parentEl.compareDocumentPosition ) {
			return !!(parentEl.compareDocumentPosition(el) & 16);
		}
		var prEl = el.parentNode;
		while(prEl && prEl != container) {
			if (prEl == parentEl)
				return true;
			prEl = prEl.parentNode;
		}
		return false;
	},
	centerEl : function(el, axis)
	{
		var clientScroll = EYE.getScroll();
		var size = EYE.getSize(el);
		if (!axis || axis == 'vertically')
			$(el).css(
				{
					top: clientScroll.t + ((Math.min(clientScroll.h,clientScroll.ih) - size.hb)/2) + 'px'
				}
			);
		if (!axis || axis == 'horizontally')
			$(el).css(
				{
					left: clientScroll.l + ((Math.min(clientScroll.w,clientScroll.iw) - size.wb)/2) + 'px'
				}
			);
	}
});

if (!$.easing.easeout) {
	$.easing.easeout = function(p, n, firstNum, delta, duration) {
		return -delta * ((n=n/duration-1)*n*n*n - 1) + firstNum;
	};
}

})(jQuery);

var userAgent = navigator.userAgent.toLowerCase();
$.os = {
    mac: /mac/.test(userAgent),
    win: /win/.test(userAgent),
    linux: /linux/.test(userAgent)
}

/**
 * Cookie plugin
 *
 * Copyright (c) 2006 Klaus Hartl (stilbuero.de)
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 *
 */

/**
 * Create a cookie with the given name and value and other optional parameters.
 *
 * @example $.cookie('the_cookie', 'the_value');
 * @desc Set the value of a cookie.
 * @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
 * @desc Create a cookie with all available options.
 * @example $.cookie('the_cookie', 'the_value');
 * @desc Create a session cookie.
 * @example $.cookie('the_cookie', null);
 * @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
 *       used when the cookie was set.
 *
 * @param String name The name of the cookie.
 * @param String value The value of the cookie.
 * @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
 * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
 *                             If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
 *                             If set to null or omitted, the cookie will be a session cookie and will not be retained
 *                             when the the browser exits.
 * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
 * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
 * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
 *                        require a secure protocol (like HTTPS).
 * @type undefined
 *
 * @name $.cookie
 * @cat Plugins/Cookie
 * @author Klaus Hartl/klaus.hartl@stilbuero.de
 */

/**
 * Get the value of a cookie with the given name.
 *
 * @example $.cookie('the_cookie');
 * @desc Get the value of a cookie.
 *
 * @param String name The name of the cookie.
 * @return The value of the cookie.
 * @type String
 *
 * @name $.cookie
 * @cat Plugins/Cookie
 * @author Klaus Hartl/klaus.hartl@stilbuero.de
 */
jQuery.cookie = function(name, value, options) {
    if (typeof value != 'undefined') { // name and value given, set cookie
        options = options || {};
        if (value === null) {
            value = '';
            options.expires = -1;
        }
        var expires = '';
        if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
            var date;
            if (typeof options.expires == 'number') {
                date = new Date();
                date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
            } else {
                date = options.expires;
            }
            expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
        }
        // CAUTION: Needed to parenthesize options.path and options.domain
        // in the following expressions, otherwise they evaluate to undefined
        // in the packed version for some reason...
        var path = options.path ? '; path=' + (options.path) : '';
        var domain = options.domain ? '; domain=' + (options.domain) : '';
        var secure = options.secure ? '; secure' : '';
        document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
    } else { // only name given, get cookie
        var cookieValue = null;
        if (document.cookie && document.cookie != '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = jQuery.trim(cookies[i]);
                // Does this cookie string begin with the name we want?
                if (cookie.substring(0, name.length + 1) == (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }
};
