/*
 * jQuery UI Accordion 1.8
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Accordion
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.widget.js
 */
(function($) {

    $.widget("ui.reverse_accordion", {
	options: {
	    active: 0,
	    animated: 'slide',
	    autoHeight: true,
	    clearStyle: false,
	    collapsible: false,
	    event: "click",
	    fillSpace: true,
	    header: "> li > :first-child,> :not(li):even",
	    icons: {
		header: "ui-icon-triangle-1-e",
		headerSelected: "ui-icon-triangle-1-s"
	    },
	    navigation: false,
	    navigationFilter: function() {
		return this.href.toLowerCase() == location.href.toLowerCase();
	    }
	},
	_create: function() {

	    var o = this.options, self = this;
	    this.running = 0;

	    this.element.addClass("ui-accordion ui-widget ui-helper-reset");

	    // in lack of child-selectors in CSS we need to mark top-LIs in a UL-accordion for some IE-fix
	    if (this.element[0].nodeName == "UL") {
		this.element.children("li").addClass("ui-accordion-li-fix");
	    }

	    this.headers = this.element.find(o.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all")
	    .bind("mouseenter.accordion", function(){
		$(this).addClass('ui-state-hover');
	    })
	    .bind("mouseleave.accordion", function(){
		$(this).removeClass('ui-state-hover');
	    })
	    .bind("focus.accordion", function(){
		$(this).addClass('ui-state-focus');
	    })
	    .bind("blur.accordion", function(){
		$(this).removeClass('ui-state-focus');
	    });

	    this.headers
	    .prev()
	    .addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom");

	    if ( o.navigation ) {
		var current = this.element.find("a").filter(o.navigationFilter);
		if ( current.length ) {
		    var header = current.closest(".ui-accordion-header");
		    if ( header.length ) {
			// anchor within header
			this.active = header;
		    } else {
			// anchor within content
			this.active = current.closest(".ui-accordion-content").prev();
		    }
		}
	    }

	    this.active = this._findActive(this.active || o.active).toggleClass("ui-state-default").toggleClass("ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top");
	    this.active.prev().addClass('ui-accordion-content-active');

	    //Append icon elements
	    //this._createIcons();

	    // IE7-/Win - Extra vertical space in lists fixed
	    if ($.browser.msie) {
		this.element.find('a').css('zoom', '1');
	    }

	    this.resize();

	    //ARIA
	    this.element.attr('role','tablist');

	    this.headers
	    .attr('role','tab')
	    .bind('keydown', function(event) {
		return self._keydown(event);
	    })
	    .prev()
	    .attr('role','tabpanel');

	    this.headers
	    .not(this.active || "")
	    .attr('aria-expanded','false')
	    .attr("tabIndex", "-1")
	    .prev()
	    .hide();

	    // make sure at least one header is in the tab order
	    if (!this.active.length) {
		this.headers.eq(0).attr('tabIndex','0');
	    } else {
		this.active
		.attr('aria-expanded','true')
		.attr('tabIndex', '0');
	    }

	    // only need links in taborder for Safari
	    if (!$.browser.safari)
		this.headers.find('a').attr('tabIndex','-1');

	    if (o.event) {
		this.headers.bind((o.event) + ".accordion", function(event) {
		    self._clickHandler.call(self, event, this);
		    event.preventDefault();
		});
	    }

	},

	_createIcons: function() {
	    var o = this.options;
	    if (o.icons) {
		$("<span/>").addClass("ui-icon " + o.icons.header).prependTo(this.headers);
		this.active.find(".ui-icon").toggleClass(o.icons.header).toggleClass(o.icons.headerSelected);
		this.element.addClass("ui-accordion-icons");
	    }
	},

	_destroyIcons: function() {
	    this.headers.children(".ui-icon").remove();
	    this.element.removeClass("ui-accordion-icons");
	},

	destroy: function() {
	    var o = this.options;

	    this.element
	    .removeClass("ui-accordion ui-widget ui-helper-reset")
	    .removeAttr("role")
	    .unbind('.accordion')
	    .removeData('accordion');

	    this.headers
	    .unbind(".accordion")
	    .removeClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-corner-top")
	    .removeAttr("role").removeAttr("aria-expanded").removeAttr("tabindex");

	    this.headers.find("a").removeAttr("tabindex");
	    this._destroyIcons();
	    var contents = this.headers.prev().css("display", "").removeAttr("role").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active");
	    if (o.autoHeight || o.fillHeight) {
		contents.css("height", "");
	    }

	    return this;
	},

	_setOption: function(key, value) {
	    $.Widget.prototype._setOption.apply(this, arguments);

	    if (key == "active") {
		this.activate(value);
	    }
	    if (key == "icons") {
		this._destroyIcons();
		if (value) {
		    this._createIcons();
		}
	    }

	},

	_keydown: function(event) {

	    var o = this.options, keyCode = $.ui.keyCode;

	    if (o.disabled || event.altKey || event.ctrlKey)
		return;

	    var length = this.headers.length;
	    var currentIndex = this.headers.index(event.target);
	    var toFocus = false;

	    switch(event.keyCode) {
		case keyCode.RIGHT:
		case keyCode.DOWN:
		    toFocus = this.headers[(currentIndex + 1) % length];
		    break;
		case keyCode.LEFT:
		case keyCode.UP:
		    toFocus = this.headers[(currentIndex - 1 + length) % length];
		    break;
		case keyCode.SPACE:
		case keyCode.ENTER:
		    this._clickHandler({
			target: event.target
		    }, event.target);
		    event.preventDefault();
	    }

	    if (toFocus) {
		$(event.target).attr('tabIndex','-1');
		$(toFocus).attr('tabIndex','0');
		toFocus.focus();
		return false;
	    }

	    return true;

	},

	resize: function() {

	    var o = this.options, maxHeight;

	    if (o.fillSpace) {

		if($.browser.msie) {
		    var defOverflow = this.element.parent().css('overflow');
		    this.element.parent().css('overflow', 'hidden');
		}
		maxHeight = this.element.parent().height();
		if($.browser.msie) {
		    this.element.parent().css('overflow', defOverflow);
		}

		this.headers.each(function() {
		    maxHeight -= $(this).outerHeight(true);
		});

		this.headers.next().each(function() {
		    $(this).height(Math.max(0, maxHeight - $(this).innerHeight() + $(this).height()));
		}).css('overflow', 'auto');

	    } else if ( o.autoHeight ) {
		maxHeight = 0;
		this.headers.prev().each(function() {
		    maxHeight = Math.max(maxHeight, $(this).height());
		}).height(maxHeight);
	    }

	    return this;
	},

	activate: function(index) {
	    // TODO this gets called on init, changing the option without an explicit call for that
	    this.options.active = index;
	    // call clickHandler with custom event
	    var active = this._findActive(index)[0];
	    this._clickHandler({
		target: active
	    }, active);

	    return this;
	},

	_findActive: function(selector) {
	    return selector
	    ? typeof selector == "number"
	    ? this.headers.filter(":eq(" + selector + ")")
	    : this.headers.not(this.headers.not(selector))
	    : selector === false
	    ? $([])
	    : this.headers.filter(":eq(0)");
	},

	// TODO isn't event.target enough? why the seperate target argument?
	_clickHandler: function(event, target) {

	    var o = this.options;
	    if (o.disabled)
		return;

	    // called only when using activate(false) to close all parts programmatically
	    if (!event.target) {
		if (!o.collapsible)
		    return;
		this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all")
		.find(".ui-icon").removeClass(o.icons.headerSelected).addClass(o.icons.header);
		this.active.next().addClass('ui-accordion-content-active');
		var toHide = this.active.next(),
		data = {
		    options: o,
		    newHeader: $([]),
		    oldHeader: o.active,
		    newContent: $([]),
		    oldContent: toHide
		},
		toShow = (this.active = $([]));
		this._toggle(toShow, toHide, data);
		return;
	    }

	    // get the click target
	    var clicked = $(event.currentTarget || target);
	    var clickedIsActive = clicked[0] == this.active[0];

	    // TODO the option is changed, is that correct?
	    // TODO if it is correct, shouldn't that happen after determining that the click is valid?
	    o.active = o.collapsible && clickedIsActive ? false : $('.ui-accordion-header', this.element).index(clicked);

	    // if animations are still active, or the active header is the target, ignore click
	    if (this.running || (!o.collapsible && clickedIsActive)) {
		return;
	    }

	    // switch classes
	    this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all")
	    .find(".ui-icon").removeClass(o.icons.headerSelected).addClass(o.icons.header);
	    //this.active.prev().addClass('ui-accordion-content-active');
	    if (!clickedIsActive) {
		clicked.removeClass("ui-state-default ui-corner-all").addClass("ui-state-active ui-corner-top")
		.find(".ui-icon").removeClass(o.icons.header).addClass(o.icons.headerSelected);
		clicked.prev().addClass('ui-accordion-content-active');
	    }

	    // find elements to show and hide
	    var toShow = clicked.prev(),
	    toHide = this.active.prev(),
	    data = {
		options: o,
		newHeader: clickedIsActive && o.collapsible ? $([]) : clicked,
		oldHeader: this.active,
		newContent: clickedIsActive && o.collapsible ? $([]) : toShow,
		oldContent: toHide
	    },
	    down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] );

	    this.active = clickedIsActive ? $([]) : clicked;
	    this._toggle(toShow, toHide, data, clickedIsActive, down);

	    return;

	},

	_toggle: function(toShow, toHide, data, clickedIsActive, down) {
	    var o = this.options, self = this;

	    this.toShow = toShow;
	    this.toHide = toHide;
	    this.data = data;

	    var complete = function() {
		if(!self) return;
		return self._completed.apply(self, arguments);
	    };

	    // trigger changestart event
	    this._trigger("changestart", null, this.data);

	    // count elements to animate
	    this.running = toHide.size() === 0 ? toShow.size() : toHide.size();

	    if (o.animated) {

		var animOptions = {};

		if ( o.collapsible && clickedIsActive ) {
		    animOptions = {
			toShow: $([]),
			toHide: toHide,
			complete: complete,
			down: down,
			autoHeight: o.autoHeight || o.fillSpace
		    };
		} else {
		    animOptions = {
			toShow: toShow,
			toHide: toHide,
			complete: complete,
			down: down,
			autoHeight: o.autoHeight || o.fillSpace
		    };
		}

		if (!o.proxied) {
		    o.proxied = o.animated;
		}

		if (!o.proxiedDuration) {
		    o.proxiedDuration = o.duration;
		}

		o.animated = $.isFunction(o.proxied) ?
		o.proxied(animOptions) : o.proxied;

		o.duration = $.isFunction(o.proxiedDuration) ?
		o.proxiedDuration(animOptions) : o.proxiedDuration;

		var animations = $.ui.reverse_accordion.animations,
		duration = o.duration,
		easing = o.animated;

		if (easing && !animations[easing] && !$.easing[easing]) {
		    easing = 'slide';
		}
		if (!animations[easing]) {
		    animations[easing] = function(options) {
			this.slide(options, {
			    easing: easing,
			    duration: duration || 700
			});
		    };
		}

		animations[easing](animOptions);

	    } else {

		if (o.collapsible && clickedIsActive) {
		    toShow.toggle();
		} else {
		    toHide.hide();
		    toShow.show();
		}

		complete(true);

	    }

	    toHide.prev().attr('aria-expanded','false').attr("tabIndex", "-1").blur();
	//toShow.prev().attr('aria-expanded','true').attr("tabIndex", "0").focus();

	},

	_completed: function(cancel) {

	    var o = this.options;

	    this.running = cancel ? 0 : --this.running;
	    if (this.running) return;

	    if (o.clearStyle) {
		this.toShow.add(this.toHide).css({
		    height: "",
		    overflow: ""
		});
	    }

	    // other classes are removed before the animation; this one needs to stay until completed
	    this.toHide.removeClass("ui-accordion-content-active");

	    this._trigger('change', null, this.data);
	}

    });


    $.extend($.ui.reverse_accordion, {
	version: "1.8",
	animations: {
	    slide: function(options, additions) {

		options = $.extend({
		    easing: "swing",
		    duration: 300
		}, options, additions);
		if ( !options.toHide.size() ) {
		    options.toShow.animate({
			height: "show"
		    }, options);
		    return;
		}
		if ( !options.toShow.size() ) {
		    options.toHide.animate({
			height: "hide"
		    }, options);
		    return;
		}
		var overflow = options.toShow.css('overflow'),
		percentDone = 0,
		showProps = {},
		hideProps = {},
		fxAttrs = [ "height", "paddingTop", "paddingBottom" ],
		originalWidth;
		// fix width before calculating height of hidden element
		var s = options.toShow;
		originalWidth = s[0].style.width;
		s.width( parseInt(s.parent().width(),10) - parseInt(s.css("paddingLeft"),10) - parseInt(s.css("paddingRight"),10) - (parseInt(s.css("borderLeftWidth"),10) || 0) - (parseInt(s.css("borderRightWidth"),10) || 0) );

		$.each(fxAttrs, function(i, prop) {
		    hideProps[prop] = 'hide';

		    var parts = ('' + $.css(options.toShow[0], prop)).match(/^([\d+-.]+)(.*)$/);
		    showProps[prop] = {
			value: parts[1],
			unit: parts[2] || 'px'
		    };
		});
		options.toShow.css({
		    height: 0,
		    overflow: 'hidden'
		}).show();
		options.toHide.filter(":hidden").each(options.complete).end().filter(":visible").animate(hideProps,{
		    step: function(now, settings) {
			// only calculate the percent when animating height
			// IE gets very inconsistent results when animating elements
			// with small values, which is common for padding
			if (settings.prop == 'height') {
			    percentDone = ( settings.end - settings.start === 0 ) ? 0 :
			    (settings.now - settings.start) / (settings.end - settings.start);
			}

			options.toShow[0].style[settings.prop] =
			(percentDone * showProps[settings.prop].value) + showProps[settings.prop].unit;
		    },
		    duration: options.duration,
		    easing: options.easing,
		    complete: function() {
			if ( !options.autoHeight ) {
			    options.toShow.css("height", "");
			}
			options.toShow.css("width", originalWidth);
			options.toShow.css({
			    overflow: overflow
			});
			options.complete();
		    }
		});
	    },
	    bounceslide: function(options) {
		this.slide(options, {
		    easing: options.down ? "easeOutBounce" : "swing",
		    duration: options.down ? 1000 : 200
		});
	    },
	    easeslide: function(options) {
		this.slide(options, {
		    easing: "easeinout",
		    duration: 700
		});
	    }
	}
    });

})(jQuery);



