/*
 * Accordion - jQuery widget
 *
 * Copyright (c) 2006 Jörn Zaefferer, Frank Marcia
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 */

// el nextUntil es necesario, sería bueno tener esto en el centro del jQuery
jQuery.fn.nextUntil = function(expr) {
    var match = [];

    // Nosotros necesitamos figurar fuera que los elementos para empujar hacia la serie
    this.each(function(){
        // El travesaño a través del nodos del hermano
        for( var i = this.nextSibling; i; i = i.nextSibling ) {
            // Asegúrese que nosotros sólo estamos tratándonos de los elementos
            if ( i.nodeType != 1 ) continue;

            // Si nosotros encontramos un fósforo que nosotros necesitamos detener entonces
            if ( jQuery.filter( expr, [i] ).r.length ) break;

            // Por otra parte, añádalo a la pila
            match.push( i );
        }
    });

    return this.pushStack( match, arguments );
}; 

/**  
 * Haga los widgets de Acordeón de elementos seleccionados.  
 *´  
 * Los requisitos semánticos:  
 *   
 * Si la estructura de su recipiente es llena con único  
 * las etiquetas para el título y los elementos satisfechos, eg. una lista de la definición  
 * (el dl> el dt + el dd), usted no tiene que especificar cualquier opción a  
 * todos.  
 *  
 * Si su estructura usa los mismos elementos para el título y  
 * satisfecho o usa algún amable de estructura anidada, usted tiene a   
 * especifique los elementos del título, el eg. vía la clase, vea el segundo ejemplo.  
 *  
 * Use el activate(Number) para cambiar el volumen activo programáticamente.  
 *  
 * @example $(' #list1 ') .Accordion ();  
 * @before <el id del dl = "list1"><dt>Header 1><dd>Content 1 </dd> [...] </dl>  
 * @desc Creates un Acordeón de la lista de la definición dada  
 *  
 * @example $(' #list2 ') .Accordion ({  
 * el título: ' div.title'  
 *});  
 * @before <el id del div = "los nav"><div><div clasifican = "title">Header 1><div>Content 1 </div></div> [...] </div>  
 * @desc Creates un Acordeón de la estructura del div dada  
 *  
 * @example $(' #nav ') .Accordion ({  
 * el título: ' a.head'  
 *});  
 * @before <el id del ul = "nav">  
 * <el li>  
 * <una clase = "head">Header 1>  
 * <el ul>  
 * <el href del li><a =" #" >Link 1 </a></li>  
 * <el href del li><a =" #" >Link 2></a></li>  
 * </ul>  
 * </li>  
 * [...]  
 * </ul>  
 * @desc Crea un Acordeón de la lista de la navegación dada  
 *  
 * @example $(' #accordion ') .Accordion () .change(function(event, el newHeader, el oldHeader, el newContent, el oldContent) {  
 * $(' #status ') .html(newHeader.text ());  
 *});  
 * @desc Updates el elemento de #status con el texto del título seleccionado cada vez los cambios del acordeón  
 *  
 * @param Object que el key/value de las escenas aparea de escenas optativas.  
 * @option String|Element|jQuery|Boolean el Seleccionador activo para el elemento activo, el valor por defecto es el primer niño, puesto a falso no desplegar ninguno a la salida,  
 * @option String|Element|jQuery director Selector para el elemento del título, eg. div.title, a.head, el valor por defecto es el tagname del primer niño  
 * @option que los showSpeed de String|Number Aceleran para el slideIn, el valor por defecto es ' el slow'  
 * @option que los hideSpeed de String|Number Aceleran para el slideOut, el valor por defecto es ' el fast'  
 * @option String que los selectedClass Clasifican para los elementos del título activos, el valor por defecto es ' el selected'  
 *  
 * El cambio de @event Llamado everytime que el acordeón cambia, el params,: el evento, el newHeader, el oldHeader, el newContent, el oldContent,  
 *  
 * El jQuery de @type  
 *  
 * El activate(Number de @see)  
 *  
 * El Acordeón de @name  
 * @cat Plugin/Accordion  
 * @author Jörn Zaefferer (http://bassistance.de)  
 */  
   