var jQueryAccordion = {
    init: function() {
	jQuery(document).ready(function() {
	    jQuery(".jquery-accordion").accordion({
		header: '.toggler',
		event: 'mouseover',
		selectedClass: 'bottom_active',
		changestart: function(event, ui) {
		    ui.newContent.parent().next().addClass('close_active');
		    ui.newContent.parent().addClass('bottom_active');
		    ui.oldContent.parent().next().removeClass('close_active');
		    ui.oldContent.parent().removeClass('bottom_active');
		},

		change: function(event, ui) {

		}
	    });
	    jQuery(".jquery-accordion").find(".close:first").addClass('close_active');
	    jQuery(".jquery-accordion").find(".bottom:first").addClass('bottom_active');
	});
    }
}

var jQuerySupportAccordion = {
    init: function() {
	jQuery(document).ready(function() {
	    jQuery(".jquery-support-accordion").reverse_accordion({
		active: null,
		alwaysOpen: true, //deprecated, use collapsible
		animated: 'slide',
		autoHeight: true,
		clearStyle: false,
		collapsible: false,
		fillSpace: false,
		navigation: false,
		navigationFilter: function() {
		    return this.href.toLowerCase() == location.href.toLowerCase();
		},
		header: '.toggler',
		event: 'mouseover',
		selectedClass: 'bottom_active',
		changestart: function(event, ui) {
		    ui.newContent.parent().parent().find('.close').addClass('close_active');
		    ui.newContent.parent().parent().find('.bottom').addClass('bottom_active');
		    ui.oldContent.parent().parent().find('.close').removeClass('close_active');
		    ui.oldContent.parent().parent().find('.bottom').removeClass('bottom_active');
		},

		change: function(event, ui) {

		}
	    });
	    jQuery(".jquery-support-accordion").find(".close:first").addClass('close_active');
	    jQuery(".jquery-support-accordion").find(".bottom:first").addClass('bottom_active');
	});

    }
}