/**  
 * Active una parte satisfecha del Acordeón programáticamente con la posición el índice cero-basado.  
 *  
 * Si el índice no se especifica, predefine para poner a cero, si es un índice inválido, el eg. un cordón,  
 * nada pasa.  
 *  
 * Requiere los jQuery quitan el corazón la revisión >= 557.  
 *  
 * @example $(' #accordion ') .activate(1);  
 * @desc Activate el segundo satisfecho del Acordeón contenido en <el id del div = "acordeón">.  
 * @example $(' #nav ') .activate ();  
 * @desc Activate el primero satisfecho del Acordeón contenido en <el id del ul = "nav">.  
 *  
 * @param Number el índice Un Entero que especifica el índice cero-basado del volumen para ser  
 * activó. Los valores por defecto a 0.  
 * El jQuery de @type  
 *  
 * @name activan  
 * @cat Plugins/Accordion  
 * @author Jörn Zaefferer (http://bassistance.de)  
 */
 
// cree el alcance privado con $alias para el jQuery
(function($) {
	// ahorre la referencia al método del plugin
	var plugin = $.fn.Accordion = function(settings) {
		
		// la configuración del arreglo  
		// TODO: permita los argumentos múltiples para extenderse, vea bicho #344
		settings = $.extend($.extend({}, arguments.callee.defaults), $.extend({
			// defina los valores por defecto del contexto
			header: $(':first-child', this)[0].tagName // tome primero que los childs etiquetan el Nombre como el título
		}, settings || {}));
		
		// calcule activo si no especificó, mientras usando el primer título
		var container = this,
			active = settings.active ? $(settings.active, this) : settings.active === false ? $("<div>") : $(settings.header, this).eq(0),
			running = 0;
		
		$(settings.header, container)
			.not(active && active[0] || "")
			.nextUntil(settings.header)
			.hide();
		active.addClass(settings.selectedClass);
		
		var clickHandler = function(event) {
			// consiga el blanco del clic
			var clicked = $(event.target);
			// si las animaciones todavía son activas, o el título activo es el blanco, ignore el clic
			if(running || clicked[0] == active[0] || !clicked.is(settings.header))
				return;
			
			// las clases del interruptor
			active.removeClass(settings.selectedClass);
			clicked.addClass(settings.selectedClass);
			
			// encuentre los elementos para mostrar y esconder
			var toShow = $(clicked).nextUntil(settings.header),
				toHide = $(active).nextUntil(settings.header),
				data = [clicked, active, toShow, toHide];
			active = clicked;
			// cuente los elementos para animar
			running = toHide.size() + toShow.size();
			var finished = function() {
				if(--running)
					return;
				// mantenga la altura flexible
				toHide.css({height: ''});
				toShow.css({height: ''});
				
				// active el evento de cambio de costumbre
				container.trigger("change", data);
			};
			// TODO si el hideSpeed se pone para poner a cero, las animaciones son los crappy  
			// el workaround: use la piel en cambio  
			// la solución: animado debe verificar para la velocidad de 0 y debe hacer algo sobre él
			toHide.slideUp(settings.hideSpeed, finished);
			toShow.slideDown(settings.showSpeed, finished);
			
			if(event.preventDefault)
				event.preventDefault();
		};
		var activateHandlder = function(event, index) {
			// llame el clickHandler con el evento de la costumbre
			clickHandler({
				target: $(settings.header, this)[index]
			});
		};
	
		return container
			.bind("click", clickHandler)
			.bind("activate", activateHandlder);
	};
	// defina los valores por defecto estáticos
	plugin.defaults = {
		selectedClass: "selected",
		showSpeed: 'slow',
		hideSpeed: 'fast'
	};
	
	// el atajo para el gatillo, el API mejor y fácilmente para documentar
	$.fn.activate = function(index) {
		//devuelva this.trigger (' el activate', [el índice || 0]);
	};
	
})(jQuery);
