/*
 * This file has been commented to support Visual Studio Intellisense.
 * You should not use this file at runtime inside the browser--it is only
 * intended to be used only for design-time IntelliSense.  Please use the
 * standard jQuery library for all production use.
 *
 * Comment version: 1.4.1a
 */

/*!
 * jQuery JavaScript Library v1.4.1
 * http://jquery.com/
 *
 * Distributed in whole under the terms of the MIT
 *
 * Copyright 2010, John Resig
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * Includes Sizzle.js
 * http://sizzlejs.com/
 * Copyright 2010, The Dojo Foundation
 * Released under the MIT, BSD, and GPL Licenses.
 *
 * Date: Mon Jan 25 19:43:33 2010 -0500
 */

(function( window, undefined ) {

// Define a local copy of jQuery
var jQuery = function( selector, context ) {
		///	<summary>
		///		1: $(expression, context): esta función acepta una cadena que contiene un selector CSS usado para buscar coincidencias de un conjunto de elementos.
		///		2: $(html): crea elementos DOM sobre la marcha a partir de la cadena de HTML puro proporcionada.
		///		3: $(elements): encapsula la funcionalidad de jQuery en torno a uno o varios elementos DOM.
		///		4: $(callback): método abreviado de $(document).ready().
		///		5: $() - A partir de jQuery 1.4, si no pasa argumentos al método jQuery(), se devuelve un conjunto jQuery vacío.
		///	</summary>
		///	<param name="selector" type="String">
		///		1: expression - An expression to search with.
		///		2: html: cadena de HTML que se crea sobre la marcha.
		///		3: elements: elementos DOM que va a encapsular un objeto jQuery.
		///		4: callback: función que se ejecuta cuando el DOM está listo.
		///	</param>
		///	<param name="context" type="jQuery">
		///		1: contexto: elemento DOM, documento o jQuery que se usa como contexto.
		///	</param>
		///	<returns type="jQuery" />

		// The jQuery object is actually just the init constructor 'enhanced'
		return new jQuery.fn.init( selector, context );
	},

	// Map over jQuery in case of overwrite
	_jQuery = window.jQuery,

	// Map over the $ in case of overwrite
	_$ = window.$,

	// Use the correct document accordingly with window argument (sandbox)
	document = window.document,

	// A central reference to the root jQuery(document)
	rootjQuery,

	// A simple way to check for HTML strings or ID strings
	// (both of which we optimize for)
	quickExpr = /^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,

	// Is it a simple selector
	isSimple = /^.[^:#\[\.,]*$/,

	// Check if a string has a non-whitespace character in it
	rnotwhite = /\S/,

	// Used for trimming whitespace
	rtrim = /^(\s|\u00A0)+|(\s|\u00A0)+$/g,

	// Match a standalone tag
	rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,

	// Keep a UserAgent string for use with jQuery.browser
	userAgent = navigator.userAgent,

	// For matching the engine and version of the browser
	browserMatch,
	
	// Has the ready events already been bound?
	readyBound = false,
	
	// The functions to execute on DOM ready
	readyList = [],

	// The ready event handler
	DOMContentLoaded,

	// Save a reference to some core methods
	toString = Object.prototype.toString,
	hasOwnProperty = Object.prototype.hasOwnProperty,
	push = Array.prototype.push,
	slice = Array.prototype.slice,
	indexOf = Array.prototype.indexOf;

jQuery.fn = jQuery.prototype = {
	init: function( selector, context ) {

		var match, elem, ret, doc;

		// Handle $(""), $(null), or $(undefined)
		if ( !selector ) {
			return this;
		}

		// Handle $(DOMElement)
		if ( selector.nodeType ) {
			this.context = this[0] = selector;
			this.length = 1;
			return this;
		}

		// Handle HTML strings
		if ( typeof selector === "string" ) {
			// Are we dealing with HTML string or an ID?
			match = quickExpr.exec( selector );

			// Verify a match, and that no context was specified for #id
			if ( match && (match[1] || !context) ) {

				// HANDLE: $(html) -> $(array)
				if ( match[1] ) {
					doc = (context ? context.ownerDocument || context : document);

					// If a single string is passed in and it's a single tag
					// just do a createElement and skip the rest
					ret = rsingleTag.exec( selector );

					if ( ret ) {
						if ( jQuery.isPlainObject( context ) ) {
							selector = [ document.createElement( ret[1] ) ];
							jQuery.fn.attr.call( selector, context, true );

						} else {
							selector = [ doc.createElement( ret[1] ) ];
						}

					} else {
						ret = buildFragment( [ match[1] ], [ doc ] );
						selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes;
					}

				// HANDLE: $("#id")
				} else {
					elem = document.getElementById( match[2] );

					if ( elem ) {
						// Handle the case where IE and Opera return items
						// by name instead of ID
						if ( elem.id !== match[2] ) {
							return rootjQuery.find( selector );
						}

						// Otherwise, we inject the element directly into the jQuery object
						this.length = 1;
						this[0] = elem;
					}

					this.context = document;
					this.selector = selector;
					return this;
				}

			// HANDLE: $("TAG")
			} else if ( !context && /^\w+$/.test( selector ) ) {
				this.selector = selector;
				this.context = document;
				selector = document.getElementsByTagName( selector );

			// HANDLE: $(expr, $(...))
			} else if ( !context || context.jquery ) {
				return (context || rootjQuery).find( selector );

			// HANDLE: $(expr, context)
			// (which is just equivalent to: $(context).find(expr)
			} else {
				return jQuery( context ).find( selector );
			}

		// HANDLE: $(function)
		// Shortcut for document ready
		} else if ( jQuery.isFunction( selector ) ) {
			return rootjQuery.ready( selector );
		}

		if (selector.selector !== undefined) {
			this.selector = selector.selector;
			this.context = selector.context;
		}

		return jQuery.isArray( selector ) ?
			this.setArray( selector ) :
			jQuery.makeArray( selector, this );
	},

	// Start with an empty selector
	selector: "",

	// The current version of jQuery being used
	jquery: "1.4.1",

	// The default length of a jQuery object is 0
	length: 0,

	// The number of elements contained in the matched element set
	size: function() {
		///	<summary>
		///		Número de elementos que coinciden actualmente.
		///		Parte del núcleo
		///	</summary>
		///	<returns type="Number" />

		return this.length;
	},

	toArray: function() {
		///	<summary>
		///		Recuperar todos los elementos DOM contenidos en el conjunto jQuery, como una matriz.
		///	</summary>
		///	<returns type="Array" />
		return slice.call( this, 0 );
	},

	// Get the Nth element in the matched element set OR
	// Get the whole matched element set as a clean array
	get: function( num ) {
		///	<summary>
		///		El acceso a un único número de elemento coincidente sirve para tener acceso al
		///		elemento n coincidente.
		///		Parte del núcleo
		///	</summary>
		///	<returns type="Element" />
		///	<param name="num" type="Number">
		///		Tener acceso al elemento en la posición n.
		///	</param>

		return num == null ?

			// Return a 'clean' array
			this.toArray() :

			// Return just the object
			( num < 0 ? this.slice(num)[ 0 ] : this[ num ] );
	},

	// Take an array of elements and push it onto the stack
	// (returning the new matched element set)
	pushStack: function( elems, name, selector ) {
		///	<summary>
		///		Establecer el objeto jQuery en una matriz de elementos y, al mismo tiempo, mantener
		///		la pila.
		///		Parte del núcleo
		///	</summary>
		///	<returns type="jQuery" />
		///	<param name="elems" type="Elements">
		///		Matriz de elementos
		///	</param>

		// Build a new jQuery matched element set
		var ret = jQuery( elems || null );

		// Add the old object onto the stack (as a reference)
		ret.prevObject = this;

		ret.context = this.context;

		if ( name === "find" ) {
			ret.selector = this.selector + (this.selector ? " " : "") + selector;
		} else if ( name ) {
			ret.selector = this.selector + "." + name + "(" + selector + ")";
		}

		// Return the newly-formed element set
		return ret;
	},

	// Force the current matched set of elements to become
	// the specified array of elements (destroying the stack in the process)
	// You should use pushStack() in order to do this, but maintain the stack
	setArray: function( elems ) {
		///	<summary>
		///		Establecer el objeto jQuery en una matriz de elementos. Esta operación es
		///		completamente destructiva: asegúrese de usar .pushStack() si desea mantener
		///		la pila de jQuery.
		///		Parte del núcleo
		///	</summary>
		///	<returns type="jQuery" />
		///	<param name="elems" type="Elements">
		///		Matriz de elementos
		///	</param>

		// Resetting the length to 0, then using the native Array push
		// is a super-fast way to populate an object with array-like properties
		this.length = 0;
		push.apply( this, elems );

		return this;
	},

	// Execute a callback for every element in the matched set.
	// (You can seed the arguments with an array of args, but this is
	// only used internally.)
	each: function( callback, args ) {
		///	<summary>
		///		Ejecutar una función en el contento de cada elemento coincidente.
		///		Esto significa que cada vez que se ejecuta la función pasada
		///		(una vez para cada elemento coincidente), la palabra clave "this"
		///		apunta al elemento específico.
		///		Asimismo, la función, cuando se ejecuta, toma un único
		///		argumento que representa la posición del elemento en el conjunto de
		///		elementos coincidentes.
		///		Parte del núcleo
		///	</summary>
		///	<returns type="jQuery" />
		///	<param name="callback" type="Function">
		///		Función que se va a ejecutar
		///	</param>

		return jQuery.each( this, callback, args );
	},
	
	ready: function( fn ) {
		///	<summary>
		///		Enlaza una función que se ejecuta cuando el DOM está preparado para ser atravesado y manipulado.
		///	</summary>
		///	<param name="fn" type="Function">La función que se ejecuta cuando el DOM está preparado.</param>

		// Attach the listeners
		jQuery.bindReady();

		// If the DOM is already ready
		if ( jQuery.isReady ) {
			// Execute the function immediately
			fn.call( document, jQuery );

		// Otherwise, remember the function for later
		} else if ( readyList ) {
			// Add the function to the wait list
			readyList.push( fn );
		}

		return this;
	},
	
	eq: function( i ) {
		///	<summary>
		///		Reducir el conjunto de elementos coincidentes a un único elemento.
		///		Posición del elemento en el conjunto de elementos coincidentes
		///		empieza en 0 y llega hasta la longitud - 1.
		///		Parte del núcleo
		///	</summary>
		///	<returns type="jQuery" />
		///	<param name="num" type="Number">
		///		pos Índice del elemento en el que se desea establecer el límite.
		///	</param>

		return i === -1 ?
			this.slice( i ) :
			this.slice( i, +i + 1 );
	},

	first: function() {
		///	<summary>
		///		Reducir el conjunto de elementos coincidentes al primero del conjunto.
		///	</summary>
		///	<returns type="jQuery" />

		return this.eq( 0 );
	},

	last: function() {
		///	<summary>
		///		Reducir el conjunto de elementos coincidentes al último del conjunto.
		///	</summary>
		///	<returns type="jQuery" />

		return this.eq( -1 );
	},

	slice: function() {
		///	<summary>
		///		Selecciona un subconjunto de elementos coincidentes. Se comporta exactamente igual que el método de segmentación de matriz integrado.
		///	</summary>
		///	<param name="start" type="Number" integer="true">Lugar en el que comienza el subconjunto (en base 0).</param>
		///	<param name="end" optional="true" type="Number" integer="true">Lugar en el que termina el subconjunto (sin incluir al propio elemento de finalización).
		///		Si se omite, termina al final de la selección</param>
		///	<returns type="jQuery">Elementos segmentados</returns>

		return this.pushStack( slice.apply( this, arguments ),
			"slice", slice.call(arguments).join(",") );
	},

	map: function( callback ) {
		///	<summary>
		///		Este miembro es interno.
		///	</summary>
		///	<private />
		///	<returns type="jQuery" />

		return this.pushStack( jQuery.map(this, function( elem, i ) {
			return callback.call( elem, i, elem );
		}));
	},
	
	end: function() {
		///	<summary>
		///		Terminar la última operación "destructiva", lo que revierte la lista de elementos coincidentes
		///		a su estado anterior. Después de una operación de terminación, la lista de elementos coincidentes se
		///		revertirá al último estado que tenían dichos elementos.
		///		Si no se produjo previamente ninguna operación destructiva, se devuelve un conjunto vacío.
		///		Parte de DOM/Traversing
		///	</summary>
		///	<returns type="jQuery" />

		return this.prevObject || jQuery(null);
	},

	// Solo para uso interno.
	// Se comporta como un método de matriz y no como un método de jQuery.
	push: push,
	sort: [].sort,
	splice: [].splice
};

// Asignar la función init al prototipo de jQuery para crear posteriormente una instancia
jQuery.fn.init.prototype = jQuery.fn;

jQuery.extend = jQuery.fn.extend = function() {
	///	<summary>
	///		Extiende un objeto con uno o varios objetos y devuelve el objeto
	///		original modificado. Esto es muy útil para la herencia simple.
	///		jQuery.extend(settings, options);
	///		var settings = jQuery.extend({}, defaults, options);
	///		Parte de JavaScript
	///	</summary>
	///	<param name="target" type="Object">
	///		 Objeto que se va a extender
	///	</param>
	///	<param name="prop1" type="Object">
	///		 Objeto que se combinará en el primero.
	///	</param>
	///	<param name="propN" type="Object" optional="true" parameterArray="true">
	///		 (opcional) Otros objetos que se van a combinar en el primero
	///	</param>
	///	<returns type="Object" />

	// copy reference to target object
	var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options, name, src, copy;

	// Handle a deep copy situation
	if ( typeof target === "boolean" ) {
		deep = target;
		target = arguments[1] || {};
		// skip the boolean and the target
		i = 2;
	}

	// Handle case when target is a string or something (possible in deep copy)
	if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
		target = {};
	}

	// extend jQuery itself if only one argument is passed
	if ( length === i ) {
		target = this;
		--i;
	}

	for ( ; i < length; i++ ) {
		// Only deal with non-null/undefined values
		if ( (options = arguments[ i ]) != null ) {
			// Extend the base object
			for ( name in options ) {
				src = target[ name ];
				copy = options[ name ];

				// Prevent never-ending loop
				if ( target === copy ) {
					continue;
				}

				// Recurse if we're merging object literal values or arrays
				if ( deep && copy && ( jQuery.isPlainObject(copy) || jQuery.isArray(copy) ) ) {
					var clone = src && ( jQuery.isPlainObject(src) || jQuery.isArray(src) ) ? src
						: jQuery.isArray(copy) ? [] : {};

					// Never move original objects, clone them
					target[ name ] = jQuery.extend( deep, clone, copy );

				// Don't bring in undefined values
				} else if ( copy !== undefined ) {
					target[ name ] = copy;
				}
			}
		}
	}

	// Return the modified object
	return target;
};

jQuery.extend({
	noConflict: function( deep ) {
		///	<summary>
		///		Ejecutar esta función para devolver el control de la variable $
		///		a la biblioteca que la implementó, cualquiera que sea. Esto sirve para asegurarnos 
		///		de que jQuery no entra en conflicto con el objeto $
		///		de otras bibliotecas.
		///		Mediante esta función, solo tenemos acceso a jQuery
		///		a través de la variable 'jQuery'. Por ejemplo, donde se solía usar
		///		$(&quot;div p&quot;), ahora se debe usar jQuery(&quot;div p&quot;).
		///		Parte del núcleo 
		///	</summary>
		///	<returns type="undefined" />

		window.$ = _$;

		if ( deep ) {
			window.jQuery = _jQuery;
		}

		return jQuery;
	},
	
	// ¿Está DOM listo para usarlo? Establecer en true una vez que tenga lugar.
	isReady: false,
	
	// Controlar cuándo el DOM está preparado
	ready: function() {
		///	<summary>
		///		Este método es interno.
		///	</summary>
		///	<private />

		// Make sure that the DOM is not already loaded
		if ( !jQuery.isReady ) {
			// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
			if ( !document.body ) {
				return setTimeout( jQuery.ready, 13 );
			}

			// Remember that the DOM is ready
			jQuery.isReady = true;

			// If there are functions bound, to execute
			if ( readyList ) {
				// Execute all of them
				var fn, i = 0;
				while ( (fn = readyList[ i++ ]) ) {
					fn.call( document, jQuery );
				}

				// Reset the list of functions
				readyList = null;
			}

			// Trigger any bound ready events
			if ( jQuery.fn.triggerHandler ) {
				jQuery( document ).triggerHandler( "ready" );
			}
		}
	},
	
	bindReady: function() {
		if ( readyBound ) {
			return;
		}

		readyBound = true;

		// Catch cases where $(document).ready() is called after the
		// browser event has already occurred.
		if ( document.readyState === "complete" ) {
			return jQuery.ready();
		}

		// Mozilla, Opera and webkit nightlies currently support this event
		if ( document.addEventListener ) {
			// Use the handy event callback
			document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
			
			// A fallback to window.onload, that will always work
			window.addEventListener( "load", jQuery.ready, false );

		// If IE event model is used
		} else if ( document.attachEvent ) {
			// ensure firing before onload,
			// maybe late but safe also for iframes
			document.attachEvent("onreadystatechange", DOMContentLoaded);
			
			// A fallback to window.onload, that will always work
			window.attachEvent( "onload", jQuery.ready );

			// If IE and not a frame
			// continually check to see if the document is ready
			var toplevel = false;

			try {
				toplevel = window.frameElement == null;
			} catch(e) {}

			if ( document.documentElement.doScroll && toplevel ) {
				doScrollCheck();
			}
		}
	},

	// See test/unit/core.js for details concerning isFunction.
	// Since version 1.3, DOM methods and functions like alert
	// aren't supported. They return false on IE (#2968).
	isFunction: function( obj ) {
		///	<summary>
		///		Determina si el parámetro pasado es una función.
		///	</summary>
		///	<param name="obj" type="Object">Objeto que se va a comprobar</param>
		///	<returns type="Boolean">Devuelve True si el parámetro es una función; de lo contrario, devuelve false.</returns>

		return toString.call(obj) === "[object Function]";
	},

	isArray: function( obj ) {
		///	<summary>
		///		Determinar si el parámetro pasado es una matriz.
		///	</summary>
		///	<param name="obj" type="Object">Objeto del que se va a determinar si es una matriz o no.</param>
		///	<returns type="Boolean">Devuelve True si el parámetro es una función; de lo contrario, devuelve false.</returns>

		return toString.call(obj) === "[object Array]";
	},

	isPlainObject: function( obj ) {
		///	<summary>
		///		Comprobar si el objeto es un objeto simple (creado con "{}" o "new Object").
		///	</summary>
		///	<param name="obj" type="Object">
		///		Objeto que se comprobará para ver si es un objeto simple.
		///	</param>
		///	<returns type="Boolean" />

		// Must be an Object.
		// Because of IE, we also have to check the presence of the constructor property.
		// Make sure that DOM nodes and window objects don't pass through, as well
		if ( !obj || toString.call(obj) !== "[object Object]" || obj.nodeType || obj.setInterval ) {
			return false;
		}
		
		// Not own constructor property must be Object
		if ( obj.constructor
			&& !hasOwnProperty.call(obj, "constructor")
			&& !hasOwnProperty.call(obj.constructor.prototype, "isPrototypeOf") ) {
			return false;
		}
		
		// Own properties are enumerated firstly, so to speed up,
		// if last one is own, then all properties are own.
	
		var key;
		for ( key in obj ) {}
		
		return key === undefined || hasOwnProperty.call( obj, key );
	},

	isEmptyObject: function( obj ) {
		///	<summary>
		///		Comprobar si un objeto está vacío (no contiene propiedades).
		///	</summary>
		///	<param name="obj" type="Object">
		///		Objeto que se comprobará para ver si está vacío.
		///	</param>
		///	<returns type="Boolean" />

		for ( var name in obj ) {
			return false;
		}
		return true;
	},
	
	error: function( msg ) {
		throw msg;
	},
	
	parseJSON: function( data ) {
		if ( typeof data !== "string" || !data ) {
			return null;
		}
		
		// Make sure the incoming data is actual JSON
		// Logic borrowed from http://json.org/json2.js
		if ( /^[\],:{}\s]*$/.test(data.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, "@")
			.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, "]")
			.replace(/(?:^|:|,)(?:\s*\[)+/g, "")) ) {

			// Try to use the native JSON parser first
			return window.JSON && window.JSON.parse ?
				window.JSON.parse( data ) :
				(new Function("return " + data))();

		} else {
			jQuery.error( "Invalid JSON: " + data );
		}
	},

	noop: function() {
		///	<summary>
		///		Función vacía.
		///	</summary>
		///	<returns type="Function" />
	},

	// Evalúa un script en un contexto global
	globalEval: function( data ) {
		///	<summary>
		///		Evalúa internamente un script en un contexto global.
		///	</summary>
		///	<private />

		if ( data && rnotwhite.test(data) ) {
			// Inspired by code by Andrea Giammarchi
			// http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
			var head = document.getElementsByTagName("head")[0] || document.documentElement,
				script = document.createElement("script");

			script.type = "text/javascript";

			if ( jQuery.support.scriptEval ) {
				script.appendChild( document.createTextNode( data ) );
			} else {
				script.text = data;
			}

			// Use insertBefore instead of appendChild to circumvent an IE6 bug.
			// This arises when a base node is used (#2709).
			head.insertBefore( script, head.firstChild );
			head.removeChild( script );
		}
	},

	nodeName: function( elem, name ) {
		///	<summary>
		///		Comprueba si el elemento especificado tiene el nombre de nodo de DOM especificado.
		///	</summary>
		///	<param name="elem" type="Element">Elemento que se va a examinar</param>
		///	<param name="name" type="String">Nombre de nodo que se va a comprobar</param>
		///	<returns type="Boolean">Devuelve true si el nombre de nodo especificado coincide con el nombre DOM del nodo; de lo contrario, devuelve false</returns>

		return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
	},

	// args is for internal usage only
	each: function( object, callback, args ) {
		///	<summary>
		///		Función de iterador genérica que se puede usar para recorrer en iteración
		///		objetos y matrices. Esta función no es la misma que
		///		$().each(), que se usa exclusivamente para recorrer en iteración un objeto
		///		jQuery. Esta función se puede usar para recorrer en iteración cualquier elemento.
		///		La devolución de llamada tiene dos argumentos: la clave (objetos) o índice (matrices) es el primero
		///		y el valor es el segundo.
		///		Parte de JavaScript
		///	</summary>
		///	<param name="obj" type="Object">
		///		 Objeto o matriz que se va a recorrer en iteración.
		///	</param>
		///	<param name="fn" type="Function">
		///		 Función que se va a ejecutar en cada objeto.
		///	</param>
		///	<returns type="Object" />

		var name, i = 0,
			length = object.length,
			isObj = length === undefined || jQuery.isFunction(object);

		if ( args ) {
			if ( isObj ) {
				for ( name in object ) {
					if ( callback.apply( object[ name ], args ) === false ) {
						break;
					}
				}
			} else {
				for ( ; i < length; ) {
					if ( callback.apply( object[ i++ ], args ) === false ) {
						break;
					}
				}
			}

		// A special, fast, case for the most common use of each
		} else {
			if ( isObj ) {
				for ( name in object ) {
					if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
						break;
					}
				}
			} else {
				for ( var value = object[0];
					i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {}
			}
		}

		return object;
	},

	trim: function( text ) {
		///	<summary>
		///		Quitar el espacio en blanco del principio y el final de una cadena.
		///		Parte de JavaScript
		///	</summary>
		///	<returns type="String" />
		///	<param name="text" type="String">
		///		Cadena que se va a recortar.
		///	</param>

		return (text || "").replace( rtrim, "" );
	},

	// results is for internal usage only
	makeArray: function( array, results ) {
		///	<summary>
		///		Devuelve cualquier elemento en una matriz verdadera. Es un método interno.
		///	</summary>
		///	<param name="array" type="Object">Elemento que se va a convertir en una matriz real</param>
		///	<returns type="Array" />
		///	<private />

		var ret = results || [];

		if ( array != null ) {
			// The window, strings (and functions) also have 'length'
			// The extra typeof function check is to prevent crashes
			// in Safari 2 (See: #3039)
			if ( array.length == null || typeof array === "string" || jQuery.isFunction(array) || (typeof array !== "function" && array.setInterval) ) {
				push.call( ret, array );
			} else {
				jQuery.merge( ret, array );
			}
		}

		return ret;
	},

	inArray: function( elem, array ) {
		if ( array.indexOf ) {
			return array.indexOf( elem );
		}

		for ( var i = 0, length = array.length; i < length; i++ ) {
			if ( array[ i ] === elem ) {
				return i;
			}
		}

		return -1;
	},

	merge: function( first, second ) {
		///	<summary>
		///		Combinar dos matrices y quitar todos los duplicados.
		///		La nueva matriz está formada por todos los resultados de la primera matriz seguidos de
		///		los resultados distintos de la segunda matriz.
		///		Parte de JavaScript
		///	</summary>
		///	<returns type="Array" />
		///	<param name="first" type="Array">
		///		 Primera matriz que se va a combinar.
		///	</param>
		///	<param name="second" type="Array">
		///		 Segunda matriz que se va a combinar.
		///	</param>

		var i = first.length, j = 0;

		if ( typeof second.length === "number" ) {
			for ( var l = second.length; j < l; j++ ) {
				first[ i++ ] = second[ j ];
			}
		} else {
			while ( second[j] !== undefined ) {
				first[ i++ ] = second[ j++ ];
			}
		}

		first.length = i;

		return first;
	},

	grep: function( elems, callback, inv ) {
		///	<summary>
		///		Filtrar los elementos de una matriz mediante una función de filtro.
		///		La función especificada pasará dos argumentos: el
		///		elemento de matriz actual y el índice del elemento de la matriz. La
		///		función debe devolver 'true' para mantener el elemento en la matriz 
		///		y false para quitarlo.
		///		});
		///		Parte de JavaScript
		///	</summary>
		///	<returns type="Array" />
		///	<param name="elems" type="Array">
		///		matriz La matriz en la que se van a buscar elementos.
		///	</param>
		///	<param name="fn" type="Function">
		///		 Función que se procesa en cada elemento.
		///	</param>
		///	<param name="inv" type="Boolean">
		///		 Invertir la selección: seleccionar el opuesto de la función.
		///	</param>

		var ret = [];

		// Go through the array, only saving the items
		// that pass the validator function
		for ( var i = 0, length = elems.length; i < length; i++ ) {
			if ( !inv !== !callback( elems[ i ], i ) ) {
				ret.push( elems[ i ] );
			}
		}

		return ret;
	},

	// arg is for internal usage only
	map: function( elems, callback, arg ) {
		///	<summary>
		///		Convertir todos los elementos de una matriz en otra matriz de elementos.
		///		La función de conversión proporcionada a este método se 
		///		llama para cada elemento de la matriz y se le pasa un argumento: 
		///		Elemento que se va a convertir.
		///		La función puede devolver entonces el valor convertido, 'null'
		///		(para quitar el elemento) o una matriz de valores, que se acoplarán
		///		en la matriz completa.
		///		Parte de JavaScript
		///	</summary>
		///	<returns type="Array" />
		///	<param name="elems" type="Array">
		///		matriz La matriz que se va a convertir.
		///	</param>
		///	<param name="fn" type="Function">
		///		 Función que se procesa en cada elemento.
		///	</param>

		var ret = [], value;

		// Atravesar la matriz y convertir cada elemento en su
		// nuevo valor o valores.
		for ( var i = 0, length = elems.length; i < length; i++ ) {
			value = callback( elems[ i ], i, arg );

			if ( value != null ) {
				ret[ ret.length ] = value;
			}
		}

		return ret.concat.apply( [], ret );
	},

	// Contador de GUID global para objetos
	guid: 1,

	proxy: function( fn, proxy, thisObject ) {
		///	<summary>
		///		Toma una función y devuelve una nueva que tendrá siempre un ámbito particular.
		///	</summary>
		///	<param name="fn" type="Function">
		///		Función cuyo ámbito se cambiará.
		///	</param>
		///	<param name="proxy" type="Object">
		///		Objeto en el que se debe establecer el ámbito de la función.
		///	</param>
		///	<returns type="Function" />

		if ( arguments.length === 2 ) {
			if ( typeof proxy === "string" ) {
				thisObject = fn;
				fn = thisObject[ proxy ];
				proxy = undefined;

			} else if ( proxy && !jQuery.isFunction( proxy ) ) {
				thisObject = proxy;
				proxy = undefined;
			}
		}

		if ( !proxy && fn ) {
			proxy = function() {
				return fn.apply( thisObject || this, arguments );
			};
		}

		// Set the guid of unique handler to the same of original handler, so it can be removed
		if ( fn ) {
			proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
		}

		// So proxy can be declared as an argument
		return proxy;
	},

	// Use of jQuery.browser is frowned upon.
	// More details: http://docs.jquery.com/Utilities/jQuery.browser
	uaMatch: function( ua ) {
		ua = ua.toLowerCase();

		var match = /(webkit)[ \/]([\w.]+)/.exec( ua ) ||
			/(opera)(?:.*version)?[ \/]([\w.]+)/.exec( ua ) ||
			/(msie) ([\w.]+)/.exec( ua ) ||
			!/compatible/.test( ua ) && /(mozilla)(?:.*? rv:([\w.]+))?/.exec( ua ) ||
		  	[];

		return { browser: match[1] || "", version: match[2] || "0" };
	},

	browser: {}
});

browserMatch = jQuery.uaMatch( userAgent );
if ( browserMatch.browser ) {
	jQuery.browser[ browserMatch.browser ] = true;
	jQuery.browser.version = browserMatch.version;
}

// Deprecated, use jQuery.browser.webkit instead
if ( jQuery.browser.webkit ) {
	jQuery.browser.safari = true;
}

if ( indexOf ) {
	jQuery.inArray = function( elem, array ) {
		///	<summary>
		///		Determina el índice del primer parámetro de la matriz.
		///	</summary>
		///	<param name="elem">Valor cuya existencia en la matriz se va a comprobar.</param>
		///	<param name="array" type="Array">Matriz que se va a examinar para buscar el valor</param>
		///	<returns type="Number" integer="true">Índice de base 0 del elemento si se encuentra; de lo contrario, -1.</returns>

		return indexOf.call( array, elem );
	};
}

// All jQuery objects should point back to these
rootjQuery = jQuery(document);

// Cleanup functions for the document ready method
if ( document.addEventListener ) {
	DOMContentLoaded = function() {
		document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
		jQuery.ready();
	};

} else if ( document.attachEvent ) {
	DOMContentLoaded = function() {
		// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
		if ( document.readyState === "complete" ) {
			document.detachEvent( "onreadystatechange", DOMContentLoaded );
			jQuery.ready();
		}
	};
}

// The DOM ready check for Internet Explorer
function doScrollCheck() {
	if ( jQuery.isReady ) {
		return;
	}

	try {
		// If IE is used, use the trick by Diego Perini
		// http://javascript.nwbox.com/IEContentLoaded/
		document.documentElement.doScroll("left");
	} catch( error ) {
		setTimeout( doScrollCheck, 1 );
		return;
	}

	// and execute any waiting functions
	jQuery.ready();
}

function evalScript( i, elem ) {
	///	<summary>
	///		Este método es interno.
	///	</summary>
	/// <private />

	if ( elem.src ) {
		jQuery.ajax({
			url: elem.src,
			async: false,
			dataType: "script"
		});
	} else {
		jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
	}

	if ( elem.parentNode ) {
		elem.parentNode.removeChild( elem );
	}
}

// Mutifunctional method to get and set values to a collection
// The value/s can be optionally by executed if its a function
function access( elems, key, value, exec, fn, pass ) {
	var length = elems.length;
	
	// Setting many attributes
	if ( typeof key === "object" ) {
		for ( var k in key ) {
			access( elems, k, key[k], exec, fn, value );
		}
		return elems;
	}
	
	// Setting one attribute
	if ( value !== undefined ) {
		// Optionally, function values get executed if exec is true
		exec = !pass && exec && jQuery.isFunction(value);
		
		for ( var i = 0; i < length; i++ ) {
			fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
		}
		
		return elems;
	}
	
	// Getting an attribute
	return length ? fn( elems[0], key ) : null;
}

function now() {
	///	<summary>
	///		Obtiene la fecha actual.
	///	</summary>
	///	<returns type="Date">La fecha actual.</returns>

	return (new Date).getTime();
}

// [vsdoc] The following function has been modified for IntelliSense.
// [vsdoc] Stubbing support properties to "false" for IntelliSense compat.
(function() {

	jQuery.support = {};

	//	var root = document.documentElement,
	//		script = document.createElement("script"),
	//		div = document.createElement("div"),
	//		id = "script" + now();

	//	div.style.display = "none";
	//	div.innerHTML = "   <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";

	//	var all = div.getElementsByTagName("*"),
	//		a = div.getElementsByTagName("a")[0];

	//	// Can't get basic test support
	//	if ( !all || !all.length || !a ) {
	//		return;
	//	}

	jQuery.support = {
		// IE strips leading whitespace when .innerHTML is used
		leadingWhitespace: false,

		// Make sure that tbody elements aren't automatically inserted
		// IE will insert them into empty tables
		tbody: false,

		// Make sure that link elements get serialized correctly by innerHTML
		// This requires a wrapper element in IE
		htmlSerialize: false,

		// Get the style information from getAttribute
		// (IE uses .cssText insted)
		style: false,

		// Make sure that URLs aren't manipulated
		// (IE normalizes it by default)
		hrefNormalized: false,

		// Make sure that element opacity exists
		// (IE uses filter instead)
		// Use a regex to work around a WebKit issue. See #5145
		opacity: false,

		// Verify style float existence
		// (IE uses styleFloat instead of cssFloat)
		cssFloat: false,

		// Make sure that if no value is specified for a checkbox
		// that it defaults to "on".
		// (WebKit defaults to "" instead)
		checkOn: false,

		// Make sure that a selected-by-default option has a working selected property.
		// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
		optSelected: false,

		// Will be defined later
		checkClone: false,
		scriptEval: false,
		noCloneEvent: false,
		boxModel: false
	};

	//	script.type = "text/javascript";
	//	try {
	//		script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
	//	} catch(e) {}

	//	root.insertBefore( script, root.firstChild );

	//	// Make sure that the execution of code works by injecting a script
	//	// tag with appendChild/createTextNode
	//	// (IE doesn't support this, fails, and uses .text instead)
	//	if ( window[ id ] ) {
	//		jQuery.support.scriptEval = true;
	//		delete window[ id ];
	//	}

	//	root.removeChild( script );

	//	if ( div.attachEvent && div.fireEvent ) {
	//		div.attachEvent("onclick", function click() {
	//			// Cloning a node shouldn't copy over any
	//			// bound event handlers (IE does this)
	//			jQuery.support.noCloneEvent = false;
	//			div.detachEvent("onclick", click);
	//		});
	//		div.cloneNode(true).fireEvent("onclick");
	//	}

	//	div = document.createElement("div");
	//	div.innerHTML = "<input type='radio' name='radiotest' checked='checked'/>";

	//	var fragment = document.createDocumentFragment();
	//	fragment.appendChild( div.firstChild );

	//	// WebKit doesn't clone checked state correctly in fragments
	//	jQuery.support.checkClone = fragment.cloneNode(true).cloneNode(true).lastChild.checked;

	//	// Figure out if the W3C box model works as expected
	//	// document.body must exist before we can do this
	//	jQuery(function() {
	//		var div = document.createElement("div");
	//		div.style.width = div.style.paddingLeft = "1px";

	//		document.body.appendChild( div );
	//		jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;
	//		document.body.removeChild( div ).style.display = 'none';
	//		div = null;
	//	});

	//	// Technique from Juriy Zaytsev
	//	// http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/
	//	var eventSupported = function( eventName ) { 
	//		var el = document.createElement("div"); 
	//		eventName = "on" + eventName; 

	//		var isSupported = (eventName in el); 
	//		if ( !isSupported ) { 
	//			el.setAttribute(eventName, "return;"); 
	//			isSupported = typeof el[eventName] === "function"; 
	//		} 
	//		el = null; 

	//		return isSupported; 
	//	};
	
	jQuery.support.submitBubbles = false;
	jQuery.support.changeBubbles = false;

	//	// release memory in IE
	//	root = script = div = all = a = null;
})();

jQuery.props = {
	"for": "htmlFor",
	"class": "className",
	readonly: "readOnly",
	maxlength: "maxLength",
	cellspacing: "cellSpacing",
	rowspan: "rowSpan",
	colspan: "colSpan",
	tabindex: "tabIndex",
	usemap: "useMap",
	frameborder: "frameBorder"
};
var expando = "jQuery" + now(), uuid = 0, windowData = {};
var emptyObject = {};

jQuery.extend({
	cache: {},
	
	expando:expando,

	// The following elements throw uncatchable exceptions if you
	// attempt to add expando properties to them.
	noData: {
		"embed": true,
		"object": true,
		"applet": true
	},

	data: function( elem, name, data ) {
		///	<summary>
		///		Almacenar datos arbitrarios asociados con el elemento especificado.
		///	</summary>
		///	<param name="elem" type="Element">
		///		Elemento DOM para asociar con los datos.
		///	</param>
		///	<param name="name" type="String">
		///		Cadena que da nombre a los datos que se van a establecer.
		///	</param>
		///	<param name="value" type="Object">
		///		Nuevo valor de datos.
		///	</param>
		///	<returns type="jQuery" />

		if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
			return;
		}

		elem = elem == window ?
			windowData :
			elem;

		var id = elem[ expando ], cache = jQuery.cache, thisCache;

		// Handle the case where there's no name immediately
		if ( !name && !id ) {
			return null;
		}

		// Compute a unique ID for the element
		if ( !id ) { 
			id = ++uuid;
		}

		// Avoid generating a new cache unless none exists and we
		// want to manipulate it.
		if ( typeof name === "object" ) {
			elem[ expando ] = id;
			thisCache = cache[ id ] = jQuery.extend(true, {}, name);
		} else if ( cache[ id ] ) {
			thisCache = cache[ id ];
		} else if ( typeof data === "undefined" ) {
			thisCache = emptyObject;
		} else {
			thisCache = cache[ id ] = {};
		}

		// Prevent overriding the named cache with undefined values
		if ( data !== undefined ) {
			elem[ expando ] = id;
			thisCache[ name ] = data;
		}

		return typeof name === "string" ? thisCache[ name ] : thisCache;
	},

	removeData: function( elem, name ) {
		if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
			return;
		}

		elem = elem == window ?
			windowData :
			elem;

		var id = elem[ expando ], cache = jQuery.cache, thisCache = cache[ id ];

		// If we want to remove a specific section of the element's data
		if ( name ) {
			if ( thisCache ) {
				// Remove the section of cache data
				delete thisCache[ name ];

				// If we've removed all the data, remove the element's cache
				if ( jQuery.isEmptyObject(thisCache) ) {
					jQuery.removeData( elem );
				}
			}

		// Otherwise, we want to remove all of the element's data
		} else {
			// Clean up the element expando
			try {
				delete elem[ expando ];
			} catch( e ) {
				// IE has trouble directly removing the expando
				// but it's ok with using removeAttribute
				if ( elem.removeAttribute ) {
					elem.removeAttribute( expando );
				}
			}

			// Completely remove the data cache
			delete cache[ id ];
		}
	}
});

jQuery.fn.extend({
	data: function( key, value ) {
		///	<summary>
		///		Almacenar los datos arbitrarios asociados con los elementos coincidentes.
		///	</summary>
		///	<param name="key" type="String">
		///		Cadena que da nombre a los datos que se van a establecer.
		///	</param>
		///	<param name="value" type="Object">
		///		Nuevo valor de datos.
		///	</param>
		///	<returns type="jQuery" />

		if ( typeof key === "undefined" && this.length ) {
			return jQuery.data( this[0] );

		} else if ( typeof key === "object" ) {
			return this.each(function() {
				jQuery.data( this, key );
			});
		}

		var parts = key.split(".");
		parts[1] = parts[1] ? "." + parts[1] : "";

		if ( value === undefined ) {
			var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);

			if ( data === undefined && this.length ) {
				data = jQuery.data( this[0], key );
			}
			return data === undefined && parts[1] ?
				this.data( parts[0] ) :
				data;
		} else {
			return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function() {
				jQuery.data( this, key, value );
			});
		}
	},

	removeData: function( key ) {
		return this.each(function() {
			jQuery.removeData( this, key );
		});
	}
});
jQuery.extend({
	queue: function( elem, type, data ) {
		if ( !elem ) {
			return;
		}

		type = (type || "fx") + "queue";
		var q = jQuery.data( elem, type );

		// Speed up dequeue by getting out quickly if this is just a lookup
		if ( !data ) {
			return q || [];
		}

		if ( !q || jQuery.isArray(data) ) {
			q = jQuery.data( elem, type, jQuery.makeArray(data) );

		} else {
			q.push( data );
		}

		return q;
	},

	dequeue: function( elem, type ) {
		type = type || "fx";

		var queue = jQuery.queue( elem, type ), fn = queue.shift();

		// If the fx queue is dequeued, always remove the progress sentinel
		if ( fn === "inprogress" ) {
			fn = queue.shift();
		}

		if ( fn ) {
			// Add a progress sentinel to prevent the fx queue from being
			// automatically dequeued
			if ( type === "fx" ) {
				queue.unshift("inprogress");
			}

			fn.call(elem, function() {
				jQuery.dequeue(elem, type);
			});
		}
	}
});

jQuery.fn.extend({
	queue: function( type, data ) {
		///	<summary>
		///		1: queue(): devuelve una referencia a la cola del primer elemento (que es una matriz de funciones).
		///		2: queue(callback): agrega una nueva función que se ejecuta al final de la cola de todos los elementos coincidentes.
		///		3: queue(queue): reemplaza la cola de todos los elementos coincidentes por la nueva cola (la matriz de funciones).
		///	</summary>
		///	<param name="type" type="Function">Función que se agrega a la cola.</param>
		///	<returns type="jQuery" />

		if ( typeof type !== "string" ) {
			data = type;
			type = "fx";
		}

		if ( data === undefined ) {
			return jQuery.queue( this[0], type );
		}
		return this.each(function( i, elem ) {
			var queue = jQuery.queue( this, type, data );

			if ( type === "fx" && queue[0] !== "inprogress" ) {
				jQuery.dequeue( this, type );
			}
		});
	},
	dequeue: function( type ) {
		///	<summary>
		///		Quita una función puesta en cola de delante de la cola y la ejecuta.
		///	</summary>
		///	<param name="type" type="String" optional="true">Tipo de cola a la que obtener acceso.</param>
		///	<returns type="jQuery" />

		return this.each(function() {
			jQuery.dequeue( this, type );
		});
	},

	// Based off of the plugin by Clint Helfers, with permission.
	// http://blindsignals.com/index.php/2009/07/jquery-delay/
	delay: function( time, type ) {
		///	<summary>
		///		Establecer un temporizador para retrasar la ejecución de los elementos siguientes en la cola.
		///	</summary>
		///	<param name="time" type="Number">
		///		Entero que indica el número de milisegundos para retrasar la ejecución del siguiente elemento de la cola.
		///	</param>
		///	<param name="type" type="String">
		///		Cadena que contiene el nombre de la cola. El valor predeterminado es fx, la cola de efectos estándar.
		///	</param>
		///	<returns type="jQuery" />

		time = jQuery.fx ? jQuery.fx.speeds[time] || time : time;
		type = type || "fx";

		return this.queue( type, function() {
			var elem = this;
			setTimeout(function() {
				jQuery.dequeue( elem, type );
			}, time );
		});
	},

	clearQueue: function( type ) {
		///	<summary>
		///		Quitar de la cola todos los elementos que no se han ejecutado aún.
		///	</summary>
		///	<param name="type" type="String" optional="true">
		///		Cadena que contiene el nombre de la cola. El valor predeterminado es fx, la cola de efectos estándar.
		///	</param>
		///	<returns type="jQuery" />

		return this.queue( type || "fx", [] );
	}
});
var rclass = /[\n\t]/g,
	rspace = /\s+/,
	rreturn = /\r/g,
	rspecialurl = /href|src|style/,
	rtype = /(button|input)/i,
	rfocusable = /(button|input|object|select|textarea)/i,
	rclickable = /^(a|area)$/i,
	rradiocheck = /radio|checkbox/;

jQuery.fn.extend({
	attr: function( name, value ) {
		///	<summary>
		///		Establecer una única propiedad en un valor calculado en todos los elementos coincidentes.
		///		En lugar de un valor, se proporciona una función que calcula el valor.
		///		Parte de DOM/Attributes
		///	</summary>
		///	<returns type="jQuery" />
		///	<param name="name" type="String">
		///		Nombre de la propiedad que se va a establecer.
		///	</param>
		///	<param name="value" type="Function">
		///		Función que devuelve el valor que se va a establecer.
		///	</param>

		return access( this, name, value, true, jQuery.attr );
	},

	removeAttr: function( name, fn ) {
		///	<summary>
		///		Quitar un atributo de cada uno de los elementos coincidentes.
		///		Parte de DOM/Attributes
		///	</summary>
		///	<param name="name" type="String">
		///		Atributo para quitar.
		///	</param>
		///	<returns type="jQuery" />

		return this.each(function(){
			jQuery.attr( this, name, "" );
			if ( this.nodeType === 1 ) {
				this.removeAttribute( name );
			}
		});
	},

	addClass: function( value ) {
		///	<summary>
		///		Agrega la clase o clases especificadas a cada uno de los elementos del conjunto de elementos coincidentes.
		///		Parte de DOM/Attributes
		///	</summary>
		///	<param name="value" type="String">
		///		Uno o varios nombres de clase para agregar al atributo de clase de cada elemento coincidente.
		///	</param>
		///	<returns type="jQuery" />

		if ( jQuery.isFunction(value) ) {
			return this.each(function(i) {
				var self = jQuery(this);
				self.addClass( value.call(this, i, self.attr("class")) );
			});
		}

		if ( value && typeof value === "string" ) {
			var classNames = (value || "").split( rspace );

			for ( var i = 0, l = this.length; i < l; i++ ) {
				var elem = this[i];

				if ( elem.nodeType === 1 ) {
					if ( !elem.className ) {
						elem.className = value;

					} else {
						var className = " " + elem.className + " ";
						for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
							if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) {
								elem.className += " " + classNames[c];
							}
						}
					}
				}
			}
		}

		return this;
	},

	removeClass: function( value ) {
		///	<summary>
		///		Quita todas las clases especificadas del conjunto de elementos coincidentes.
		///		Parte de DOM/Attributes
		///	</summary>
		///	<param name="value" type="String" optional="true">
		///		(Opcional) Nombre de clase para quitar del atributo de clase de cada elemento coincidente.
		///	</param>
		///	<returns type="jQuery" />

		if ( jQuery.isFunction(value) ) {
			return this.each(function(i) {
				var self = jQuery(this);
				self.removeClass( value.call(this, i, self.attr("class")) );
			});
		}

		if ( (value && typeof value === "string") || value === undefined ) {
			var classNames = (value || "").split(rspace);

			for ( var i = 0, l = this.length; i < l; i++ ) {
				var elem = this[i];

				if ( elem.nodeType === 1 && elem.className ) {
					if ( value ) {
						var className = (" " + elem.className + " ").replace(rclass, " ");
						for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
							className = className.replace(" " + classNames[c] + " ", " ");
						}
						elem.className = className.substring(1, className.length - 1);

					} else {
						elem.className = "";
					}
				}
			}
		}

		return this;
	},

	toggleClass: function( value, stateVal ) {
		///	<summary>
		///		Agregar o quitar una clase de cada elemento del conjunto de elementos coincidentes, dependiendo
		///		de la presencia de la clase o del valor del argumento modificador.
		///	</summary>
		///	<param name="value" type="Object">
		///		Nombre de clase al que se alterna para cada elemento del conjunto coincidente.
		///	</param>
		///	<param name="stateVal" type="Object">
		///		Valor booleano para determinar si la clase se debe agregar o quitar.
		///	</param>
		///	<returns type="jQuery" />

		var type = typeof value, isBool = typeof stateVal === "boolean";

		if ( jQuery.isFunction( value ) ) {
			return this.each(function(i) {
				var self = jQuery(this);
				self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal );
			});
		}

		return this.each(function() {
			if ( type === "string" ) {
				// toggle individual class names
				var className, i = 0, self = jQuery(this),
					state = stateVal,
					classNames = value.split( rspace );

				while ( (className = classNames[ i++ ]) ) {
					// check each className given, space seperated list
					state = isBool ? state : !self.hasClass( className );
					self[ state ? "addClass" : "removeClass" ]( className );
				}

			} else if ( type === "undefined" || type === "boolean" ) {
				if ( this.className ) {
					// store className if set
					jQuery.data( this, "__className__", this.className );
				}

				// toggle whole className
				this.className = this.className || value === false ? "" : jQuery.data( this, "__className__" ) || "";
			}
		});
	},

	hasClass: function( selector ) {
		///	<summary>
		///		Compara la selección actual con una clase y devuelve un valor que indica si al menos una selección tiene una clase dada.
		///	</summary>
		///	<param name="selector" type="String">Clase con la que se va a comparar</param>
		///	<returns type="Boolean">Devuelve True si al menos un elemento de la selección tiene la clase; de lo contrario, devuelve false.</returns>

		var className = " " + selector + " ";
		for ( var i = 0, l = this.length; i < l; i++ ) {
			if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
				return true;
			}
		}

		return false;
	},

	val: function( value ) {
		///	<summary>
		///		Establece el valor de cada elemento coincidente.
		///		Parte de DOM/Attributes
		///	</summary>
		///	<returns type="jQuery" />
		///	<param name="value" type="String">
		///		Cadena de texto o matriz de cadenas para establecer como propiedad de valor de cada
		///		elemento coincidente.
		///	</param>

		if ( value === undefined ) {
			var elem = this[0];

			if ( elem ) {
				if ( jQuery.nodeName( elem, "option" ) ) {
					return (elem.attributes.value || {}).specified ? elem.value : elem.text;
				}

				// We need to handle select boxes special
				if ( jQuery.nodeName( elem, "select" ) ) {
					var index = elem.selectedIndex,
						values = [],
						options = elem.options,
						one = elem.type === "select-one";

					// Nothing was selected
					if ( index < 0 ) {
						return null;
					}

					// Loop through all the selected options
					for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
						var option = options[ i ];

						if ( option.selected ) {
							// Get the specifc value for the option
							value = jQuery(option).val();

							// We don't need an array for one selects
							if ( one ) {
								return value;
							}

							// Multi-Selects return an array
							values.push( value );
						}
					}

					return values;
				}

				// Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
				if ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) {
					return elem.getAttribute("value") === null ? "on" : elem.value;
				}
				

				// Everything else, we just grab the value
				return (elem.value || "").replace(rreturn, "");

			}

			return undefined;
		}

		var isFunction = jQuery.isFunction(value);

		return this.each(function(i) {
			var self = jQuery(this), val = value;

			if ( this.nodeType !== 1 ) {
				return;
			}

			if ( isFunction ) {
				val = value.call(this, i, self.val());
			}

			// Typecast each time if the value is a Function and the appended
			// value is therefore different each time.
			if ( typeof val === "number" ) {
				val += "";
			}

			if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) {
				this.checked = jQuery.inArray( self.val(), val ) >= 0;

			} else if ( jQuery.nodeName( this, "select" ) ) {
				var values = jQuery.makeArray(val);

				jQuery( "option", this ).each(function() {
					this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
				});

				if ( !values.length ) {
					this.selectedIndex = -1;
				}

			} else {
				this.value = val;
			}
		});
	}
});

jQuery.extend({
	attrFn: {
		val: true,
		css: true,
		html: true,
		text: true,
		data: true,
		width: true,
		height: true,
		offset: true
	},
		
	attr: function( elem, name, value, pass ) {
		///	<summary>
		///		Este método es interno.
		///	</summary>
		///	<private />

		// don't set attributes on text and comment nodes
		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
			return undefined;
		}

		if ( pass && name in jQuery.attrFn ) {
			return jQuery(elem)[name](value);
		}

		var notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ),
			// Whether we are setting (or getting)
			set = value !== undefined;

		// Try to normalize/fix the name
		name = notxml && jQuery.props[ name ] || name;

		// Only do all the following if this is a node (faster for style)
		if ( elem.nodeType === 1 ) {
			// These attributes require special treatment
			var special = rspecialurl.test( name );

			// Safari mis-reports the default selected property of an option
			// Accessing the parent's selectedIndex property fixes it
			if ( name === "selected" && !jQuery.support.optSelected ) {
				var parent = elem.parentNode;
				if ( parent ) {
					parent.selectedIndex;
	
					// Make sure that it also works with optgroups, see #5701
					if ( parent.parentNode ) {
						parent.parentNode.selectedIndex;
					}
				}
			}

			// If applicable, access the attribute via the DOM 0 way
			if ( name in elem && notxml && !special ) {
				if ( set ) {
					// We can't allow the type property to be changed (since it causes problems in IE)
					if ( name === "type" && rtype.test( elem.nodeName ) && elem.parentNode ) {
						jQuery.error( "type property can't be changed" );
					}

					elem[ name ] = value;
				}

				// browsers index elements by id/name on forms, give priority to attributes.
				if ( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) {
					return elem.getAttributeNode( name ).nodeValue;
				}

				// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
				// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
				if ( name === "tabIndex" ) {
					var attributeNode = elem.getAttributeNode( "tabIndex" );

					return attributeNode && attributeNode.specified ?
						attributeNode.value :
						rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
							0 :
							undefined;
				}

				return elem[ name ];
			}

			if ( !jQuery.support.style && notxml && name === "style" ) {
				if ( set ) {
					elem.style.cssText = "" + value;
				}

				return elem.style.cssText;
			}

			if ( set ) {
				// convert the value to a string (all browsers do this but IE) see #1070
				elem.setAttribute( name, "" + value );
			}

			var attr = !jQuery.support.hrefNormalized && notxml && special ?
					// Some attributes require a special call on IE
					elem.getAttribute( name, 2 ) :
					elem.getAttribute( name );

			// Non-existent attributes return null, we normalize to undefined
			return attr === null ? undefined : attr;
		}

		// elem is actually elem.style ... set the style
		// Using attr for specific style information is now deprecated. Use style insead.
		return jQuery.style( elem, name, value );
	}
});
var fcleanup = function( nm ) {
	return nm.replace(/[^\w\s\.\|`]/g, function( ch ) {
		return "\\" + ch;
	});
};

/*
 * A number of helper functions used for managing events.
 * Many of the ideas behind this code originated from
 * Dean Edwards' addEvent library.
 */
jQuery.event = {

	// Bind an event to an element
	// Original by Dean Edwards
	add: function( elem, types, handler, data ) {
		///	<summary>
		///		Este método es interno.
		///	</summary>
		///	<private />

		if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
			return;
		}

		// For whatever reason, IE has trouble passing the window object
		// around, causing it to be cloned in the process
		if ( elem.setInterval && ( elem !== window && !elem.frameElement ) ) {
			elem = window;
		}

		// Make sure that the function being executed has a unique ID
		if ( !handler.guid ) {
			handler.guid = jQuery.guid++;
		}

		// if data is passed, bind to handler
		if ( data !== undefined ) {
			// Create temporary function pointer to original handler
			var fn = handler;

			// Create unique handler function, wrapped around original handler
			handler = jQuery.proxy( fn );

			// Store data in unique handler
			handler.data = data;
		}

		// Init the element's event structure
		var events = jQuery.data( elem, "events" ) || jQuery.data( elem, "events", {} ),
			handle = jQuery.data( elem, "handle" ), eventHandle;

		if ( !handle ) {
			eventHandle = function() {
				// Handle the second event of a trigger and when
				// an event is called after a page has unloaded
				return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
					jQuery.event.handle.apply( eventHandle.elem, arguments ) :
					undefined;
			};

			handle = jQuery.data( elem, "handle", eventHandle );
		}

		// If no handle is found then we must be trying to bind to one of the
		// banned noData elements
		if ( !handle ) {
			return;
		}

		// Add elem as a property of the handle function
		// This is to prevent a memory leak with non-native
		// event in IE.
		handle.elem = elem;

		// Handle multiple events separated by a space
		// jQuery(...).bind("mouseover mouseout", fn);
		types = types.split( /\s+/ );

		var type, i = 0;

		while ( (type = types[ i++ ]) ) {
			// Namespaced event handlers
			var namespaces = type.split(".");
			type = namespaces.shift();

			if ( i > 1 ) {
				handler = jQuery.proxy( handler );

				if ( data !== undefined ) {
					handler.data = data;
				}
			}

			handler.type = namespaces.slice(0).sort().join(".");

			// Get the current list of functions bound to this event
			var handlers = events[ type ],
				special = this.special[ type ] || {};

			// Init the event handler queue
			if ( !handlers ) {
				handlers = events[ type ] = {};

				// Check for a special event handler
				// Only use addEventListener/attachEvent if the special
				// events handler returns false
				if ( !special.setup || special.setup.call( elem, data, namespaces, handler) === false ) {
					// Bind the global event handler to the element
					if ( elem.addEventListener ) {
						elem.addEventListener( type, handle, false );
					} else if ( elem.attachEvent ) {
						elem.attachEvent( "on" + type, handle );
					}
				}
			}
			
			if ( special.add ) { 
				var modifiedHandler = special.add.call( elem, handler, data, namespaces, handlers ); 
				if ( modifiedHandler && jQuery.isFunction( modifiedHandler ) ) { 
					modifiedHandler.guid = modifiedHandler.guid || handler.guid; 
					modifiedHandler.data = modifiedHandler.data || handler.data; 
					modifiedHandler.type = modifiedHandler.type || handler.type; 
					handler = modifiedHandler; 
				} 
			} 
			
			// Add the function to the element's handler list
			handlers[ handler.guid ] = handler;

			// Keep track of which events have been used, for global triggering
			this.global[ type ] = true;
		}

		// Nullify elem to prevent memory leaks in IE
		elem = null;
	},

	global: {},

	// Detach an event or set of events from an element
	remove: function( elem, types, handler ) {
		///	<summary>
		///		Este método es interno.
		///	</summary>
		///	<private />

		// don't do events on text and comment nodes
		if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
			return;
		}

		var events = jQuery.data( elem, "events" ), ret, type, fn;

		if ( events ) {
			// Unbind all events for the element
			if ( types === undefined || (typeof types === "string" && types.charAt(0) === ".") ) {
				for ( type in events ) {
					this.remove( elem, type + (types || "") );
				}
			} else {
				// types is actually an event object here
				if ( types.type ) {
					handler = types.handler;
					types = types.type;
				}

				// Handle multiple events separated by a space
				// jQuery(...).unbind("mouseover mouseout", fn);
				types = types.split(/\s+/);
				var i = 0;
				while ( (type = types[ i++ ]) ) {
					// Namespaced event handlers
					var namespaces = type.split(".");
					type = namespaces.shift();
					var all = !namespaces.length,
						cleaned = jQuery.map( namespaces.slice(0).sort(), fcleanup ),
						namespace = new RegExp("(^|\\.)" + cleaned.join("\\.(?:.*\\.)?") + "(\\.|$)"),
						special = this.special[ type ] || {};

					if ( events[ type ] ) {
						// remove the given handler for the given type
						if ( handler ) {
							fn = events[ type ][ handler.guid ];
							delete events[ type ][ handler.guid ];

						// remove all handlers for the given type
						} else {
							for ( var handle in events[ type ] ) {
								// Handle the removal of namespaced events
								if ( all || namespace.test( events[ type ][ handle ].type ) ) {
									delete events[ type ][ handle ];
								}
							}
						}

						if ( special.remove ) {
							special.remove.call( elem, namespaces, fn);
						}

						// remove generic event handler if no more handlers exist
						for ( ret in events[ type ] ) {
							break;
						}
						if ( !ret ) {
							if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
								if ( elem.removeEventListener ) {
									elem.removeEventListener( type, jQuery.data( elem, "handle" ), false );
								} else if ( elem.detachEvent ) {
									elem.detachEvent( "on" + type, jQuery.data( elem, "handle" ) );
								}
							}
							ret = null;
							delete events[ type ];
						}
					}
				}
			}

			// Remove the expando if it's no longer used
			for ( ret in events ) {
				break;
			}
			if ( !ret ) {
				var handle = jQuery.data( elem, "handle" );
				if ( handle ) {
					handle.elem = null;
				}
				jQuery.removeData( elem, "events" );
				jQuery.removeData( elem, "handle" );
			}
		}
	},

	// bubbling is internal
	trigger: function( event, data, elem /*, bubbling */ ) {
		///	<summary>
		///		This method is internal.
		///	</summary>
		///	<private />

		// Event object or event type
		var type = event.type || event,
			bubbling = arguments[3];

		if ( !bubbling ) {
			event = typeof event === "object" ?
				// jQuery.Event object
				event[expando] ? event :
				// Object literal
				jQuery.extend( jQuery.Event(type), event ) :
				// Just the event type (string)
				jQuery.Event(type);

			if ( type.indexOf("!") >= 0 ) {
				event.type = type = type.slice(0, -1);
				event.exclusive = true;
			}

			// Handle a global trigger
			if ( !elem ) {
				// Don't bubble custom events when global (to avoid too much overhead)
				event.stopPropagation();

				// Only trigger if we've ever bound an event for it
				if ( this.global[ type ] ) {
					jQuery.each( jQuery.cache, function() {
						if ( this.events && this.events[type] ) {
							jQuery.event.trigger( event, data, this.handle.elem );
						}
					});
				}
			}

			// Handle triggering a single element

			// don't do events on text and comment nodes
			if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
				return undefined;
			}

			// Clean up in case it is reused
			event.result = undefined;
			event.target = elem;

			// Clone the incoming data, if any
			data = jQuery.makeArray( data );
			data.unshift( event );
		}

		event.currentTarget = elem;

		// Trigger the event, it is assumed that "handle" is a function
		var handle = jQuery.data( elem, "handle" );
		if ( handle ) {
			handle.apply( elem, data );
		}

		var parent = elem.parentNode || elem.ownerDocument;

		// Trigger an inline bound script
		try {
			if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) {
				if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) {
					event.result = false;
				}
			}

		// prevent IE from throwing an error for some elements with some event types, see #3533
		} catch (e) {}

		if ( !event.isPropagationStopped() && parent ) {
			jQuery.event.trigger( event, data, parent, true );

		} else if ( !event.isDefaultPrevented() ) {
			var target = event.target, old,
				isClick = jQuery.nodeName(target, "a") && type === "click";

			if ( !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) {
				try {
					if ( target[ type ] ) {
						// Make sure that we don't accidentally re-trigger the onFOO events
						old = target[ "on" + type ];

						if ( old ) {
							target[ "on" + type ] = null;
						}

						this.triggered = true;
						target[ type ]();
					}

				// prevent IE from throwing an error for some elements with some event types, see #3533
				} catch (e) {}

				if ( old ) {
					target[ "on" + type ] = old;
				}

				this.triggered = false;
			}
		}
	},

	handle: function( event ) {
		///	<summary>
		///		Este método es interno.
		///	</summary>
		///	<private />

		// returned undefined or false
		var all, handlers;

		event = arguments[0] = jQuery.event.fix( event || window.event );
		event.currentTarget = this;

		// Namespaced event handlers
		var namespaces = event.type.split(".");
		event.type = namespaces.shift();

		// Cache this now, all = true means, any handler
		all = !namespaces.length && !event.exclusive;

		var namespace = new RegExp("(^|\\.)" + namespaces.slice(0).sort().join("\\.(?:.*\\.)?") + "(\\.|$)");

		handlers = ( jQuery.data(this, "events") || {} )[ event.type ];

		for ( var j in handlers ) {
			var handler = handlers[ j ];

			// Filter the functions by class
			if ( all || namespace.test(handler.type) ) {
				// Pass in a reference to the handler function itself
				// So that we can later remove it
				event.handler = handler;
				event.data = handler.data;

				var ret = handler.apply( this, arguments );

				if ( ret !== undefined ) {
					event.result = ret;
					if ( ret === false ) {
						event.preventDefault();
						event.stopPropagation();
					}
				}

				if ( event.isImmediatePropagationStopped() ) {
					break;
				}

			}
		}

		return event.result;
	},

	props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),

	fix: function( event ) {
		///	<summary>
		///		Este método es interno.
		///	</summary>
		///	<private />

		if ( event[ expando ] ) {
			return event;
		}

		// store a copy of the original event object
		// and "clone" to set read-only properties
		var originalEvent = event;
		event = jQuery.Event( originalEvent );

		for ( var i = this.props.length, prop; i; ) {
			prop = this.props[ --i ];
			event[ prop ] = originalEvent[ prop ];
		}

		// Fix target property, if necessary
		if ( !event.target ) {
			event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
		}

		// check if target is a textnode (safari)
		if ( event.target.nodeType === 3 ) {
			event.target = event.target.parentNode;
		}

		// Add relatedTarget, if necessary
		if ( !event.relatedTarget && event.fromElement ) {
			event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
		}

		// Calculate pageX/Y if missing and clientX/Y available
		if ( event.pageX == null && event.clientX != null ) {
			var doc = document.documentElement, body = document.body;
			event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
			event.pageY = event.clientY + (doc && doc.scrollTop  || body && body.scrollTop  || 0) - (doc && doc.clientTop  || body && body.clientTop  || 0);
		}

		// Add which for key events
		if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) ) {
			event.which = event.charCode || event.keyCode;
		}

		// Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
		if ( !event.metaKey && event.ctrlKey ) {
			event.metaKey = event.ctrlKey;
		}

		// Add which for click: 1 === left; 2 === middle; 3 === right
		// Note: button is not normalized, so don't use it
		if ( !event.which && event.button !== undefined ) {
			event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
		}

		return event;
	},

	// Deprecated, use jQuery.guid instead
	guid: 1E8,

	// Deprecated, use jQuery.proxy instead
	proxy: jQuery.proxy,

	special: {
		ready: {
			// Make sure the ready event is setup
			setup: jQuery.bindReady,
			teardown: jQuery.noop
		},

		live: {
			add: function( proxy, data, namespaces, live ) {
				jQuery.extend( proxy, data || {} );

				proxy.guid += data.selector + data.live; 
				data.liveProxy = proxy;

				jQuery.event.add( this, data.live, liveHandler, data ); 
				
			},

			remove: function( namespaces ) {
				if ( namespaces.length ) {
					var remove = 0, name = new RegExp("(^|\\.)" + namespaces[0] + "(\\.|$)");

					jQuery.each( (jQuery.data(this, "events").live || {}), function() {
						if ( name.test(this.type) ) {
							remove++;
						}
					});

					if ( remove < 1 ) {
						jQuery.event.remove( this, namespaces[0], liveHandler );
					}
				}
			},
			special: {}
		},
		beforeunload: {
			setup: function( data, namespaces, fn ) {
				// We only want to do this special case on windows
				if ( this.setInterval ) {
					this.onbeforeunload = fn;
				}

				return false;
			},
			teardown: function( namespaces, fn ) {
				if ( this.onbeforeunload === fn ) {
					this.onbeforeunload = null;
				}
			}
		}
	}
};

jQuery.Event = function( src ) {
	// Allow instantiation without the 'new' keyword
	if ( !this.preventDefault ) {
		return new jQuery.Event( src );
	}

	// Event object
	if ( src && src.type ) {
		this.originalEvent = src;
		this.type = src.type;
	// Event type
	} else {
		this.type = src;
	}

	// timeStamp is buggy for some events on Firefox(#3843)
	// So we won't rely on the native value
	this.timeStamp = now();

	// Mark it as fixed
	this[ expando ] = true;
};

function returnFalse() {
	return false;
}
function returnTrue() {
	return true;
}

// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
jQuery.Event.prototype = {
	preventDefault: function() {
		this.isDefaultPrevented = returnTrue;

		var e = this.originalEvent;
		if ( !e ) {
			return;
		}
		
		// if preventDefault exists run it on the original event
		if ( e.preventDefault ) {
			e.preventDefault();
		}
		// otherwise set the returnValue property of the original event to false (IE)
		e.returnValue = false;
	},
	stopPropagation: function() {
		this.isPropagationStopped = returnTrue;

		var e = this.originalEvent;
		if ( !e ) {
			return;
		}
		// if stopPropagation exists run it on the original event
		if ( e.stopPropagation ) {
			e.stopPropagation();
		}
		// otherwise set the cancelBubble property of the original event to true (IE)
		e.cancelBubble = true;
	},
	stopImmediatePropagation: function() {
		this.isImmediatePropagationStopped = returnTrue;
		this.stopPropagation();
	},
	isDefaultPrevented: returnFalse,
	isPropagationStopped: returnFalse,
	isImmediatePropagationStopped: returnFalse
};

// Checks if an event happened on an element within another element
// Used in jQuery.event.special.mouseenter and mouseleave handlers
var withinElement = function( event ) {
	// Check if mouse(over|out) are still within the same parent element
	var parent = event.relatedTarget;

	// Traverse up the tree
	while ( parent && parent !== this ) {
		// Firefox sometimes assigns relatedTarget a XUL element
		// which we cannot access the parentNode property of
		try {
			parent = parent.parentNode;

		// assuming we've left the element since we most likely mousedover a xul element
		} catch(e) {
			break;
		}
	}

	if ( parent !== this ) {
		// set the correct event type
		event.type = event.data;

		// handle event if we actually just moused on to a non sub-element
		jQuery.event.handle.apply( this, arguments );
	}

},

// In case of event delegation, we only need to rename the event.type,
// liveHandler will take care of the rest.
delegate = function( event ) {
	event.type = event.data;
	jQuery.event.handle.apply( this, arguments );
};

// Create mouseenter and mouseleave events
jQuery.each({
	mouseenter: "mouseover",
	mouseleave: "mouseout"
}, function( orig, fix ) {
	jQuery.event.special[ orig ] = {
		setup: function( data ) {
			jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );
		},
		teardown: function( data ) {
			jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );
		}
	};
});

// submit delegation
if ( !jQuery.support.submitBubbles ) {

jQuery.event.special.submit = {
	setup: function( data, namespaces, fn ) {
		if ( this.nodeName.toLowerCase() !== "form" ) {
			jQuery.event.add(this, "click.specialSubmit." + fn.guid, function( e ) {
				var elem = e.target, type = elem.type;

				if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
					return trigger( "submit", this, arguments );
				}
			});
	 
			jQuery.event.add(this, "keypress.specialSubmit." + fn.guid, function( e ) {
				var elem = e.target, type = elem.type;

				if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
					return trigger( "submit", this, arguments );
				}
			});

		} else {
			return false;
		}
	},

	remove: function( namespaces, fn ) {
		jQuery.event.remove( this, "click.specialSubmit" + (fn ? "."+fn.guid : "") );
		jQuery.event.remove( this, "keypress.specialSubmit" + (fn ? "."+fn.guid : "") );
	}
};

}

// change delegation, happens here so we have bind.
if ( !jQuery.support.changeBubbles ) {

var formElems = /textarea|input|select/i;

function getVal( elem ) {
	var type = elem.type, val = elem.value;

	if ( type === "radio" || type === "checkbox" ) {
		val = elem.checked;

	} else if ( type === "select-multiple" ) {
		val = elem.selectedIndex > -1 ?
			jQuery.map( elem.options, function( elem ) {
				return elem.selected;
			}).join("-") :
			"";

	} else if ( elem.nodeName.toLowerCase() === "select" ) {
		val = elem.selectedIndex;
	}

	return val;
}

function testChange( e ) {
		var elem = e.target, data, val;

		if ( !formElems.test( elem.nodeName ) || elem.readOnly ) {
			return;
		}

		data = jQuery.data( elem, "_change_data" );
		val = getVal(elem);

		// the current data will be also retrieved by beforeactivate
		if ( e.type !== "focusout" || elem.type !== "radio" ) {
			jQuery.data( elem, "_change_data", val );
		}
		
		if ( data === undefined || val === data ) {
			return;
		}

		if ( data != null || val ) {
			e.type = "change";
			return jQuery.event.trigger( e, arguments[1], elem );
		}
}

jQuery.event.special.change = {
	filters: {
		focusout: testChange, 

		click: function( e ) {
			var elem = e.target, type = elem.type;

			if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) {
				return testChange.call( this, e );
			}
		},

		// Change has to be called before submit
		// Keydown will be called before keypress, which is used in submit-event delegation
		keydown: function( e ) {
			var elem = e.target, type = elem.type;

			if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") ||
				(e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
				type === "select-multiple" ) {
				return testChange.call( this, e );
			}
		},

		// Beforeactivate happens also before the previous element is blurred
		// with this event you can't trigger a change event, but you can store
		// information/focus[in] is not needed anymore
		beforeactivate: function( e ) {
			var elem = e.target;

			if ( elem.nodeName.toLowerCase() === "input" && elem.type === "radio" ) {
				jQuery.data( elem, "_change_data", getVal(elem) );
			}
		}
	},
	setup: function( data, namespaces, fn ) {
		for ( var type in changeFilters ) {
			jQuery.event.add( this, type + ".specialChange." + fn.guid, changeFilters[type] );
		}

		return formElems.test( this.nodeName );
	},
	remove: function( namespaces, fn ) {
		for ( var type in changeFilters ) {
			jQuery.event.remove( this, type + ".specialChange" + (fn ? "."+fn.guid : ""), changeFilters[type] );
		}

		return formElems.test( this.nodeName );
	}
};

var changeFilters = jQuery.event.special.change.filters;

}

function trigger( type, elem, args ) {
	args[0].type = type;
	return jQuery.event.handle.apply( elem, args );
}

// Create "bubbling" focus and blur events
if ( document.addEventListener ) {
	jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
		jQuery.event.special[ fix ] = {
			setup: function() {
				///	<summary>
				///		Este método es interno.
				///	</summary>
				///	<private />

				this.addEventListener( orig, handler, true );
			}, 
			teardown: function() { 
				///	<summary>
				///		Este método es interno.
				///	</summary>
				///	<private />

				this.removeEventListener( orig, handler, true );
			}
		};

		function handler( e ) { 
			e = jQuery.event.fix( e );
			e.type = fix;
			return jQuery.event.handle.call( this, e );
		}
	});
}

//	jQuery.each(["bind", "one"], function( i, name ) {
//		jQuery.fn[ name ] = function( type, data, fn ) {
//			// Handle object literals
//			if ( typeof type === "object" ) {
//				for ( var key in type ) {
//					this[ name ](key, data, type[key], fn);
//				}
//				return this;
//			}
//			
//			if ( jQuery.isFunction( data ) ) {
//				fn = data;
//				data = undefined;
//			}
//
//			var handler = name === "one" ? jQuery.proxy( fn, function( event ) {
//				jQuery( this ).unbind( event, handler );
//				return fn.apply( this, arguments );
//			}) : fn;
//
//			return type === "unload" && name !== "one" ?
//				this.one( type, data, fn ) :
//				this.each(function() {
//					jQuery.event.add( this, type, handler, data );
//				});
//		};
//	});

jQuery.fn[ "bind" ] = function( type, data, fn ) {
	///	<summary>
	///		Enlaza un controlador a uno o varios eventos para cada elemento coincidente. También puede enlazar eventos personalizados.
	///	</summary>
	///	<param name="type" type="String">Uno o varios tipos de eventos separados por un espacio. Los valores de tipo de evento integrados son: blur, focus, load, resize, scroll, unload, click, dblclick, mousedown, mouseup, mousemove, mouseover, mouseout, mouseenter, mouseleave, change, select, submit, keydown, keypress, keyup, error .</param>
	///	<param name="data" optional="true" type="Object">Datos adicionales pasados al controlador de eventos como event.data</param>
	///	<param name="fn" type="Function">Función que se enlaza al evento en cada uno de los elementos del conjunto de elementos coincidentes. Se debe usar una función callback(eventObject) como esta, que se corresponde con el elemento DOM.</param>

	// Controlar literales de objeto
	if ( typeof type === "object" ) {
		for ( var key in type ) {
			this[ "bind" ](key, data, type[key], fn);
		}
		return this;
	}
	
	if ( jQuery.isFunction( data ) ) {
		fn = data;
		data = undefined;
	}

	var handler = "bind" === "one" ? jQuery.proxy( fn, function( event ) {
		jQuery( this ).unbind( event, handler );
		return fn.apply( this, arguments );
	}) : fn;

	return type === "unload" && "bind" !== "one" ?
		this.one( type, data, fn ) :
		this.each(function() {
			jQuery.event.add( this, type, handler, data );
		});
};

jQuery.fn[ "one" ] = function( type, data, fn ) {
	///	<summary>
	///		Enlaza un controlador a uno o varios eventos para que se ejecuten exactamente una vez para cada elemento coincidente.
	///	</summary>
	///	<param name="type" type="String">Uno o varios tipos de eventos separados por un espacio. Los valores de tipo de evento integrados son: blur, focus, load, resize, scroll, unload, click, dblclick, mousedown, mouseup, mousemove, mouseover, mouseout, mouseenter, mouseleave, change, select, submit, keydown, keypress, keyup, error .</param>
	///	<param name="data" optional="true" type="Object">Datos adicionales pasados al controlador de eventos como event.data</param>
	///	<param name="fn" type="Function">Función que se enlaza al evento en cada uno de los elementos del conjunto de elementos coincidentes. Se debe usar una función callback(eventObject) como esta, que se corresponde con el elemento DOM.</param>

	// Handle object literals
	if ( typeof type === "object" ) {
		for ( var key in type ) {
			this[ "one" ](key, data, type[key], fn);
		}
		return this;
	}
	
	if ( jQuery.isFunction( data ) ) {
		fn = data;
		data = undefined;
	}

	var handler = "one" === "one" ? jQuery.proxy( fn, function( event ) {
		jQuery( this ).unbind( event, handler );
		return fn.apply( this, arguments );
	}) : fn;

	return type === "unload" && "one" !== "one" ?
		this.one( type, data, fn ) :
		this.each(function() {
			jQuery.event.add( this, type, handler, data );
		});
};

jQuery.fn.extend({
	unbind: function( type, fn ) {
		///	<summary>
		///		Desenlaza un controlador de uno o varios eventos para cada elemento coincidente.
		///	</summary>
		///	<param name="type" type="String">Uno o varios tipos de eventos separados por un espacio. Los valores de tipo de evento integrados son: blur, focus, load, resize, scroll, unload, click, dblclick, mousedown, mouseup, mousemove, mouseover, mouseout, mouseenter, mouseleave, change, select, submit, keydown, keypress, keyup, error .</param>
		///	<param name="fn" type="Function">Función que se enlaza al evento en cada uno de los elementos del conjunto de elementos coincidentes. Se debe usar una función callback(eventObject) como esta, que se corresponde con el elemento DOM.</param>

		// Handle object literals
		if ( typeof type === "object" && !type.preventDefault ) {
			for ( var key in type ) {
				this.unbind(key, type[key]);
			}
			return this;
		}

		return this.each(function() {
			jQuery.event.remove( this, type, fn );
		});
	},
	trigger: function( type, data ) {
		///	<summary>
		///		Desencadena un tipo de evento en cada elemento coincidente.
		///	</summary>
		///	<param name="type" type="String">Uno o varios tipos de eventos separados por un espacio. Los valores de tipo de evento integrados son: blur, focus, load, resize, scroll, unload, click, dblclick, mousedown, mouseup, mousemove, mouseover, mouseout, mouseenter, mouseleave, change, select, submit, keydown, keypress, keyup, error .</param>
		///	<param name="data" optional="true" type="Array">Datos adicionales pasados al controlador de eventos como argumentos adicionales.</param>
		///	<param name="fn" type="Function">Este parámetro no está documentado.</param>

		return this.each(function() {
			jQuery.event.trigger( type, data, this );
		});
	},

	triggerHandler: function( type, data ) {
		///	<summary>
		///		Desencadena todos los controladores de eventos enlazados en un elemento de un tipo de evento específico sin ejecutar las acciones predeterminadas del explorador.
		///	</summary>
		///	<param name="type" type="String">Uno o varios tipos de eventos separados por un espacio. Los valores de tipo de evento integrados son: blur, focus, load, resize, scroll, unload, click, dblclick, mousedown, mouseup, mousemove, mouseover, mouseout, mouseenter, mouseleave, change, select, submit, keydown, keypress, keyup, error .</param>
		///	<param name="data" optional="true" type="Array">Datos adicionales pasados al controlador de eventos como argumentos adicionales.</param>
		///	<param name="fn" type="Function">Este parámetro no está documentado.</param>

		if ( this[0] ) {
			var event = jQuery.Event( type );
			event.preventDefault();
			event.stopPropagation();
			jQuery.event.trigger( event, data, this[0] );
			return event.result;
		}
	},

	toggle: function( fn ) {
		///	<summary>
		///		Alterna entre dos o más llamadas a función cada clic alterno.
		///	</summary>
		///	<param name="fn" type="Function">Funciones cuya ejecución se alterna</param>

		// Save reference to arguments for access in closure
		var args = arguments, i = 1;

		// link all the functions, so any of them can unbind this click handler
		while ( i < args.length ) {
			jQuery.proxy( fn, args[ i++ ] );
		}

		return this.click( jQuery.proxy( fn, function( event ) {
			// Figure out which function to execute
			var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i;
			jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 );

			// Make sure that clicks stop
			event.preventDefault();

			// and execute the function
			return args[ lastToggle ].apply( this, arguments ) || false;
		}));
	},

	hover: function( fnOver, fnOut ) {
		///	<summary>
		///		Simula el movimiento del mouse dentro y fuera de un objeto (mantener el mouse).
		///	</summary>
		///	<param name="fnOver" type="Function">Función que se activa cuando el mouse se coloca en un elemento coincidente.</param>
		///	<param name="fnOut" type="Function">Función que se activa cuando el mouse se desplaza fuera de un elemento coincidente.</param>

		return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
	}
});

//	jQuery.each(["live", "die"], function( i, name ) {
//		jQuery.fn[ name ] = function( types, data, fn ) {
//			var type, i = 0;
//
//			if ( jQuery.isFunction( data ) ) {
//				fn = data;
//				data = undefined;
//			}
//
//			types = (types || "").split( /\s+/ );
//
//			while ( (type = types[ i++ ]) != null ) {
//				type = type === "focus" ? "focusin" : // focus --> focusin
//						type === "blur" ? "focusout" : // blur --> focusout
//						type === "hover" ? types.push("mouseleave") && "mouseenter" : // hover support
//						type;
//				
//				if ( name === "live" ) {
//					// bind live handler
//					jQuery( this.context ).bind( liveConvert( type, this.selector ), {
//						data: data, selector: this.selector, live: type
//					}, fn );
//
//				} else {
//					// unbind live handler
//					jQuery( this.context ).unbind( liveConvert( type, this.selector ), fn ? { guid: fn.guid + this.selector + type } : null );
//				}
//			}
//			
//			return this;
//		}
//	});

jQuery.fn[ "live" ] = function( types, data, fn ) {
	///	<summary>
	///		Asociar un controlador al evento para todos los elementos que coinciden con el selector actual, ahora o
	///		en el futuro.
	///	</summary>
	///	<param name="types" type="String">
	///		Cadena que contiene un tipo de evento de JavaScript, como "click" o "keydown".
	///	</param>
	///	<param name="data" type="Object">
	///		Asignación de datos que se pasará al controlador de eventos.
	///	</param>
	///	<param name="fn" type="Function">
	///		Función para ejecutar en el momento en que se desencadena el evento.
	///	</param>
	///	<returns type="jQuery" />

	var type, i = 0;

	if ( jQuery.isFunction( data ) ) {
		fn = data;
		data = undefined;
	}

	types = (types || "").split( /\s+/ );

	while ( (type = types[ i++ ]) != null ) {
		type = type === "focus" ? "focusin" : // focus --> focusin
				type === "blur" ? "focusout" : // blur --> focusout
				type === "hover" ? types.push("mouseleave") && "mouseenter" : // hover support
				type;
		
		if ( "live" === "live" ) {
			// bind live handler
			jQuery( this.context ).bind( liveConvert( type, this.selector ), {
				data: data, selector: this.selector, live: type
			}, fn );

		} else {
			// unbind live handler
			jQuery( this.context ).unbind( liveConvert( type, this.selector ), fn ? { guid: fn.guid + this.selector + type } : null );
		}
	}
	
	return this;
}

jQuery.fn[ "die" ] = function( types, data, fn ) {
	///	<summary>
	///		Quitar de los elementos todos los controladores de eventos asociados previamente con .live().
	///	</summary>
	///	<param name="types" type="String">
	///		Cadena que contiene un tipo de evento de JavaScript, como click o keydown.
	///	</param>
	///	<param name="data" type="Object">
	///		Función que dejará de ejecutarse.
	///	</param>
	///	<returns type="jQuery" />

	var type, i = 0;

	if ( jQuery.isFunction( data ) ) {
		fn = data;
		data = undefined;
	}

	types = (types || "").split( /\s+/ );

	while ( (type = types[ i++ ]) != null ) {
		type = type === "focus" ? "focusin" : // focus --> focusin
				type === "blur" ? "focusout" : // blur --> focusout
				type === "hover" ? types.push("mouseleave") && "mouseenter" : // hover support
				type;
		
		if ( "die" === "live" ) {
			// bind live handler
			jQuery( this.context ).bind( liveConvert( type, this.selector ), {
				data: data, selector: this.selector, live: type
			}, fn );

		} else {
			// unbind live handler
			jQuery( this.context ).unbind( liveConvert( type, this.selector ), fn ? { guid: fn.guid + this.selector + type } : null );
		}
	}
	
	return this;
}

function liveHandler( event ) {
	var stop, elems = [], selectors = [], args = arguments,
		related, match, fn, elem, j, i, l, data,
		live = jQuery.extend({}, jQuery.data( this, "events" ).live);

	// Make sure we avoid non-left-click bubbling in Firefox (#3861)
	if ( event.button && event.type === "click" ) {
		return;
	}

	for ( j in live ) {
		fn = live[j];
		if ( fn.live === event.type ||
				fn.altLive && jQuery.inArray(event.type, fn.altLive) > -1 ) {

			data = fn.data;
			if ( !(data.beforeFilter && data.beforeFilter[event.type] && 
					!data.beforeFilter[event.type](event)) ) {
				selectors.push( fn.selector );
			}
		} else {
			delete live[j];
		}
	}

	match = jQuery( event.target ).closest( selectors, event.currentTarget );

	for ( i = 0, l = match.length; i < l; i++ ) {
		for ( j in live ) {
			fn = live[j];
			elem = match[i].elem;
			related = null;

			if ( match[i].selector === fn.selector ) {
				// Those two events require additional checking
				if ( fn.live === "mouseenter" || fn.live === "mouseleave" ) {
					related = jQuery( event.relatedTarget ).closest( fn.selector )[0];
				}

				if ( !related || related !== elem ) {
					elems.push({ elem: elem, fn: fn });
				}
			}
		}
	}

	for ( i = 0, l = elems.length; i < l; i++ ) {
		match = elems[i];
		event.currentTarget = match.elem;
		event.data = match.fn.data;
		if ( match.fn.apply( match.elem, args ) === false ) {
			stop = false;
			break;
		}
	}

	return stop;
}

function liveConvert( type, selector ) {
	return "live." + (type ? type + "." : "") + selector.replace(/\./g, "`").replace(/ /g, "&");
}

//	jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
//		"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
//		"change select submit keydown keypress keyup error").split(" "), function( i, name ) {
//
//		// Handle event binding
//		jQuery.fn[ name ] = function( fn ) {
//			return fn ? this.bind( name, fn ) : this.trigger( name );
//		};
//
//		if ( jQuery.attrFn ) {
//			jQuery.attrFn[ name ] = true;
//		}
//	});

jQuery.fn[ "blur" ] = function( fn ) {
	///	<summary>
	///		1: blur(): desencadena el evento blur para cada elemento coincidente.
	///		2: blur(fn): enlaza una función al evento blur de cada elemento coincidente.
	///	</summary>
	///	<param name="fn" type="Function">La función que se va a ejecutar.</param>
	///	<returns type="jQuery" />

	return fn ? this.bind( "blur", fn ) : this.trigger( "blur" );
};

jQuery.fn[ "focus" ] = function( fn ) {
	///	<summary>
	///		1: focus(): desencadena el evento focus de cada elemento coincidente.
	///		2: focus(fn): enlaza una función al evento focus de cada elemento coincidente.
	///	</summary>
	///	<param name="fn" type="Function">La función que se va a ejecutar.</param>
	///	<returns type="jQuery" />

	return fn ? this.bind( "focus", fn ) : this.trigger( "focus" );
};

jQuery.fn[ "focusin" ] = function( fn ) {
		///	<summary>
		///		Enlazar un controlador de eventos al evento de JavaScript "focusin".
		///	</summary>
		///	<param name="fn" type="Function">
		///		Función para ejecutar cada vez que se desencadena el evento.
		///	</param>
		///	<returns type="jQuery" />

	return fn ? this.bind( "focusin", fn ) : this.trigger( "focusin" );
};

jQuery.fn[ "focusout" ] = function( fn ) {
		///	<summary>
		///		Enlazar un controlador de eventos al evento de JavaScript "focusout".
		///	</summary>
		///	<param name="fn" type="Function">
		///		Función para ejecutar cada vez que se desencadena el evento.
		///	</param>
		///	<returns type="jQuery" />

	return fn ? this.bind( "focusout", fn ) : this.trigger( "focusout" );
};

jQuery.fn[ "load" ] = function( fn ) {
	///	<summary>
	///		1: load(): desencadena el evento load de cada elemento coincidente.
	///		2: load(fn); enlaza una función al evento load de cada elemento coincidente.
	///	</summary>
	///	<param name="fn" type="Function">La función que se va a ejecutar.</param>
	///	<returns type="jQuery" />

	return fn ? this.bind( "load", fn ) : this.trigger( "load" );
};

jQuery.fn[ "resize" ] = function( fn ) {
	///	<summary>
	///		1: resize(): desencadena el evento resize de cada elemento coincidente.
	///		2: resize(fn): enlaza una función al evento resize de cada elemento coincidente.
	///	</summary>
	///	<param name="fn" type="Function">La función que se va a ejecutar.</param>
	///	<returns type="jQuery" />

	return fn ? this.bind( "resize", fn ) : this.trigger( "resize" );
};

jQuery.fn[ "scroll" ] = function( fn ) {
	///	<summary>
	///		1: scroll(): desencadena el evento scroll de cada elemento coincidente.
	///		2: scroll(fn): enlaza una función al evento scroll de cada elemento coincidente.
	///	</summary>
	///	<param name="fn" type="Function">La función que se va a ejecutar.</param>
	///	<returns type="jQuery" />

	return fn ? this.bind( "scroll", fn ) : this.trigger( "scroll" );
};

jQuery.fn[ "unload" ] = function( fn ) {
	///	<summary>
	///		1: unload(); desencadena el evento unload de cada elemento coincidente.
	///		2: unload(fn); enlaza una función al evento unload de cada elemento coincidente.
	///	</summary>
	///	<param name="fn" type="Function">La función que se va a ejecutar.</param>
	///	<returns type="jQuery" />

	return fn ? this.bind( "unload", fn ) : this.trigger( "unload" );
};

jQuery.fn[ "click" ] = function( fn ) {
	///	<summary>
	///		1: click(): desencadena el evento click de cada elemento coincidente.
	///		2: click(fn): enlaza una función al evento click de cada elemento coincidente.
	///	</summary>
	///	<param name="fn" type="Function">La función que se va a ejecutar.</param>
	///	<returns type="jQuery" />

	return fn ? this.bind( "click", fn ) : this.trigger( "click" );
};

jQuery.fn[ "dblclick" ] = function( fn ) {
	///	<summary>
	///		1: dblclick(); desencadena el evento dblclick de cada elemento coincidente.
	///		2: dblclick(fn): enlaza una función al evento dblclick de cada elemento coincidente.
	///	</summary>
	///	<param name="fn" type="Function">La función que se va a ejecutar.</param>
	///	<returns type="jQuery" />

	return fn ? this.bind( "dblclick", fn ) : this.trigger( "dblclick" );
};

jQuery.fn[ "mousedown" ] = function( fn ) {
	///	<summary>
	///		Enlaza una función al evento mousedown de cada elemento coincidente. 
	///	</summary>
	///	<param name="fn" type="Function">La función que se va a ejecutar.</param>
	///	<returns type="jQuery" />

	return fn ? this.bind( "mousedown", fn ) : this.trigger( "mousedown" );
};

jQuery.fn[ "mouseup" ] = function( fn ) {
	///	<summary>
	///		Enlaza una función al evento mouseup de cada elemento coincidente.
	///	</summary>
	///	<param name="fn" type="Function">La función que se va a ejecutar.</param>
	///	<returns type="jQuery" />

	return fn ? this.bind( "mouseup", fn ) : this.trigger( "mouseup" );
};

jQuery.fn[ "mousemove" ] = function( fn ) {
	///	<summary>
	///		Enlaza una función al evento mousemove de cada elemento coincidente.
	///	</summary>
	///	<param name="fn" type="Function">La función que se va a ejecutar.</param>
	///	<returns type="jQuery" />

	return fn ? this.bind( "mousemove", fn ) : this.trigger( "mousemove" );
};

jQuery.fn[ "mouseover" ] = function( fn ) {
	///	<summary>
	///		Enlaza una función al evento mouseover de cada elemento coincidente. 
	///	</summary>
	///	<param name="fn" type="Function">La función que se va a ejecutar.</param>
	///	<returns type="jQuery" />

	return fn ? this.bind( "mouseover", fn ) : this.trigger( "mouseover" );
};

jQuery.fn[ "mouseout" ] = function( fn ) {
	///	<summary>
	///		Enlaza una función al evento mouseout de cada elemento coincidente. 
	///	</summary>
	///	<param name="fn" type="Function">La función que se va a ejecutar.</param>
	///	<returns type="jQuery" />

	return fn ? this.bind( "mouseout", fn ) : this.trigger( "mouseout" );
};

jQuery.fn[ "mouseenter" ] = function( fn ) {
	///	<summary>
	///		Enlaza una función al evento mouseenter de cada elemento coincidente. 
	///	</summary>
	///	<param name="fn" type="Function">La función que se va a ejecutar.</param>
	///	<returns type="jQuery" />

	return fn ? this.bind( "mouseenter", fn ) : this.trigger( "mouseenter" );
};

jQuery.fn[ "mouseleave" ] = function( fn ) {
	///	<summary>
	///		Enlaza una función al evento mouseleave de cada elemento coincidente. 
	///	</summary>
	///	<param name="fn" type="Function">La función que se va a ejecutar.</param>
	///	<returns type="jQuery" />

	return fn ? this.bind( "mouseleave", fn ) : this.trigger( "mouseleave" );
};

jQuery.fn[ "change" ] = function( fn ) {
	///	<summary>
	///		1: change(): desencadena el evento change de cada elemento coincidente.
	///		2: change(fn); enlaza una función al evento change de cada elemento coincidente.
	///	</summary>
	///	<param name="fn" type="Function">La función que se va a ejecutar.</param>
	///	<returns type="jQuery" />

	return fn ? this.bind( "change", fn ) : this.trigger( "change" );
};

jQuery.fn[ "select" ] = function( fn ) {
	///	<summary>
	///		1: select(): desencadena el evento select de cada elemento coincidente.
	///		2: select(fn); enlaza una función al evento select de cada elemento coincidente.
	///	</summary>
	///	<param name="fn" type="Function">La función que se va a ejecutar.</param>
	///	<returns type="jQuery" />

	return fn ? this.bind( "select", fn ) : this.trigger( "select" );
};

jQuery.fn[ "submit" ] = function( fn ) {
	///	<summary>
	///		1: submit(): desencadena el evento submit de cada elemento coincidente.
	///		2: submit(fn); enlaza una función al evento submit de cada elemento coincidente.
	///	</summary>
	///	<param name="fn" type="Function">La función que se va a ejecutar.</param>
	///	<returns type="jQuery" />

	return fn ? this.bind( "submit", fn ) : this.trigger( "submit" );
};

jQuery.fn[ "keydown" ] = function( fn ) {
	///	<summary>
	///		1: keydown(): desencadena el evento keydown de cada elemento coincidente.
	///		2: keydown(fn); enlaza una función al evento keydown de cada elemento coincidente.
	///	</summary>
	///	<param name="fn" type="Function">La función que se va a ejecutar.</param>
	///	<returns type="jQuery" />

	return fn ? this.bind( "keydown", fn ) : this.trigger( "keydown" );
};

jQuery.fn[ "keypress" ] = function( fn ) {
	///	<summary>
	///		1: keypress(): desencadena el evento keypress de cada elemento coincidente.
	///		2: keypress(fn); enlaza una función al evento keypress de cada elemento coincidente.
	///	</summary>
	///	<param name="fn" type="Function">La función que se va a ejecutar.</param>
	///	<returns type="jQuery" />

	return fn ? this.bind( "keypress", fn ) : this.trigger( "keypress" );
};

jQuery.fn[ "keyup" ] = function( fn ) {
	///	<summary>
	///		1: keyup(): desencadena el evento keyup de cada elemento coincidente.
	///		2: keyup(fn): enlaza una función al evento keyup de cada elemento coincidente.
	///	</summary>
	///	<param name="fn" type="Function">La función que se va a ejecutar.</param>
	///	<returns type="jQuery" />

	return fn ? this.bind( "keyup", fn ) : this.trigger( "keyup" );
};

jQuery.fn[ "error" ] = function( fn ) {
	///	<summary>
	///		1: error(): desencadena el evento error de cada elemento coincidente.
	///		2: error(fn); enlaza una función al evento error de cada elemento coincidente.
	///	</summary>
	///	<param name="fn" type="Function">La función que se va a ejecutar.</param>
	///	<returns type="jQuery" />

	return fn ? this.bind( "error", fn ) : this.trigger( "error" );
};

// Prevent memory leaks in IE
// Window isn't included so as not to unbind existing unload events
// More info:
//  - http://isaacschlueter.com/2006/10/msie-memory-leaks/
if ( window.attachEvent && !window.addEventListener ) {
	window.attachEvent("onunload", function() {
		for ( var id in jQuery.cache ) {
			if ( jQuery.cache[ id ].handle ) {
				// Try/Catch is to handle iframes being unloaded, see #4280
				try {
					jQuery.event.remove( jQuery.cache[ id ].handle.elem );
				} catch(e) {}
			}
		}
	});
}
/*!
 * Sizzle CSS Selector Engine - v1.0
 *  Copyright 2009, The Dojo Foundation
 *  Released under the MIT, BSD, and GPL Licenses.
 *  More information: http://sizzlejs.com/
 */
(function(){

var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
	done = 0,
	toString = Object.prototype.toString,
	hasDuplicate = false,
	baseHasDuplicate = true;

// Here we check if the JavaScript engine is using some sort of
// optimization where it does not always call our comparision
// function. If that is the case, discard the hasDuplicate value.
//   Thus far that includes Google Chrome.
[0, 0].sort(function(){
	baseHasDuplicate = false;
	return 0;
});

var Sizzle = function(selector, context, results, seed) {
	results = results || [];
	var origContext = context = context || document;

	if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
		return [];
	}
	
	if ( !selector || typeof selector !== "string" ) {
		return results;
	}

	var parts = [], m, set, checkSet, extra, prune = true, contextXML = isXML(context),
		soFar = selector;
	
	// Reset the position of the chunker regexp (start from head)
	while ( (chunker.exec(""), m = chunker.exec(soFar)) !== null ) {
		soFar = m[3];
		
		parts.push( m[1] );
		
		if ( m[2] ) {
			extra = m[3];
			break;
		}
	}

	if ( parts.length > 1 && origPOS.exec( selector ) ) {
		if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
			set = posProcess( parts[0] + parts[1], context );
		} else {
			set = Expr.relative[ parts[0] ] ?
				[ context ] :
				Sizzle( parts.shift(), context );

			while ( parts.length ) {
				selector = parts.shift();

				if ( Expr.relative[ selector ] ) {
					selector += parts.shift();
				}
				
				set = posProcess( selector, set );
			}
		}
	} else {
		// Take a shortcut and set the context if the root selector is an ID
		// (but not if it'll be faster if the inner selector is an ID)
		if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
				Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
			var ret = Sizzle.find( parts.shift(), context, contextXML );
			context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0];
		}

		if ( context ) {
			var ret = seed ?
				{ expr: parts.pop(), set: makeArray(seed) } :
				Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
			set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set;

			if ( parts.length > 0 ) {
				checkSet = makeArray(set);
			} else {
				prune = false;
			}

			while ( parts.length ) {
				var cur = parts.pop(), pop = cur;

				if ( !Expr.relative[ cur ] ) {
					cur = "";
				} else {
					pop = parts.pop();
				}

				if ( pop == null ) {
					pop = context;
				}

				Expr.relative[ cur ]( checkSet, pop, contextXML );
			}
		} else {
			checkSet = parts = [];
		}
	}

	if ( !checkSet ) {
		checkSet = set;
	}

	if ( !checkSet ) {
		Sizzle.error( cur || selector );
	}

	if ( toString.call(checkSet) === "[object Array]" ) {
		if ( !prune ) {
			results.push.apply( results, checkSet );
		} else if ( context && context.nodeType === 1 ) {
			for ( var i = 0; checkSet[i] != null; i++ ) {
				if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
					results.push( set[i] );
				}
			}
		} else {
			for ( var i = 0; checkSet[i] != null; i++ ) {
				if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
					results.push( set[i] );
				}
			}
		}
	} else {
		makeArray( checkSet, results );
	}

	if ( extra ) {
		Sizzle( extra, origContext, results, seed );
		Sizzle.uniqueSort( results );
	}

	return results;
};

Sizzle.uniqueSort = function(results){
	///	<summary>
	///		Quita todos los elementos duplicados de una matriz de elementos.
	///	</summary>
	///	<param name="array" type="Array&lt;Element&gt;">Matriz que se va a convertir</param>
	///	<returns type="Array&lt;Element&gt;">La matriz después de la conversión.</returns>

	if ( sortOrder ) {
		hasDuplicate = baseHasDuplicate;
		results.sort(sortOrder);

		if ( hasDuplicate ) {
			for ( var i = 1; i < results.length; i++ ) {
				if ( results[i] === results[i-1] ) {
					results.splice(i--, 1);
				}
			}
		}
	}

	return results;
};

Sizzle.matches = function(expr, set){
	return Sizzle(expr, null, null, set);
};

Sizzle.find = function(expr, context, isXML){
	var set, match;

	if ( !expr ) {
		return [];
	}

	for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
		var type = Expr.order[i], match;
		
		if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
			var left = match[1];
			match.splice(1,1);

			if ( left.substr( left.length - 1 ) !== "\\" ) {
				match[1] = (match[1] || "").replace(/\\/g, "");
				set = Expr.find[ type ]( match, context, isXML );
				if ( set != null ) {
					expr = expr.replace( Expr.match[ type ], "" );
					break;
				}
			}
		}
	}

	if ( !set ) {
		set = context.getElementsByTagName("*");
	}

	return {set: set, expr: expr};
};

Sizzle.filter = function(expr, set, inplace, not){
	var old = expr, result = [], curLoop = set, match, anyFound,
		isXMLFilter = set && set[0] && isXML(set[0]);

	while ( expr && set.length ) {
		for ( var type in Expr.filter ) {
			if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
				var filter = Expr.filter[ type ], found, item, left = match[1];
				anyFound = false;

				match.splice(1,1);

				if ( left.substr( left.length - 1 ) === "\\" ) {
					continue;
				}

				if ( curLoop === result ) {
					result = [];
				}

				if ( Expr.preFilter[ type ] ) {
					match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );

					if ( !match ) {
						anyFound = found = true;
					} else if ( match === true ) {
						continue;
					}
				}

				if ( match ) {
					for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
						if ( item ) {
							found = filter( item, match, i, curLoop );
							var pass = not ^ !!found;

							if ( inplace && found != null ) {
								if ( pass ) {
									anyFound = true;
								} else {
									curLoop[i] = false;
								}
							} else if ( pass ) {
								result.push( item );
								anyFound = true;
							}
						}
					}
				}

				if ( found !== undefined ) {
					if ( !inplace ) {
						curLoop = result;
					}

					expr = expr.replace( Expr.match[ type ], "" );

					if ( !anyFound ) {
						return [];
					}

					break;
				}
			}
		}

		// Improper expression
		if ( expr === old ) {
			if ( anyFound == null ) {
				Sizzle.error( expr );
			} else {
				break;
			}
		}

		old = expr;
	}

	return curLoop;
};

Sizzle.error = function( msg ) {
	throw "Syntax error, unrecognized expression: " + msg;
};

var Expr = Sizzle.selectors = {
	order: [ "ID", "NAME", "TAG" ],
	match: {
		ID: /#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
		CLASS: /\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
		NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,
		ATTR: /\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
		TAG: /^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,
		CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,
		POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,
		PSEUDO: /:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
	},
	leftMatch: {},
	attrMap: {
		"class": "className",
		"for": "htmlFor"
	},
	attrHandle: {
		href: function(elem){
			return elem.getAttribute("href");
		}
	},
	relative: {
		"+": function(checkSet, part){
			var isPartStr = typeof part === "string",
				isTag = isPartStr && !/\W/.test(part),
				isPartStrNotTag = isPartStr && !isTag;

			if ( isTag ) {
				part = part.toLowerCase();
			}

			for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
				if ( (elem = checkSet[i]) ) {
					while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}

					checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
						elem || false :
						elem === part;
				}
			}

			if ( isPartStrNotTag ) {
				Sizzle.filter( part, checkSet, true );
			}
		},
		">": function(checkSet, part){
			var isPartStr = typeof part === "string";

			if ( isPartStr && !/\W/.test(part) ) {
				part = part.toLowerCase();

				for ( var i = 0, l = checkSet.length; i < l; i++ ) {
					var elem = checkSet[i];
					if ( elem ) {
						var parent = elem.parentNode;
						checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
					}
				}
			} else {
				for ( var i = 0, l = checkSet.length; i < l; i++ ) {
					var elem = checkSet[i];
					if ( elem ) {
						checkSet[i] = isPartStr ?
							elem.parentNode :
							elem.parentNode === part;
					}
				}

				if ( isPartStr ) {
					Sizzle.filter( part, checkSet, true );
				}
			}
		},
		"": function(checkSet, part, isXML){
			var doneName = done++, checkFn = dirCheck;

			if ( typeof part === "string" && !/\W/.test(part) ) {
				var nodeCheck = part = part.toLowerCase();
				checkFn = dirNodeCheck;
			}

			checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
		},
		"~": function(checkSet, part, isXML){
			var doneName = done++, checkFn = dirCheck;

			if ( typeof part === "string" && !/\W/.test(part) ) {
				var nodeCheck = part = part.toLowerCase();
				checkFn = dirNodeCheck;
			}

			checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML);
		}
	},
	find: {
		ID: function(match, context, isXML){
			if ( typeof context.getElementById !== "undefined" && !isXML ) {
				var m = context.getElementById(match[1]);
				return m ? [m] : [];
			}
		},
		NAME: function(match, context){
			if ( typeof context.getElementsByName !== "undefined" ) {
				var ret = [], results = context.getElementsByName(match[1]);

				for ( var i = 0, l = results.length; i < l; i++ ) {
					if ( results[i].getAttribute("name") === match[1] ) {
						ret.push( results[i] );
					}
				}

				return ret.length === 0 ? null : ret;
			}
		},
		TAG: function(match, context){
			return context.getElementsByTagName(match[1]);
		}
	},
	preFilter: {
		CLASS: function(match, curLoop, inplace, result, not, isXML){
			match = " " + match[1].replace(/\\/g, "") + " ";

			if ( isXML ) {
				return match;
			}

			for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
				if ( elem ) {
					if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n]/g, " ").indexOf(match) >= 0) ) {
						if ( !inplace ) {
							result.push( elem );
						}
					} else if ( inplace ) {
						curLoop[i] = false;
					}
				}
			}

			return false;
		},
		ID: function(match){
			return match[1].replace(/\\/g, "");
		},
		TAG: function(match, curLoop){
			return match[1].toLowerCase();
		},
		CHILD: function(match){
			if ( match[1] === "nth" ) {
				// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
				var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
					match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||
					!/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);

				// calculate the numbers (first)n+(last) including if they are negative
				match[2] = (test[1] + (test[2] || 1)) - 0;
				match[3] = test[3] - 0;
			}

			// TODO: Move to normal caching system
			match[0] = done++;

			return match;
		},
		ATTR: function(match, curLoop, inplace, result, not, isXML){
			var name = match[1].replace(/\\/g, "");
			
			if ( !isXML && Expr.attrMap[name] ) {
				match[1] = Expr.attrMap[name];
			}

			if ( match[2] === "~=" ) {
				match[4] = " " + match[4] + " ";
			}

			return match;
		},
		PSEUDO: function(match, curLoop, inplace, result, not){
			if ( match[1] === "not" ) {
				// If we're dealing with a complex expression, or a simple one
				if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
					match[3] = Sizzle(match[3], null, null, curLoop);
				} else {
					var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
					if ( !inplace ) {
						result.push.apply( result, ret );
					}
					return false;
				}
			} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
				return true;
			}
			
			return match;
		},
		POS: function(match){
			match.unshift( true );
			return match;
		}
	},
	filters: {
		enabled: function(elem){
			return elem.disabled === false && elem.type !== "hidden";
		},
		disabled: function(elem){
			return elem.disabled === true;
		},
		checked: function(elem){
			return elem.checked === true;
		},
		selected: function(elem){
			// Accessing this property makes selected-by-default
			// options in Safari work properly
			elem.parentNode.selectedIndex;
			return elem.selected === true;
		},
		parent: function(elem){
			return !!elem.firstChild;
		},
		empty: function(elem){
			return !elem.firstChild;
		},
		has: function(elem, i, match){
			///	<summary>
			///		Solo para uso interno; usar hasClass('class')
			///	</summary>
			///	<private />

			return !!Sizzle( match[3], elem ).length;
		},
		header: function(elem){
			return /h\d/i.test( elem.nodeName );
		},
		text: function(elem){
			return "text" === elem.type;
		},
		radio: function(elem){
			return "radio" === elem.type;
		},
		checkbox: function(elem){
			return "checkbox" === elem.type;
		},
		file: function(elem){
			return "file" === elem.type;
		},
		password: function(elem){
			return "password" === elem.type;
		},
		submit: function(elem){
			return "submit" === elem.type;
		},
		image: function(elem){
			return "image" === elem.type;
		},
		reset: function(elem){
			return "reset" === elem.type;
		},
		button: function(elem){
			return "button" === elem.type || elem.nodeName.toLowerCase() === "button";
		},
		input: function(elem){
			return /input|select|textarea|button/i.test(elem.nodeName);
		}
	},
	setFilters: {
		first: function(elem, i){
			return i === 0;
		},
		last: function(elem, i, match, array){
			return i === array.length - 1;
		},
		even: function(elem, i){
			return i % 2 === 0;
		},
		odd: function(elem, i){
			return i % 2 === 1;
		},
		lt: function(elem, i, match){
			return i < match[3] - 0;
		},
		gt: function(elem, i, match){
			return i > match[3] - 0;
		},
		nth: function(elem, i, match){
			return match[3] - 0 === i;
		},
		eq: function(elem, i, match){
			return match[3] - 0 === i;
		}
	},
	filter: {
		PSEUDO: function(elem, match, i, array){
			var name = match[1], filter = Expr.filters[ name ];

			if ( filter ) {
				return filter( elem, i, match, array );
			} else if ( name === "contains" ) {
				return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0;
			} else if ( name === "not" ) {
				var not = match[3];

				for ( var i = 0, l = not.length; i < l; i++ ) {
					if ( not[i] === elem ) {
						return false;
					}
				}

				return true;
			} else {
				Sizzle.error( "Syntax error, unrecognized expression: " + name );
			}
		},
		CHILD: function(elem, match){
			var type = match[1], node = elem;
			switch (type) {
				case 'only':
				case 'first':
					while ( (node = node.previousSibling) )	 {
						if ( node.nodeType === 1 ) { 
							return false; 
						}
					}
					if ( type === "first" ) { 
						return true; 
					}
					node = elem;
				case 'last':
					while ( (node = node.nextSibling) )	 {
						if ( node.nodeType === 1 ) { 
							return false; 
						}
					}
					return true;
				case 'nth':
					var first = match[2], last = match[3];

					if ( first === 1 && last === 0 ) {
						return true;
					}
					
					var doneName = match[0],
						parent = elem.parentNode;
	
					if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
						var count = 0;
						for ( node = parent.firstChild; node; node = node.nextSibling ) {
							if ( node.nodeType === 1 ) {
								node.nodeIndex = ++count;
							}
						} 
						parent.sizcache = doneName;
					}
					
					var diff = elem.nodeIndex - last;
					if ( first === 0 ) {
						return diff === 0;
					} else {
						return ( diff % first === 0 && diff / first >= 0 );
					}
			}
		},
		ID: function(elem, match){
			return elem.nodeType === 1 && elem.getAttribute("id") === match;
		},
		TAG: function(elem, match){
			return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match;
		},
		CLASS: function(elem, match){
			return (" " + (elem.className || elem.getAttribute("class")) + " ")
				.indexOf( match ) > -1;
		},
		ATTR: function(elem, match){
			var name = match[1],
				result = Expr.attrHandle[ name ] ?
					Expr.attrHandle[ name ]( elem ) :
					elem[ name ] != null ?
						elem[ name ] :
						elem.getAttribute( name ),
				value = result + "",
				type = match[2],
				check = match[4];

			return result == null ?
				type === "!=" :
				type === "=" ?
				value === check :
				type === "*=" ?
				value.indexOf(check) >= 0 :
				type === "~=" ?
				(" " + value + " ").indexOf(check) >= 0 :
				!check ?
				value && result !== false :
				type === "!=" ?
				value !== check :
				type === "^=" ?
				value.indexOf(check) === 0 :
				type === "$=" ?
				value.substr(value.length - check.length) === check :
				type === "|=" ?
				value === check || value.substr(0, check.length + 1) === check + "-" :
				false;
		},
		POS: function(elem, match, i, array){
			var name = match[2], filter = Expr.setFilters[ name ];

			if ( filter ) {
				return filter( elem, i, match, array );
			}
		}
	}
};

var origPOS = Expr.match.POS;

for ( var type in Expr.match ) {
	Expr.match[ type ] = new RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );
	Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, function(all, num){
		return "\\" + (num - 0 + 1);
	}));
}

var makeArray = function(array, results) {
	array = Array.prototype.slice.call( array, 0 );

	if ( results ) {
		results.push.apply( results, array );
		return results;
	}
	
	return array;
};

// Perform a simple check to determine if the browser is capable of
// converting a NodeList to an array using builtin methods.
try {
	Array.prototype.slice.call( document.documentElement.childNodes, 0 );

// Provide a fallback method if it does not work
} catch(e){
	makeArray = function(array, results) {
		var ret = results || [];

		if ( toString.call(array) === "[object Array]" ) {
			Array.prototype.push.apply( ret, array );
		} else {
			if ( typeof array.length === "number" ) {
				for ( var i = 0, l = array.length; i < l; i++ ) {
					ret.push( array[i] );
				}
			} else {
				for ( var i = 0; array[i]; i++ ) {
					ret.push( array[i] );
				}
			}
		}

		return ret;
	};
}

var sortOrder;

if ( document.documentElement.compareDocumentPosition ) {
	sortOrder = function( a, b ) {
		if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
			if ( a == b ) {
				hasDuplicate = true;
			}
			return a.compareDocumentPosition ? -1 : 1;
		}

		var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
		if ( ret === 0 ) {
			hasDuplicate = true;
		}
		return ret;
	};
} else if ( "sourceIndex" in document.documentElement ) {
	sortOrder = function( a, b ) {
		if ( !a.sourceIndex || !b.sourceIndex ) {
			if ( a == b ) {
				hasDuplicate = true;
			}
			return a.sourceIndex ? -1 : 1;
		}

		var ret = a.sourceIndex - b.sourceIndex;
		if ( ret === 0 ) {
			hasDuplicate = true;
		}
		return ret;
	};
} else if ( document.createRange ) {
	sortOrder = function( a, b ) {
		if ( !a.ownerDocument || !b.ownerDocument ) {
			if ( a == b ) {
				hasDuplicate = true;
			}
			return a.ownerDocument ? -1 : 1;
		}

		var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
		aRange.setStart(a, 0);
		aRange.setEnd(a, 0);
		bRange.setStart(b, 0);
		bRange.setEnd(b, 0);
		var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
		if ( ret === 0 ) {
			hasDuplicate = true;
		}
		return ret;
	};
}

// Utility function for retreiving the text value of an array of DOM nodes
function getText( elems ) {
	var ret = "", elem;

	for ( var i = 0; elems[i]; i++ ) {
		elem = elems[i];

		// Get the text from text nodes and CDATA nodes
		if ( elem.nodeType === 3 || elem.nodeType === 4 ) {
			ret += elem.nodeValue;

		// Traverse everything else, except comment nodes
		} else if ( elem.nodeType !== 8 ) {
			ret += getText( elem.childNodes );
		}
	}

	return ret;
}

// [vsdoc] The following function has been modified for IntelliSense.
// Check to see if the browser returns elements by name when
// querying by getElementById (and provide a workaround)
(function(){
	// We're going to inject a fake input element with a specified name
	//	var form = document.createElement("div"),
	//		id = "script" + (new Date).getTime();
	//	form.innerHTML = "<a name='" + id + "'/>";

	//	// Inject it into the root element, check its status, and remove it quickly
	//	var root = document.documentElement;
	//	root.insertBefore( form, root.firstChild );

	// The workaround has to do additional checks after a getElementById
	// Which slows things down for other browsers (hence the branching)
	//	if ( document.getElementById( id ) ) {
		Expr.find.ID = function(match, context, isXML){
			if ( typeof context.getElementById !== "undefined" && !isXML ) {
				var m = context.getElementById(match[1]);
				return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];
			}
		};

		Expr.filter.ID = function(elem, match){
			var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
			return elem.nodeType === 1 && node && node.nodeValue === match;
		};
	//	}

	//	root.removeChild( form );
	root = form = null; // release memory in IE
})();

// [vsdoc] The following function has been modified for IntelliSense.
(function(){
	// Check to see if the browser returns only elements
	// when doing getElementsByTagName("*")

	// Create a fake element
	//	var div = document.createElement("div");
	//	div.appendChild( document.createComment("") );

	// Make sure no comments are found
	//	if ( div.getElementsByTagName("*").length > 0 ) {
		Expr.find.TAG = function(match, context){
			var results = context.getElementsByTagName(match[1]);

			// Filter out possible comments
			if ( match[1] === "*" ) {
				var tmp = [];

				for ( var i = 0; results[i]; i++ ) {
					if ( results[i].nodeType === 1 ) {
						tmp.push( results[i] );
					}
				}

				results = tmp;
			}

			return results;
		};
	//	}

	// Check to see if an attribute returns normalized href attributes
	//	div.innerHTML = "<a href='#'></a>";
	//	if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
	//			div.firstChild.getAttribute("href") !== "#" ) {
		Expr.attrHandle.href = function(elem){
			return elem.getAttribute("href", 2);
		};
	//	}

	div = null; // release memory in IE
})();

if ( document.querySelectorAll ) {
	(function(){
		var oldSizzle = Sizzle, div = document.createElement("div");
		div.innerHTML = "<p class='TEST'></p>";

		// Safari can't handle uppercase or unicode characters when
		// in quirks mode.
		if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
			return;
		}
	
		Sizzle = function(query, context, extra, seed){
			context = context || document;

			// Only use querySelectorAll on non-XML documents
			// (ID selectors don't work in non-HTML documents)
			if ( !seed && context.nodeType === 9 && !isXML(context) ) {
				try {
					return makeArray( context.querySelectorAll(query), extra );
				} catch(e){}
			}
		
			return oldSizzle(query, context, extra, seed);
		};

		for ( var prop in oldSizzle ) {
			Sizzle[ prop ] = oldSizzle[ prop ];
		}

		div = null; // release memory in IE
	})();
}

(function(){
	var div = document.createElement("div");

	div.innerHTML = "<div class='test e'></div><div class='test'></div>";

	// Opera can't find a second classname (in 9.6)
	// Also, make sure that getElementsByClassName actually exists
	if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) {
		return;
	}

	// Safari caches class attributes, doesn't catch changes (in 3.2)
	div.lastChild.className = "e";

	if ( div.getElementsByClassName("e").length === 1 ) {
		return;
	}
	
	Expr.order.splice(1, 0, "CLASS");
	Expr.find.CLASS = function(match, context, isXML) {
		if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
			return context.getElementsByClassName(match[1]);
		}
	};

	div = null; // release memory in IE
})();

function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
	for ( var i = 0, l = checkSet.length; i < l; i++ ) {
		var elem = checkSet[i];
		if ( elem ) {
			elem = elem[dir];
			var match = false;

			while ( elem ) {
				if ( elem.sizcache === doneName ) {
					match = checkSet[elem.sizset];
					break;
				}

				if ( elem.nodeType === 1 && !isXML ){
					elem.sizcache = doneName;
					elem.sizset = i;
				}

				if ( elem.nodeName.toLowerCase() === cur ) {
					match = elem;
					break;
				}

				elem = elem[dir];
			}

			checkSet[i] = match;
		}
	}
}

function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
	for ( var i = 0, l = checkSet.length; i < l; i++ ) {
		var elem = checkSet[i];
		if ( elem ) {
			elem = elem[dir];
			var match = false;

			while ( elem ) {
				if ( elem.sizcache === doneName ) {
					match = checkSet[elem.sizset];
					break;
				}

				if ( elem.nodeType === 1 ) {
					if ( !isXML ) {
						elem.sizcache = doneName;
						elem.sizset = i;
					}
					if ( typeof cur !== "string" ) {
						if ( elem === cur ) {
							match = true;
							break;
						}

					} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
						match = elem;
						break;
					}
				}

				elem = elem[dir];
			}

			checkSet[i] = match;
		}
	}
}

var contains = document.compareDocumentPosition ? function(a, b){
	///	<summary>
	///		Comprobar si un nodo DOM está dentro de otro nodo DOM.
	///	</summary>
	///	<param name="a" type="Object">
	///		Elemento DOM que puede contener el otro elemento.
	///	</param>
	///	<param name="b" type="Object">
	///		Nodo DOM que el otro elemento puede contener.
	///	</param>
	///	<returns type="Boolean" />

	return a.compareDocumentPosition(b) & 16;
} : function(a, b){
	///	<summary>
	///		Comprobar si un nodo DOM está dentro de otro nodo DOM.
	///	</summary>
	///	<param name="a" type="Object">
	///		Elemento DOM que puede contener el otro elemento.
	///	</param>
	///	<param name="b" type="Object">
	///		Nodo DOM que el otro elemento puede contener.
	///	</param>
	///	<returns type="Boolean" />

	return a !== b && (a.contains ? a.contains(b) : true);
};

var isXML = function(elem){
	///	<summary>
	///		Determina si el parámetro pasado es un documento XML.
	///	</summary>
	///	<param name="elem" type="Object">Objeto que se va a comprobar</param>
	///	<returns type="Boolean">Devuelve True si el parámetro es un documento XML; de lo contrario, devuelve false.</returns>

	// documentElement is verified for cases where it doesn't yet exist
	// (such as loading iframes in IE - #4833) 
	var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;
	return documentElement ? documentElement.nodeName !== "HTML" : false;
};

var posProcess = function(selector, context){
	var tmpSet = [], later = "", match,
		root = context.nodeType ? [context] : context;

	// Position selectors must be done after the filter
	// And so must :not(positional) so we move all PSEUDOs to the end
	while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
		later += match[0];
		selector = selector.replace( Expr.match.PSEUDO, "" );
	}

	selector = Expr.relative[selector] ? selector + "*" : selector;

	for ( var i = 0, l = root.length; i < l; i++ ) {
		Sizzle( selector, root[i], tmpSet );
	}

	return Sizzle.filter( later, tmpSet );
};

// EXPOSE
jQuery.find = Sizzle;
jQuery.expr = Sizzle.selectors;
jQuery.expr[":"] = jQuery.expr.filters;
jQuery.unique = Sizzle.uniqueSort;
jQuery.getText = getText;
jQuery.isXMLDoc = isXML;
jQuery.contains = contains;

return;

window.Sizzle = Sizzle;

})();
var runtil = /Until$/,
	rparentsprev = /^(?:parents|prevUntil|prevAll)/,
	// Note: This RegExp should be improved, or likely pulled from Sizzle
	rmultiselector = /,/,
	slice = Array.prototype.slice;

// Implement the identical functionality for filter and not
var winnow = function( elements, qualifier, keep ) {
	if ( jQuery.isFunction( qualifier ) ) {
		return jQuery.grep(elements, function( elem, i ) {
			return !!qualifier.call( elem, i, elem ) === keep;
		});

	} else if ( qualifier.nodeType ) {
		return jQuery.grep(elements, function( elem, i ) {
			return (elem === qualifier) === keep;
		});

	} else if ( typeof qualifier === "string" ) {
		var filtered = jQuery.grep(elements, function( elem ) {
			return elem.nodeType === 1;
		});

		if ( isSimple.test( qualifier ) ) {
			return jQuery.filter(qualifier, filtered, !keep);
		} else {
			qualifier = jQuery.filter( qualifier, filtered );
		}
	}

	return jQuery.grep(elements, function( elem, i ) {
		return (jQuery.inArray( elem, qualifier ) >= 0) === keep;
	});
};

jQuery.fn.extend({
	find: function( selector ) {
		///	<summary>
		///		Busca todos los elementos que coinciden con la expresión especificada.
		///		Este método es una forma eficaz de buscar elementos descendientes
		///		adicionales con los que realizar el proceso.
		///		Toda la operación de búsqueda se realiza mediante una expresión jQuery. La expresión se puede
		///		escribir mediante la sintaxis de selector de CSS 1-3 o lenguaje XPath básico.
		///		Parte de DOM/Traversing
		///	</summary>
		///	<returns type="jQuery" />
		///	<param name="selector" type="String">
		///		Expresión con la que se va a realizar la búsqueda.
		///	</param>
		///	<returns type="jQuery" />

		var ret = this.pushStack( "", "find", selector ), length = 0;

		for ( var i = 0, l = this.length; i < l; i++ ) {
			length = ret.length;
			jQuery.find( selector, this[i], ret );

			if ( i > 0 ) {
				// Asegúrese de que los resultados son únicos.
				for ( var n = length; n < ret.length; n++ ) {
					for ( var r = 0; r < length; r++ ) {
						if ( ret[r] === ret[n] ) {
							ret.splice(n--, 1);
							break;
						}
					}
				}
			}
		}

		return ret;
	},

	has: function( target ) {
		///	<summary>
		///		Reducir el conjunto de elementos coincidentes a aquellos que tienen un descendiente que coincida con
		///		el selector o el elemento DOM.
		///	</summary>
		///	<param name="target" type="String">
		///		Cadena que contiene una expresión de selector con la que deben coincidir los elementos.
		///	</param>
		///	<returns type="jQuery" />

		var targets = jQuery( target );
		return this.filter(function() {
			for ( var i = 0, l = targets.length; i < l; i++ ) {
				if ( jQuery.contains( this, targets[i] ) ) {
					return true;
				}
			}
		});
	},

	not: function( selector ) {
		///	<summary>
		///		Quita todos los elementos incluidos en la matriz de elementos del conjunto
		///		de elementos coincidentes. Este método se usa para quitar uno o varios
		///		elementos de un objeto jQuery.
		///		Parte de DOM/Traversing
		///	</summary>
		///	<param name="selector" type="jQuery">
		///		Conjunto de elementos que se va a quitar del conjunto de elementos coincidentes de jQuery.
		///	</param>
		///	<returns type="jQuery" />

		return this.pushStack( winnow(this, selector, false), "not", selector);
	},

	filter: function( selector ) {
		///	<summary>
		///		Quita todos los elementos del conjunto de elementos coincidentes que no
		///		superan el filtro especificado. Este método se usa para restringir
		///		los resultados de una búsqueda.
		///		})
		///		Parte de DOM/Traversing
		///	</summary>
		///	<returns type="jQuery" />
		///	<param name="selector" type="Function">
		///		Función que se usa para el filtrado
		///	</param>
		///	<returns type="jQuery" />

		return this.pushStack( winnow(this, selector, true), "filter", selector );
	},
	
	is: function( selector ) {
		///	<summary>
		///		Compara la selección actual con una expresión y devuelve true
		///		si al menos un elemento de la selección coincide con la expresión especificada.
		///		Devuelve false si no hay ningún elemento coincidente o si la expresión no es válida.
		///		filter(String) se utiliza internamente y, por tanto, todas las reglas que se aplican allí
		///		también se aplican aquí.
		///		Parte de DOM/Traversing
		///	</summary>
		///	<returns type="Boolean" />
		///	<param name="expr" type="String">
		///		 Expresión con la que se va a filtrar
		///	</param>

		return !!selector && jQuery.filter( selector, this ).length > 0;
	},

	closest: function( selectors, context ) {
		///	<summary>
		///		Obtener un conjunto de elementos que contenga el elemento primario más cercano que coincida con el selector especificado, incluido el elemento inicial.
		///	</summary>
		///	<param name="selectors" type="String">
		///		Cadena que contiene una expresión de selector con la que deben coincidir los elementos.
		///	</param>
		///	<param name="context" type="Element">
		///		Elemento DOM en el que se puede encontrar un elemento coincidente. Si no se pasa contexto,
		///		se usará el contexto del conjunto jQuery.
		///	</param>
		///	<returns type="jQuery" />

		if ( jQuery.isArray( selectors ) ) {
			var ret = [], cur = this[0], match, matches = {}, selector;

			if ( cur && selectors.length ) {
				for ( var i = 0, l = selectors.length; i < l; i++ ) {
					selector = selectors[i];

					if ( !matches[selector] ) {
						matches[selector] = jQuery.expr.match.POS.test( selector ) ? 
							jQuery( selector, context || this.context ) :
							selector;
					}
				}

				while ( cur && cur.ownerDocument && cur !== context ) {
					for ( selector in matches ) {
						match = matches[selector];

						if ( match.jquery ? match.index(cur) > -1 : jQuery(cur).is(match) ) {
							ret.push({ selector: selector, elem: cur });
							delete matches[selector];
						}
					}
					cur = cur.parentNode;
				}
			}

			return ret;
		}

		var pos = jQuery.expr.match.POS.test( selectors ) ? 
			jQuery( selectors, context || this.context ) : null;

		return this.map(function( i, cur ) {
			while ( cur && cur.ownerDocument && cur !== context ) {
				if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selectors) ) {
					return cur;
				}
				cur = cur.parentNode;
			}
			return null;
		});
	},
	
	// Determine the position of an element within
	// the matched set of elements
	index: function( elem ) {
		///	<summary>
		///		Busca cada elemento coincidente del objeto y devuelve
		///		el índice del elemento, si se encuentra, empezando por cero. 
		///		Devuelve -1 si no se encuentra el objeto.
		///		Parte del núcleo
		///	</summary>
		///	<returns type="Number" />
		///	<param name="elem" type="Element">
		///		Objeto que se va a buscar
		///	</param>

		if ( !elem || typeof elem === "string" ) {
			return jQuery.inArray( this[0],
				// If it receives a string, the selector is used
				// If it receives nothing, the siblings are used
				elem ? jQuery( elem ) : this.parent().children() );
		}
		// Locate the position of the desired element
		return jQuery.inArray(
			// If it receives a jQuery object, the first element is used
			elem.jquery ? elem[0] : elem, this );
	},

	add: function( selector, context ) {
		///	<summary>
		///		Agrega uno o varios elementos al conjunto de elementos coincidentes.
		///		Parte de DOM/Traversing
		///	</summary>
		///	<param name="selector" type="String">
		///		Cadena que contiene una expresión de selector con la que deben coincidir elementos adicionales.
		///	</param>
		///	<param name="context" type="Element">
		///		Agregar algunos elementos con raíz en el contexto especificado.
		///	</param>
		///	<returns type="jQuery" />

		var set = typeof selector === "string" ?
				jQuery( selector, context || this.context ) :
				jQuery.makeArray( selector ),
			all = jQuery.merge( this.get(), set );

		return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
			all :
			jQuery.unique( all ) );
	},

	andSelf: function() {
		///	<summary>
		///		Agrega la selección anterior a la actual.
		///	</summary>
		///	<returns type="jQuery" />

		return this.add( this.prevObject );
	}
});

// A painfully simple check to see if an element is disconnected
// from a document (should be improved, where feasible).
function isDisconnected( node ) {
	return !node || !node.parentNode || node.parentNode.nodeType === 11;
}

jQuery.each({
	parent: function( elem ) {
		var parent = elem.parentNode;
		return parent && parent.nodeType !== 11 ? parent : null;
	},
	parents: function( elem ) {
		return jQuery.dir( elem, "parentNode" );
	},
	next: function( elem ) {
		return jQuery.nth( elem, 2, "nextSibling" );
	},
	prev: function( elem ) {
		return jQuery.nth( elem, 2, "previousSibling" );
	},
	nextAll: function( elem ) {
		return jQuery.dir( elem, "nextSibling" );
	},
	prevAll: function( elem ) {
		return jQuery.dir( elem, "previousSibling" );
	},
	siblings: function( elem ) {
		return jQuery.sibling( elem.parentNode.firstChild, elem );
	},
	children: function( elem ) {
		return jQuery.sibling( elem.firstChild );
	},
	contents: function( elem ) {
		return jQuery.nodeName( elem, "iframe" ) ?
			elem.contentDocument || elem.contentWindow.document :
			jQuery.makeArray( elem.childNodes );
	}
}, function( name, fn ) {
	jQuery.fn[ name ] = function( until, selector ) {
		var ret = jQuery.map( this, fn, until );
		
		if ( !runtil.test( name ) ) {
			selector = until;
		}

		if ( selector && typeof selector === "string" ) {
			ret = jQuery.filter( selector, ret );
		}

		ret = this.length > 1 ? jQuery.unique( ret ) : ret;

		if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {
			ret = ret.reverse();
		}

		return this.pushStack( ret, name, slice.call(arguments).join(",") );
	};
});

jQuery.fn[ "parentsUntil" ] = function( until, selector ) {
	///	<summary>
	///		Obtener los antecesores de cada elemento en el conjunto actual de elementos coincidentes, hasta
	///		(sin incluirlo) el elemento coincidente con el selector.
	///	</summary>
	///	<param name="until" type="String">
	///		Cadena que contiene una expresión de selector para indicar dónde detener la búsqueda de
	///		coincidencias en los elementos antecesores.
	///	</param>
	///	<returns type="jQuery" />

	var fn = function( elem, i, until ) {
		return jQuery.dir( elem, "parentNode", until );
	}

	var ret = jQuery.map( this, fn, until );
	
	if ( !runtil.test( "parentsUntil" ) ) {
		selector = until;
	}

	if ( selector && typeof selector === "string" ) {
		ret = jQuery.filter( selector, ret );
	}

	ret = this.length > 1 ? jQuery.unique( ret ) : ret;

	if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( "parentsUntil" ) ) {
		ret = ret.reverse();
	}

	return this.pushStack( ret, "parentsUntil", slice.call(arguments).join(",") );
};

jQuery.fn[ "nextUntil" ] = function( until, selector ) {
	///	<summary>
	///		Obtener todos los elementos del mismo nivel de cada elemento hasta (sin incluirlo) el elemento coincidente
	///		con el selector.
	///	</summary>
	///	<param name="until" type="String">
	///		Cadena que contiene una expresión de selector para indicar dónde detener la búsqueda
	///		de coincidencias en los elementos siguientes del mismo nivel.
	///	</param>
	///	<returns type="jQuery" />

	var fn = function( elem, i, until ) {
		return jQuery.dir( elem, "nextSibling", until );
	}

	var ret = jQuery.map( this, fn, until );
	
	if ( !runtil.test( "nextUntil" ) ) {
		selector = until;
	}

	if ( selector && typeof selector === "string" ) {
		ret = jQuery.filter( selector, ret );
	}

	ret = this.length > 1 ? jQuery.unique( ret ) : ret;

	if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( "nextUntil" ) ) {
		ret = ret.reverse();
	}

	return this.pushStack( ret, "nextUntil", slice.call(arguments).join(",") );
};

jQuery.fn[ "prevUntil" ] = function( until, selector ) {
	///	<summary>
	///		Obtener todos los elementos anteriores del mismo nivel de cada elemento hasta (sin incluirlo) el elemento coincidente
	///		con el selector.
	///	</summary>
	///	<param name="until" type="String">
	///		Cadena que contiene una expresión de selector para indicar dónde detener la búsqueda
	///		de coincidencias de elementos anteriores del mismo nivel.
	///	</param>
	///	<returns type="jQuery" />

	var fn = function( elem, i, until ) {
		return jQuery.dir( elem, "previousSibling", until );
	}

	var ret = jQuery.map( this, fn, until );
	
	if ( !runtil.test( "prevUntil" ) ) {
		selector = until;
	}

	if ( selector && typeof selector === "string" ) {
		ret = jQuery.filter( selector, ret );
	}

	ret = this.length > 1 ? jQuery.unique( ret ) : ret;

	if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( "prevUntil" ) ) {
		ret = ret.reverse();
	}

	return this.pushStack( ret, "prevUntil", slice.call(arguments).join(",") );
};

jQuery.extend({
	filter: function( expr, elems, not ) {
		if ( not ) {
			expr = ":not(" + expr + ")";
		}

		return jQuery.find.matches(expr, elems);
	},
	
	dir: function( elem, dir, until ) {
		///	<summary>
		///		Este miembro es solo para uso interno.
		///	</summary>
		///	<private />

		var matched = [], cur = elem[dir];
		while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
			if ( cur.nodeType === 1 ) {
				matched.push( cur );
			}
			cur = cur[dir];
		}
		return matched;
	},

	nth: function( cur, result, dir, elem ) {
		///	<summary>
		///		Este miembro es solo para uso interno.
		///	</summary>
		///	<private />

		result = result || 1;
		var num = 0;

		for ( ; cur; cur = cur[dir] ) {
			if ( cur.nodeType === 1 && ++num === result ) {
				break;
			}
		}

		return cur;
	},

	sibling: function( n, elem ) {
		///	<summary>
		///		Este miembro es solo para uso interno.
		///	</summary>
		///	<private />

		var r = [];

		for ( ; n; n = n.nextSibling ) {
			if ( n.nodeType === 1 && n !== elem ) {
				r.push( n );
			}
		}

		return r;
	}
});
var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
	rleadingWhitespace = /^\s+/,
	rxhtmlTag = /(<([\w:]+)[^>]*?)\/>/g,
	rselfClosing = /^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,
	rtagName = /<([\w:]+)/,
	rtbody = /<tbody/i,
	rhtml = /<|&\w+;/,
	rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,  // checked="checked" or checked (html5)
	fcloseTag = function( all, front, tag ) {
		return rselfClosing.test( tag ) ?
			all :
			front + "></" + tag + ">";
	},
	wrapMap = {
		option: [ 1, "<select multiple='multiple'>", "</select>" ],
		legend: [ 1, "<fieldset>", "</fieldset>" ],
		thead: [ 1, "<table>", "</table>" ],
		tr: [ 2, "<table><tbody>", "</tbody></table>" ],
		td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
		col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
		area: [ 1, "<map>", "</map>" ],
		_default: [ 0, "", "" ]
	};

wrapMap.optgroup = wrapMap.option;
wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
wrapMap.th = wrapMap.td;

// IE can't serialize <link> and <script> tags normally
if ( !jQuery.support.htmlSerialize ) {
	wrapMap._default = [ 1, "div<div>", "</div>" ];
}

jQuery.fn.extend({
	text: function( text ) {
		///	<summary>
		///		Establecer el contenido de texto de todos los elementos coincidentes.
		///		Similar a html(), pero aplica un carácter de escape a HTML (reemplazar &quot;&lt;&quot; y &quot;&gt;&quot; por sus
		///		entidades HTML).
		///		Parte de DOM/Attributes
		///	</summary>
		///	<returns type="jQuery" />
		///	<param name="text" type="String">
		///		Valor de texto en el que se establece el contenido del elemento.
		///	</param>

		if ( jQuery.isFunction(text) ) {
			return this.each(function(i) {
				var self = jQuery(this);
				self.text( text.call(this, i, self.text()) );
			});
		}

		if ( typeof text !== "object" && text !== undefined ) {
			return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
		}

		return jQuery.getText( this );
	},

	wrapAll: function( html ) {
		///	<summary>
		///		Encapsula todos los elementos coincidentes con una estructura de otros elementos.
		///		Este proceso de encapsulamiento sirve sobre todo para insertar una estructura
		///		adicional en un documento sin ejecutar las cualidades semánticas
		///		originales de un documento.
		///		Esto funciona atravesando el primer elemento
		///		proporcionado y buscando el elemento antecesor más profundo dentro de su
		///		estructura. Será ese elemento el que encapsulará a todos los demás.
		///		Esto no funciona con elementos que contienen texto. Todo el texto necesario
		///		debe agregarse después del encapsulamiento.
		///		Parte de DOM/Manipulation
		///	</summary>
		///	<returns type="jQuery" />
		///	<param name="html" type="Element">
		///		Elemento DOM que se encapsulará en torno al destino.
		///	</param>

		if ( jQuery.isFunction( html ) ) {
			return this.each(function(i) {
				jQuery(this).wrapAll( html.call(this, i) );
			});
		}

		if ( this[0] ) {
			// Elementos en torno a los cuales se encapsula el destino
			var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);

			if ( this[0].parentNode ) {
				wrap.insertBefore( this[0] );
			}

			wrap.map(function() {
				var elem = this;

				while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
					elem = elem.firstChild;
				}

				return elem;
			}).append(this);
		}

		return this;
	},

	wrapInner: function( html ) {
		///	<summary>
		///		Encapsula el contenido secundario interno de cada elemento coincidente (incluidos los nodos de texto) con una estructura HTML.
		///	</summary>
		///	<param name="html" type="String">
		///		Cadena de HTML o elemento DOM que se encapsulará en torno al contenido de destino.
		///	</param>
		///	<returns type="jQuery" />

		if ( jQuery.isFunction( html ) ) {
			return this.each(function(i) {
				jQuery(this).wrapInner( html.call(this, i) );
			});
		}

		return this.each(function() {
			var self = jQuery( this ), contents = self.contents();

			if ( contents.length ) {
				contents.wrapAll( html );

			} else {
				self.append( html );
			}
		});
	},

	wrap: function( html ) {
		///	<summary>
		///		Encapsula todos los elementos coincidentes con una estructura de otros elementos.
		///		Este proceso de encapsulamiento sirve sobre todo para insertar una estructura
		///		adicional en un documento sin ejecutar las cualidades semánticas
		///		originales de un documento.
		///		Esto funciona atravesando el primer elemento
		///		proporcionado y buscando el elemento antecesor más profundo dentro de su
		///		estructura. Será ese elemento el que encapsulará a todos los demás.
		///		Esto no funciona con elementos que contienen texto. Todo el texto necesario
		///		debe agregarse después del encapsulamiento.
		///		Parte de DOM/Manipulation
		///	</summary>
		///	<returns type="jQuery" />
		///	<param name="html" type="Element">
		///		Elemento DOM que se encapsulará en torno al destino.
		///	</param>

		return this.each(function() {
			jQuery( this ).wrapAll( html );
		});
	},

	unwrap: function() {
		///	<summary>
		///		Quitar los elementos primarios del conjunto de elementos coincidentes del elemento DOM, dejando
		///		los elementos coincidentes en su lugar.
		///	</summary>
		///	<returns type="jQuery" />
		return this.parent().each(function() {
			if ( !jQuery.nodeName( this, "body" ) ) {
				jQuery( this ).replaceWith( this.childNodes );
			}
		}).end();
	},

	append: function() {
		///	<summary>
		///		Anexar contenido al interior de cada elemento coincidente.
		///		Esa operación es similar a utilizar appendChild en todos los
		///		elementos especificados agregándolos al documento.
		///		Parte de DOM/Manipulation
		///	</summary>
		///	<returns type="jQuery" />

		return this.domManip(arguments, true, function( elem ) {
			if ( this.nodeType === 1 ) {
				this.appendChild( elem );
			}
		});
	},

	prepend: function() {
		///	<summary>
		///		Anteponer contenido al interior de cada elemento coincidente.
		///		Esta operación es el mejor modo de insertar elementos
		///		al principio de todos los elementos coincidentes.
		///		Parte de DOM/Manipulation
		///	</summary>
		///	<returns type="jQuery" />

		return this.domManip(arguments, true, function( elem ) {
			if ( this.nodeType === 1 ) {
				this.insertBefore( elem, this.firstChild );
			}
		});
	},

	before: function() {
		///	<summary>
		///		Insertar contenido delante de cada elemento coincidente.
		///		Parte de DOM/Manipulation
		///	</summary>
		///	<returns type="jQuery" />

		if ( this[0] && this[0].parentNode ) {
			return this.domManip(arguments, false, function( elem ) {
				this.parentNode.insertBefore( elem, this );
			});
		} else if ( arguments.length ) {
			var set = jQuery(arguments[0]);
			set.push.apply( set, this.toArray() );
			return this.pushStack( set, "before", arguments );
		}
	},

	after: function() {
		///	<summary>
		///		Insertar contenido detrás de cada elemento coincidente.
		///		Parte de DOM/Manipulation
		///	</summary>
		///	<returns type="jQuery" />

		if ( this[0] && this[0].parentNode ) {
			return this.domManip(arguments, false, function( elem ) {
				this.parentNode.insertBefore( elem, this.nextSibling );
			});
		} else if ( arguments.length ) {
			var set = this.pushStack( this, "after", arguments );
			set.push.apply( set, jQuery(arguments[0]).toArray() );
			return set;
		}
	},

	clone: function( events ) {
		///	<summary>
		///		Clonar los elementos DOM coincidentes y seleccionar los clones. 
		///		Esto sirve para mover copias de los elementos a otra
		///		ubicación en el DOM.
		///		Parte de DOM/Manipulation
		///	</summary>
		///	<returns type="jQuery" />
		///	<param name="deep" type="Boolean" optional="true">
		///		(Opcional) Establecer en false si no se desean clonar todos los elementos descendientes además del propio elemento.
		///	</param>

		// Do the clone
		var ret = this.map(function() {
			if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) {
				// IE copies events bound via attachEvent when
				// using cloneNode. Calling detachEvent on the
				// clone will also remove the events from the orignal
				// In order to get around this, we use innerHTML.
				// Unfortunately, this means some modifications to
				// attributes in IE that are actually only stored
				// as properties will not be copied (such as the
				// the name attribute on an input).
				var html = this.outerHTML, ownerDocument = this.ownerDocument;
				if ( !html ) {
					var div = ownerDocument.createElement("div");
					div.appendChild( this.cloneNode(true) );
					html = div.innerHTML;
				}

				return jQuery.clean([html.replace(rinlinejQuery, "")
					.replace(rleadingWhitespace, "")], ownerDocument)[0];
			} else {
				return this.cloneNode(true);
			}
		});

		// Copy the events from the original to the clone
		if ( events === true ) {
			cloneCopyEvent( this, ret );
			cloneCopyEvent( this.find("*"), ret.find("*") );
		}

		// Return the cloned set
		return ret;
	},

	html: function( value ) {
		///	<summary>
		///		Establecer el contenido html de cada elemento coincidente.
		///		Esta propiedad no está disponible en los documentos XML.
		///		Parte de DOM/Attributes
		///	</summary>
		///	<returns type="jQuery" />
		///	<param name="value" type="String">
		///		Cadena HTML para establecer como contenido de cada elemento coincidente.
		///	</param>

		if ( value === undefined ) {
			return this[0] && this[0].nodeType === 1 ?
				this[0].innerHTML.replace(rinlinejQuery, "") :
				null;

		// See if we can take a shortcut and just use innerHTML
		} else if ( typeof value === "string" && !/<script/i.test( value ) &&
			(jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
			!wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {

			value = value.replace(rxhtmlTag, fcloseTag);

			try {
				for ( var i = 0, l = this.length; i < l; i++ ) {
					// Remove element nodes and prevent memory leaks
					if ( this[i].nodeType === 1 ) {
						jQuery.cleanData( this[i].getElementsByTagName("*") );
						this[i].innerHTML = value;
					}
				}

			// If using innerHTML throws an exception, use the fallback method
			} catch(e) {
				this.empty().append( value );
			}

		} else if ( jQuery.isFunction( value ) ) {
			this.each(function(i){
				var self = jQuery(this), old = self.html();
				self.empty().append(function(){
					return value.call( this, i, old );
				});
			});

		} else {
			this.empty().append( value );
		}

		return this;
	},

	replaceWith: function( value ) {
		///	<summary>
		///		Reemplaza todos los elementos coincidentes por los elementos HTML o DOM especificados.
		///	</summary>
		///	<param name="value" type="Object">
		///		Contenido para insertar. Puede ser una cadena HTML, un elemento DOM o un objeto jQuery.
		///	</param>
		///	<returns type="jQuery">El elemento que se acaba de reemplazar.</returns>

		if ( this[0] && this[0].parentNode ) {
			// Make sure that the elements are removed from the DOM before they are inserted
			// this can help fix replacing a parent with child elements
			if ( !jQuery.isFunction( value ) ) {
				value = jQuery( value ).detach();

			} else {
				return this.each(function(i) {
					var self = jQuery(this), old = self.html();
					self.replaceWith( value.call( this, i, old ) );
				});
			}

			return this.each(function() {
				var next = this.nextSibling, parent = this.parentNode;

				jQuery(this).remove();

				if ( next ) {
					jQuery(next).before( value );
				} else {
					jQuery(parent).append( value );
				}
			});
		} else {
			return this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value );
		}
	},

	detach: function( selector ) {
		///	<summary>
		///		Quitar el conjunto de elementos coincidentes del elemento DOM.
		///	</summary>
		///	<param name="selector" type="String">
		///		Expresión de selector que filtra el conjunto de elementos coincidentes para quitar.
		///	</param>
		///	<returns type="jQuery" />

		return this.remove( selector, true );
	},

	domManip: function( args, table, callback ) {
		///	<param name="args" type="Array">
		///		 Argumentos
		///	</param>
		///	<param name="table" type="Boolean">
		///		 Insertar TBODY en TABLEs si se encuentra alguno.
		///	</param>
		///	<param name="dir" type="Number">
		///		 Si dir&lt;0, procesar los argumentos en el orden inverso.
		///	</param>
		///	<param name="fn" type="Function">
		///		 La función que realiza la manipulación de DOM.
		///	</param>
		///	<returns type="jQuery" />
		///	<summary>
		///		Parte del núcleo
		///	</summary>

		var results, first, value = args[0], scripts = [];

		// We can't cloneNode fragments that contain checked, in WebKit
		if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) {
			return this.each(function() {
				jQuery(this).domManip( args, table, callback, true );
			});
		}

		if ( jQuery.isFunction(value) ) {
			return this.each(function(i) {
				var self = jQuery(this);
				args[0] = value.call(this, i, table ? self.html() : undefined);
				self.domManip( args, table, callback );
			});
		}

		if ( this[0] ) {
			// If we're in a fragment, just use that instead of building a new one
			if ( args[0] && args[0].parentNode && args[0].parentNode.nodeType === 11 ) {
				results = { fragment: args[0].parentNode };
			} else {
				results = buildFragment( args, this, scripts );
			}

			first = results.fragment.firstChild;

			if ( first ) {
				table = table && jQuery.nodeName( first, "tr" );

				for ( var i = 0, l = this.length; i < l; i++ ) {
					callback.call(
						table ?
							root(this[i], first) :
							this[i],
						results.cacheable || this.length > 1 || i > 0 ?
							results.fragment.cloneNode(true) :
							results.fragment
					);
				}
			}

			if ( scripts ) {
				jQuery.each( scripts, evalScript );
			}
		}

		return this;

		function root( elem, cur ) {
			return jQuery.nodeName(elem, "table") ?
				(elem.getElementsByTagName("tbody")[0] ||
				elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
				elem;
		}
	}
});

function cloneCopyEvent(orig, ret) {
	var i = 0;

	ret.each(function() {
		if ( this.nodeName !== (orig[i] && orig[i].nodeName) ) {
			return;
		}

		var oldData = jQuery.data( orig[i++] ), curData = jQuery.data( this, oldData ), events = oldData && oldData.events;

		if ( events ) {
			delete curData.handle;
			curData.events = {};

			for ( var type in events ) {
				for ( var handler in events[ type ] ) {
					jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data );
				}
			}
		}
	});
}

function buildFragment( args, nodes, scripts ) {
	var fragment, cacheable, cacheresults, doc;

	// webkit does not clone 'checked' attribute of radio inputs on cloneNode, so don't cache if string has a checked
	if ( args.length === 1 && typeof args[0] === "string" && args[0].length < 512 && args[0].indexOf("<option") < 0 && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) {
		cacheable = true;
		cacheresults = jQuery.fragments[ args[0] ];
		if ( cacheresults ) {
			if ( cacheresults !== 1 ) {
				fragment = cacheresults;
			}
		}
	}

	if ( !fragment ) {
		doc = (nodes && nodes[0] ? nodes[0].ownerDocument || nodes[0] : document);
		fragment = doc.createDocumentFragment();
		jQuery.clean( args, doc, fragment, scripts );
	}

	if ( cacheable ) {
		jQuery.fragments[ args[0] ] = cacheresults ? fragment : 1;
	}

	return { fragment: fragment, cacheable: cacheable };
}

jQuery.fragments = {};

//	jQuery.each({
//		appendTo: "append",
//		prependTo: "prepend",
//		insertBefore: "before",
//		insertAfter: "after",
//		replaceAll: "replaceWith"
//	}, function( name, original ) {
//		jQuery.fn[ name ] = function( selector ) {
//			var ret = [], insert = jQuery( selector );

//			for ( var i = 0, l = insert.length; i < l; i++ ) {
//				var elems = (i > 0 ? this.clone(true) : this).get();
//				jQuery.fn[ original ].apply( jQuery(insert[i]), elems );
//				ret = ret.concat( elems );
//			}
//			return this.pushStack( ret, name, insert.selector );
//		};
//	});

jQuery.fn[ "appendTo" ] = function( selector ) {
	///	<summary>
	///		Anexar todos los elementos coincidentes en otro conjunto de elementos especificado.
	///		A partir de jQuery 1.3.2, se devuelven todos los elementos insertados.
	///		Esta operación es, básicamente, la operación contraria de un
	///		$(A).append(B) normal, en la que en lugar de anexar B en A, se anexa
	///		A en B.
	///	</summary>
	///	<param name="selector" type="Selector">
	///		 destino en el que se anexará el contenido.
	///	</param>
	///	<returns type="jQuery" />

	var ret = [], insert = jQuery( selector );

	for ( var i = 0, l = insert.length; i < l; i++ ) {
		var elems = (i > 0 ? this.clone(true) : this).get();
		jQuery.fn[ "append" ].apply( jQuery(insert[i]), elems );
		ret = ret.concat( elems );
	}
	return this.pushStack( ret, "appendTo", insert.selector );
};

jQuery.fn[ "prependTo" ] = function( selector ) {
	///	<summary>
	///		Anteponer todos los elementos coincidentes a otro conjunto de elementos especificado.
	///		A partir de jQuery 1.3.2, se devuelven todos los elementos insertados.
	///		Esta operación es, básicamente, la operación contraria de un
	///		$(A).prepend(B), en la que en lugar de anteponer B a A, se antepone
	///		A a B.
	///	</summary>
	///	<param name="selector" type="Selector">
	///		 destino en el que se anexará el contenido.
	///	</param>
	///	<returns type="jQuery" />

	var ret = [], insert = jQuery( selector );

	for ( var i = 0, l = insert.length; i < l; i++ ) {
		var elems = (i > 0 ? this.clone(true) : this).get();
		jQuery.fn[ "prepend" ].apply( jQuery(insert[i]), elems );
		ret = ret.concat( elems );
	}
	return this.pushStack( ret, "prependTo", insert.selector );
};

jQuery.fn[ "insertBefore" ] = function( selector ) {
	///	<summary>
	///		Insertar todos los elementos coincidentes delante de otro conjunto de elementos especificado.
	///		A partir de jQuery 1.3.2, se devuelven todos los elementos insertados.
	///		Esta operación es, básicamente, la operación contraria de un
	///		$(A).before(B) normal, en la que en lugar de insertar B delante de A, se inserta
	///		A delante de B.
	///	</summary>
	///	<param name="content" type="String">
	///		 Contenido tras el que se insertan los elementos seleccionados.
	///	</param>
	///	<returns type="jQuery" />

	var ret = [], insert = jQuery( selector );

	for ( var i = 0, l = insert.length; i < l; i++ ) {
		var elems = (i > 0 ? this.clone(true) : this).get();
		jQuery.fn[ "before" ].apply( jQuery(insert[i]), elems );
		ret = ret.concat( elems );
	}
	return this.pushStack( ret, "insertBefore", insert.selector );
};

jQuery.fn[ "insertAfter" ] = function( selector ) {
	///	<summary>
	///		Insertar todos los elementos coincidentes detrás de otro conjunto de elementos especificado.
	///		A partir de jQuery 1.3.2, se devuelven todos los elementos insertados.
	///		Esta operación es, básicamente, la operación contraria de un
	///		$(A).after(B) normal, en la que el lugar de insertar B detrás de A, se inserta
	///		A detrás de B.
	///	</summary>
	///	<param name="content" type="String">
	///		 Contenido tras el que se insertan los elementos seleccionados.
	///	</param>
	///	<returns type="jQuery" />

	var ret = [], insert = jQuery( selector );

	for ( var i = 0, l = insert.length; i < l; i++ ) {
		var elems = (i > 0 ? this.clone(true) : this).get();
		jQuery.fn[ "after" ].apply( jQuery(insert[i]), elems );
		ret = ret.concat( elems );
	}
	return this.pushStack( ret, "insertAfter", insert.selector );
};

jQuery.fn[ "replaceAll" ] = function( selector ) {
	///	<summary>
	///		Reemplaza los elementos que ha encontrado el selector especificado por los elementos coincidentes.
	///		A partir de jQuery 1.3.2, se devuelven todos los elementos insertados.
	///	</summary>
	///	<param name="selector" type="Selector">Elementos que se buscan y con los que se reemplazan los elementos coincidentes.</param>
	///	<returns type="jQuery" />

	var ret = [], insert = jQuery( selector );

	for ( var i = 0, l = insert.length; i < l; i++ ) {
		var elems = (i > 0 ? this.clone(true) : this).get();
		jQuery.fn[ "replaceWith" ].apply( jQuery(insert[i]), elems );
		ret = ret.concat( elems );
	}
	return this.pushStack( ret, "replaceAll", insert.selector );
};

jQuery.each({
	// keepData is for internal use only--do not document
	remove: function( selector, keepData ) {
		if ( !selector || jQuery.filter( selector, [ this ] ).length ) {
			if ( !keepData && this.nodeType === 1 ) {
				jQuery.cleanData( this.getElementsByTagName("*") );
				jQuery.cleanData( [ this ] );
			}

			if ( this.parentNode ) {
				 this.parentNode.removeChild( this );
			}
		}
	},

	empty: function() {
		///	<summary>
		///		Quita todos los nodos secundarios del conjunto de elementos coincidentes.
		///		Parte de DOM/Manipulation
		///	</summary>
		///	<returns type="jQuery" />

		// Remove element nodes and prevent memory leaks
		if ( this.nodeType === 1 ) {
			jQuery.cleanData( this.getElementsByTagName("*") );
		}

		// Remove any remaining nodes
		while ( this.firstChild ) {
			this.removeChild( this.firstChild );
		}
	}
}, function( name, fn ) {
	jQuery.fn[ name ] = function() {
		return this.each( fn, arguments );
	};
});

jQuery.extend({
	clean: function( elems, context, fragment, scripts ) {
		///	<summary>
		///		Este método es exclusivamente para uso interno.
		///	</summary>
		///	<private />

		context = context || document;

		// !context.createElement fails in IE with an error but returns typeof 'object'
		if ( typeof context.createElement === "undefined" ) {
			context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
		}

		var ret = [];

		jQuery.each(elems, function( i, elem ) {
			if ( typeof elem === "number" ) {
				elem += "";
			}

			if ( !elem ) {
				return;
			}

			// Convert html string into DOM nodes
			if ( typeof elem === "string" && !rhtml.test( elem ) ) {
				elem = context.createTextNode( elem );

			} else if ( typeof elem === "string" ) {
				// Fix "XHTML"-style tags in all browsers
				elem = elem.replace(rxhtmlTag, fcloseTag);

				// Trim whitespace, otherwise indexOf won't work as expected
				var tag = (rtagName.exec( elem ) || ["", ""])[1].toLowerCase(),
					wrap = wrapMap[ tag ] || wrapMap._default,
					depth = wrap[0],
					div = context.createElement("div");

				// Go to html and back, then peel off extra wrappers
				div.innerHTML = wrap[1] + elem + wrap[2];

				// Move to the right depth
				while ( depth-- ) {
					div = div.lastChild;
				}

				// Remove IE's autoinserted <tbody> from table fragments
				if ( !jQuery.support.tbody ) {

					// String was a <table>, *may* have spurious <tbody>
					var hasBody = rtbody.test(elem),
						tbody = tag === "table" && !hasBody ?
							div.firstChild && div.firstChild.childNodes :

							// String was a bare <thead> or <tfoot>
							wrap[1] === "<table>" && !hasBody ?
								div.childNodes :
								[];

					for ( var j = tbody.length - 1; j >= 0 ; --j ) {
						if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
							tbody[ j ].parentNode.removeChild( tbody[ j ] );
						}
					}

				}

				// IE completely kills leading whitespace when innerHTML is used
				if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
					div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
				}

				elem = jQuery.makeArray( div.childNodes );
			}

			if ( elem.nodeType ) {
				ret.push( elem );
			} else {
				ret = jQuery.merge( ret, elem );
			}

		});

		if ( fragment ) {
			for ( var i = 0; ret[i]; i++ ) {
				if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
					scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
				} else {
					if ( ret[i].nodeType === 1 ) {
						ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
					}
					fragment.appendChild( ret[i] );
				}
			}
		}

		return ret;
	},
	
	cleanData: function( elems ) {
		for ( var i = 0, elem, id; (elem = elems[i]) != null; i++ ) {
			jQuery.event.remove( elem );
			jQuery.removeData( elem );
		}
	}
});
// exclude the following css properties to add px
var rexclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
	ralpha = /alpha\([^)]*\)/,
	ropacity = /opacity=([^)]*)/,
	rfloat = /float/i,
	rdashAlpha = /-([a-z])/ig,
	rupper = /([A-Z])/g,
	rnumpx = /^-?\d+(?:px)?$/i,
	rnum = /^-?\d/,

	cssShow = { position: "absolute", visibility: "hidden", display:"block" },
	cssWidth = [ "Left", "Right" ],
	cssHeight = [ "Top", "Bottom" ],

	// cache check for defaultView.getComputedStyle
	getComputedStyle = document.defaultView && document.defaultView.getComputedStyle,
	// normalize float css property
	styleFloat = jQuery.support.cssFloat ? "cssFloat" : "styleFloat",
	fcamelCase = function( all, letter ) {
		return letter.toUpperCase();
	};

jQuery.fn.css = function( name, value ) {
	///	<summary>
	///		Establecer una única propiedad de estilo en un valor en todos los elementos coincidentes.
	///		Si se proporciona un número, este se convierte automáticamente en un valor de píxel.
	///		Parte de CSS
	///	</summary>
	///	<returns type="jQuery" />
	///	<param name="name" type="String">
	///		Nombre de propiedad CSS.
	///	</param>
	///	<param name="value" type="String">
	///		Valor para establecer para la propiedad.
	///	</param>

	return access( this, name, value, true, function( elem, name, value ) {
		if ( value === undefined ) {
			return jQuery.curCSS( elem, name );
		}
		
		if ( typeof value === "number" && !rexclude.test(name) ) {
			value += "px";
		}

		jQuery.style( elem, name, value );
	});
};

jQuery.extend({
	style: function( elem, name, value ) {
		// don't set styles on text and comment nodes
		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
			return undefined;
		}

		// ignore negative width and height values #1599
		if ( (name === "width" || name === "height") && parseFloat(value) < 0 ) {
			value = undefined;
		}

		var style = elem.style || elem, set = value !== undefined;

		// IE uses filters for opacity
		if ( !jQuery.support.opacity && name === "opacity" ) {
			if ( set ) {
				// IE has trouble with opacity if it does not have layout
				// Force it by setting the zoom level
				style.zoom = 1;

				// Set the alpha filter to set the opacity
				var opacity = parseInt( value, 10 ) + "" === "NaN" ? "" : "alpha(opacity=" + value * 100 + ")";
				var filter = style.filter || jQuery.curCSS( elem, "filter" ) || "";
				style.filter = ralpha.test(filter) ? filter.replace(ralpha, opacity) : opacity;
			}

			return style.filter && style.filter.indexOf("opacity=") >= 0 ?
				(parseFloat( ropacity.exec(style.filter)[1] ) / 100) + "":
				"";
		}

		// Make sure we're using the right name for getting the float value
		if ( rfloat.test( name ) ) {
			name = styleFloat;
		}

		name = name.replace(rdashAlpha, fcamelCase);

		if ( set ) {
			style[ name ] = value;
		}

		return style[ name ];
	},

	css: function( elem, name, force, extra ) {
		///	<summary>
		///		Este método es exclusivamente para uso interno.
		///	</summary>
		///	<private />

		if ( name === "width" || name === "height" ) {
			var val, props = cssShow, which = name === "width" ? cssWidth : cssHeight;

			function getWH() {
				val = name === "width" ? elem.offsetWidth : elem.offsetHeight;

				if ( extra === "border" ) {
					return;
				}

				jQuery.each( which, function() {
					if ( !extra ) {
						val -= parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
					}

					if ( extra === "margin" ) {
						val += parseFloat(jQuery.curCSS( elem, "margin" + this, true)) || 0;
					} else {
						val -= parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
					}
				});
			}

			if ( elem.offsetWidth !== 0 ) {
				getWH();
			} else {
				jQuery.swap( elem, props, getWH );
			}

			return Math.max(0, Math.round(val));
		}

		return jQuery.curCSS( elem, name, force );
	},

	curCSS: function( elem, name, force ) {
		///	<summary>
		///		Este método es exclusivamente para uso interno.
		///	</summary>
		///	<private />

		var ret, style = elem.style, filter;

		// IE uses filters for opacity
		if ( !jQuery.support.opacity && name === "opacity" && elem.currentStyle ) {
			ret = ropacity.test(elem.currentStyle.filter || "") ?
				(parseFloat(RegExp.$1) / 100) + "" :
				"";

			return ret === "" ?
				"1" :
				ret;
		}

		// Make sure we're using the right name for getting the float value
		if ( rfloat.test( name ) ) {
			name = styleFloat;
		}

		if ( !force && style && style[ name ] ) {
			ret = style[ name ];

		} else if ( getComputedStyle ) {

			// Only "float" is needed here
			if ( rfloat.test( name ) ) {
				name = "float";
			}

			name = name.replace( rupper, "-$1" ).toLowerCase();

			var defaultView = elem.ownerDocument.defaultView;

			if ( !defaultView ) {
				return null;
			}

			var computedStyle = defaultView.getComputedStyle( elem, null );

			if ( computedStyle ) {
				ret = computedStyle.getPropertyValue( name );
			}

			// We should always get a number back from opacity
			if ( name === "opacity" && ret === "" ) {
				ret = "1";
			}

		} else if ( elem.currentStyle ) {
			var camelCase = name.replace(rdashAlpha, fcamelCase);

			ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];

			// From the awesome hack by Dean Edwards
			// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291

			// If we're not dealing with a regular pixel number
			// but a number that has a weird ending, we need to convert it to pixels
			if ( !rnumpx.test( ret ) && rnum.test( ret ) ) {
				// Remember the original values
				var left = style.left, rsLeft = elem.runtimeStyle.left;

				// Put in the new values to get a computed value out
				elem.runtimeStyle.left = elem.currentStyle.left;
				style.left = camelCase === "fontSize" ? "1em" : (ret || 0);
				ret = style.pixelLeft + "px";

				// Revert the changed values
				style.left = left;
				elem.runtimeStyle.left = rsLeft;
			}
		}

		return ret;
	},

	// A method for quickly swapping in/out CSS properties to get correct calculations
	swap: function( elem, options, callback ) {
		///	<summary>
		///		Agregar o quitar opciones de estilo.
		///	</summary>

		var old = {};

		// Remember the old values, and insert the new ones
		for ( var name in options ) {
			old[ name ] = elem.style[ name ];
			elem.style[ name ] = options[ name ];
		}

		callback.call( elem );

		// Revert the old values
		for ( var name in options ) {
			elem.style[ name ] = old[ name ];
		}
	}
});

if ( jQuery.expr && jQuery.expr.filters ) {
	jQuery.expr.filters.hidden = function( elem ) {
		var width = elem.offsetWidth, height = elem.offsetHeight,
			skip = elem.nodeName.toLowerCase() === "tr";

		return width === 0 && height === 0 && !skip ?
			true :
			width > 0 && height > 0 && !skip ?
				false :
				jQuery.curCSS(elem, "display") === "none";
	};

	jQuery.expr.filters.visible = function( elem ) {
		return !jQuery.expr.filters.hidden( elem );
	};
}
var jsc = now(),
	rscript = /<script(.|\s)*?\/script>/gi,
	rselectTextarea = /select|textarea/i,
	rinput = /color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,
	jsre = /=\?(&|$)/,
	rquery = /\?/,
	rts = /(\?|&)_=.*?(&|$)/,
	rurl = /^(\w+:)?\/\/([^\/?#]+)/,
	r20 = /%20/g;

jQuery.fn.extend({
	// Keep a copy of the old load
	_load: jQuery.fn.load,

	load: function( url, params, callback ) {
		///	<summary>
		///		Carga HTML de un archivo remoto y lo inserta en el DOM. De forma predeterminada, realiza una solicitud GET, pero si se incluyen parámetros
		///		entonces se realiza una solicitud POST.
		///	</summary>
		///	<param name="url" type="String">La dirección URL de la página HTML que se va a cargar.</param>
		///	<param name="data" optional="true" type="Map">Pares clave-valor que se enviarán al servidor.</param>
		///	<param name="callback" optional="true" type="Function">La función a la que se llama cuando se completa la solicitud de AJAX. Debe asignar una function(responseText, textStatus, XMLHttpRequest) como esta, que asigna el elemento DOM insertado.</param>
		///	<returns type="jQuery" />

		if ( typeof url !== "string" ) {
			return this._load( url );

		// Don't do a request if no elements are being requested
		} else if ( !this.length ) {
			return this;
		}

		var off = url.indexOf(" ");
		if ( off >= 0 ) {
			var selector = url.slice(off, url.length);
			url = url.slice(0, off);
		}

		// Default to a GET request
		var type = "GET";

		// If the second parameter was provided
		if ( params ) {
			// If it's a function
			if ( jQuery.isFunction( params ) ) {
				// We assume that it's the callback
				callback = params;
				params = null;

			// Otherwise, build a param string
			} else if ( typeof params === "object" ) {
				params = jQuery.param( params, jQuery.ajaxSettings.traditional );
				type = "POST";
			}
		}

		var self = this;

		// Request the remote document
		jQuery.ajax({
			url: url,
			type: type,
			dataType: "html",
			data: params,
			complete: function( res, status ) {
				// If successful, inject the HTML into all the matched elements
				if ( status === "success" || status === "notmodified" ) {
					// See if a selector was specified
					self.html( selector ?
						// Create a dummy div to hold the results
						jQuery("<div />")
							// inject the contents of the document in, removing the scripts
							// to avoid any 'Permission Denied' errors in IE
							.append(res.responseText.replace(rscript, ""))

							// Locate the specified elements
							.find(selector) :

						// If not, just inject the full result
						res.responseText );
				}

				if ( callback ) {
					self.each( callback, [res.responseText, status, res] );
				}
			}
		});

		return this;
	},

	serialize: function() {
		///	<summary>
		///		Serializa un conjunto de elementos de entrada en una cadena de datos.
		///	</summary>
		///	<returns type="String">El resultado serializado</returns>

		return jQuery.param(this.serializeArray());
	},
	serializeArray: function() {
		///	<summary>
		///		Serializa todos los formularios y elementos de formulario, pero devuelve una estructura de datos JSON.
		///	</summary>
		///	<returns type="String">Estructura de datos JSON que representa los elementos serializados.</returns>

		return this.map(function() {
			return this.elements ? jQuery.makeArray(this.elements) : this;
		})
		.filter(function() {
			return this.name && !this.disabled &&
				(this.checked || rselectTextarea.test(this.nodeName) ||
					rinput.test(this.type));
		})
		.map(function( i, elem ) {
			var val = jQuery(this).val();

			return val == null ?
				null :
				jQuery.isArray(val) ?
					jQuery.map( val, function( val, i ) {
						return { name: elem.name, value: val };
					}) :
					{ name: elem.name, value: val };
		}).get();
	}
});

// Attach a bunch of functions for handling common AJAX events
//	jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), function( i, o ) {
//		jQuery.fn[o] = function( f ) {
//			return this.bind(o, f);
//		};
//	});

jQuery.fn["ajaxStart"] = function( f ) {
	///	<summary>
	///		Adjuntar una función que se ejecute siempre que se inicie una solicitud AJAX y no haya ninguna activa. Este es un evento AJAX.
	///	</summary>
	///	<param name="f" type="Function">La función que se va a ejecutar.</param>
	///	<returns type="jQuery" />

	return this.bind("ajaxStart", f);
};

jQuery.fn["ajaxStop"] = function( f ) {
	///	<summary>
	///		Adjuntar una función que se ejecute siempre que finalicen todas las solicitudes AJAX. Este es un evento AJAX.
	///	</summary>
	///	<param name="f" type="Function">La función que se va a ejecutar.</param>
	///	<returns type="jQuery" />

	return this.bind("ajaxStop", f);
};

jQuery.fn["ajaxComplete"] = function( f ) {
	///	<summary>
	///		Adjuntar una función que se ejecute siempre que se complete una solicitud AJAX. Este es un evento AJAX.
	///	</summary>
	///	<param name="f" type="Function">La función que se va a ejecutar.</param>
	///	<returns type="jQuery" />

	return this.bind("ajaxComplete", f);
};

jQuery.fn["ajaxError"] = function( f ) {
	///	<summary>
	///		Adjuntar una función que se ejecute siempre que no se pueda completar una solicitud AJAX. Este es un evento AJAX.
	///	</summary>
	///	<param name="f" type="Function">La función que se va a ejecutar.</param>
	///	<returns type="jQuery" />

	return this.bind("ajaxError", f);
};

jQuery.fn["ajaxSuccess"] = function( f ) {
	///	<summary>
	///		Adjuntar una función que se ejecute siempre que se complete una solicitud AJAX correctamente. Este es un evento AJAX.
	///	</summary>
	///	<param name="f" type="Function">La función que se va a ejecutar.</param>
	///	<returns type="jQuery" />

	return this.bind("ajaxSuccess", f);
};

jQuery.fn["ajaxSend"] = function( f ) {
	///	<summary>
	///		Adjuntar una función que se ejecute antes de que se envíe una solicitud AJAX. Este es un evento AJAX.
	///	</summary>
	///	<param name="f" type="Function">La función que se va a ejecutar.</param>
	///	<returns type="jQuery" />

	return this.bind("ajaxSend", f);
};

jQuery.extend({

	get: function( url, data, callback, type ) {
		///	<summary>
		///		Carga una página remota mediante una solicitud GET HTTP.
		///	</summary>
		///	<param name="url" type="String">La dirección URL de la página HTML que se va a cargar.</param>
		///	<param name="data" optional="true" type="Map">Pares clave-valor que se enviarán al servidor.</param>
		///	<param name="callback" optional="true" type="Function">La función a la que se llama cuando se completa la solicitud de AJAX. Debe asignar una function(responseText, textStatus) como esta, que asigna las opciones de esta solicitud AJAX.</param>
		///	<param name="type" optional="true" type="String">Tipo de datos que se van a devolver para la función de devolución de llamada. Los valores válidos son xml, html, script, json, text, _default.</param>
		///	<returns type="XMLHttpRequest" />

		// shift arguments if data argument was omited
		if ( jQuery.isFunction( data ) ) {
			type = type || callback;
			callback = data;
			data = null;
		}

		return jQuery.ajax({
			type: "GET",
			url: url,
			data: data,
			success: callback,
			dataType: type
		});
	},

	getScript: function( url, callback ) {
		///	<summary>
		///		Carga y ejecuta un archivo JavaScript local mediante una solicitud GET HTTP.
		///	</summary>
		///	<param name="url" type="String">La dirección URL del script que se va a cargar.</param>
		///	<param name="callback" optional="true" type="Function">La función a la que se llama cuando se completa la solicitud de AJAX. Debe asignar una function(data, textStatus) como esta, que asigna las opciones de la solicitud AJAX.</param>
		///	<returns type="XMLHttpRequest" />

		return jQuery.get(url, null, callback, "script");
	},

	getJSON: function( url, data, callback ) {
		///	<summary>
		///		Carga datos JSON mediante una solicitud GET HTTP.
		///	</summary>
		///	<param name="url" type="String">La dirección URL de los datos JSON que se van a cargar.</param>
		///	<param name="data" optional="true" type="Map">Pares clave-valor que se enviarán al servidor.</param>
		///	<param name="callback" optional="true" type="Function">La función a la que se llama cuando se completa la solicitud AJAX si los datos se cargan correctamente. Debe asignar una function(data, textStatus) como esta, que asigna las opciones de esta solicitud AJAX.</param>
		///	<returns type="XMLHttpRequest" />

		return jQuery.get(url, data, callback, "json");
	},

	post: function( url, data, callback, type ) {
		///	<summary>
		///		Carga una página remota mediante una solicitud POST HTTP.
		///	</summary>
		///	<param name="url" type="String">La dirección URL de la página HTML que se va a cargar.</param>
		///	<param name="data" optional="true" type="Map">Pares clave-valor que se enviarán al servidor.</param>
		///	<param name="callback" optional="true" type="Function">La función a la que se llama cuando se completa la solicitud AJAX. Debe asignar una function(responseText, textStatus) como esta, que asigna las opciones de esta solicitud AJAX.</param>
		///	<param name="type" optional="true" type="String">Tipo de datos que se van a devolver para la función de devolución de llamada. Los valores válidos son xml, html, script, json, text, _default.</param>
		///	<returns type="XMLHttpRequest" />

		// shift arguments if data argument was omited
		if ( jQuery.isFunction( data ) ) {
			type = type || callback;
			callback = data;
			data = {};
		}

		return jQuery.ajax({
			type: "POST",
			url: url,
			data: data,
			success: callback,
			dataType: type
		});
	},

	ajaxSetup: function( settings ) {
		///	<summary>
		///		Establece la configuración global de las solicitudes AJAX.
		///	</summary>
		///	<param name="settings" type="Options">Conjunto de pares clave-valor que configuran la solicitud AJAX predeterminada.</param>

		jQuery.extend( jQuery.ajaxSettings, settings );
	},

	ajaxSettings: {
		url: location.href,
		global: true,
		type: "GET",
		contentType: "application/x-www-form-urlencoded",
		processData: true,
		async: true,
		/*
		timeout: 0,
		data: null,
		username: null,
		password: null,
		traditional: false,
		*/
		// Create the request object; Microsoft failed to properly
		// implement the XMLHttpRequest in IE7 (can't request local files),
		// so we use the ActiveXObject when it is available
		// This function can be overriden by calling jQuery.ajaxSetup
		xhr: window.XMLHttpRequest && (window.location.protocol !== "file:" || !window.ActiveXObject) ?
			function() {
				return new window.XMLHttpRequest();
			} :
			function() {
				try {
					return new window.ActiveXObject("Microsoft.XMLHTTP");
				} catch(e) {}
			},
		accepts: {
			xml: "application/xml, text/xml",
			html: "text/html",
			script: "text/javascript, application/javascript",
			json: "application/json, text/javascript",
			text: "text/plain",
			_default: "*/*"
		}
	},

	// Last-Modified header cache for next request
	lastModified: {},
	etag: {},

	ajax: function( origSettings ) {
		///	<summary>
		///		Cargar una página remota mediante una solicitud HTTP.
		///	</summary>
		///	<private />

		var s = jQuery.extend(true, {}, jQuery.ajaxSettings, origSettings);
		
		var jsonp, status, data,
			callbackContext = origSettings && origSettings.context || s,
			type = s.type.toUpperCase();

		// convert data if not already a string
		if ( s.data && s.processData && typeof s.data !== "string" ) {
			s.data = jQuery.param( s.data, s.traditional );
		}

		// Handle JSONP Parameter Callbacks
		if ( s.dataType === "jsonp" ) {
			if ( type === "GET" ) {
				if ( !jsre.test( s.url ) ) {
					s.url += (rquery.test( s.url ) ? "&" : "?") + (s.jsonp || "callback") + "=?";
				}
			} else if ( !s.data || !jsre.test(s.data) ) {
				s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
			}
			s.dataType = "json";
		}

		// Build temporary JSONP function
		if ( s.dataType === "json" && (s.data && jsre.test(s.data) || jsre.test(s.url)) ) {
			jsonp = s.jsonpCallback || ("jsonp" + jsc++);

			// Replace the =? sequence both in the query string and the data
			if ( s.data ) {
				s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
			}

			s.url = s.url.replace(jsre, "=" + jsonp + "$1");

			// We need to make sure
			// that a JSONP style response is executed properly
			s.dataType = "script";

			// Handle JSONP-style loading
			window[ jsonp ] = window[ jsonp ] || function( tmp ) {
				data = tmp;
				success();
				complete();
				// Garbage collect
				window[ jsonp ] = undefined;

				try {
					delete window[ jsonp ];
				} catch(e) {}

				if ( head ) {
					head.removeChild( script );
				}
			};
		}

		if ( s.dataType === "script" && s.cache === null ) {
			s.cache = false;
		}

		if ( s.cache === false && type === "GET" ) {
			var ts = now();

			// try replacing _= if it is there
			var ret = s.url.replace(rts, "$1_=" + ts + "$2");

			// if nothing was replaced, add timestamp to the end
			s.url = ret + ((ret === s.url) ? (rquery.test(s.url) ? "&" : "?") + "_=" + ts : "");
		}

		// If data is available, append data to url for get requests
		if ( s.data && type === "GET" ) {
			s.url += (rquery.test(s.url) ? "&" : "?") + s.data;
		}

		// Watch for a new set of requests
		if ( s.global && ! jQuery.active++ ) {
			jQuery.event.trigger( "ajaxStart" );
		}

		// Matches an absolute URL, and saves the domain
		var parts = rurl.exec( s.url ),
			remote = parts && (parts[1] && parts[1] !== location.protocol || parts[2] !== location.host);

		// If we're requesting a remote document
		// and trying to load JSON or Script with a GET
		if ( s.dataType === "script" && type === "GET" && remote ) {
			var head = document.getElementsByTagName("head")[0] || document.documentElement;
			var script = document.createElement("script");
			script.src = s.url;
			if ( s.scriptCharset ) {
				script.charset = s.scriptCharset;
			}

			// Handle Script loading
			if ( !jsonp ) {
				var done = false;

				// Attach handlers for all browsers
				script.onload = script.onreadystatechange = function() {
					if ( !done && (!this.readyState ||
							this.readyState === "loaded" || this.readyState === "complete") ) {
						done = true;
						success();
						complete();

						// Handle memory leak in IE
						script.onload = script.onreadystatechange = null;
						if ( head && script.parentNode ) {
							head.removeChild( script );
						}
					}
				};
			}

			// Use insertBefore instead of appendChild  to circumvent an IE6 bug.
			// This arises when a base node is used (#2709 and #4378).
			head.insertBefore( script, head.firstChild );

			// We handle everything using the script element injection
			return undefined;
		}

		var requestDone = false;

		// Create the request object
		var xhr = s.xhr();

		if ( !xhr ) {
			return;
		}

		// Open the socket
		// Passing null username, generates a login popup on Opera (#2865)
		if ( s.username ) {
			xhr.open(type, s.url, s.async, s.username, s.password);
		} else {
			xhr.open(type, s.url, s.async);
		}

		// Need an extra try/catch for cross domain requests in Firefox 3
		try {
			// Set the correct header, if data is being sent
			if ( s.data || origSettings && origSettings.contentType ) {
				xhr.setRequestHeader("Content-Type", s.contentType);
			}

			// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
			if ( s.ifModified ) {
				if ( jQuery.lastModified[s.url] ) {
					xhr.setRequestHeader("If-Modified-Since", jQuery.lastModified[s.url]);
				}

				if ( jQuery.etag[s.url] ) {
					xhr.setRequestHeader("If-None-Match", jQuery.etag[s.url]);
				}
			}

			// Set header so the called script knows that it's an XMLHttpRequest
			// Only send the header if it's not a remote XHR
			if ( !remote ) {
				xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
			}

			// Set the Accepts header for the server, depending on the dataType
			xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
				s.accepts[ s.dataType ] + ", */*" :
				s.accepts._default );
		} catch(e) {}

		// Allow custom headers/mimetypes and early abort
		if ( s.beforeSend && s.beforeSend.call(callbackContext, xhr, s) === false ) {
			// Handle the global AJAX counter
			if ( s.global && ! --jQuery.active ) {
				jQuery.event.trigger( "ajaxStop" );
			}

			// close opended socket
			xhr.abort();
			return false;
		}

		if ( s.global ) {
			trigger("ajaxSend", [xhr, s]);
		}

		// Wait for a response to come back
		var onreadystatechange = xhr.onreadystatechange = function( isTimeout ) {
			// The request was aborted
			if ( !xhr || xhr.readyState === 0 || isTimeout === "abort" ) {
				// Opera doesn't call onreadystatechange before this point
				// so we simulate the call
				if ( !requestDone ) {
					complete();
				}

				requestDone = true;
				if ( xhr ) {
					xhr.onreadystatechange = jQuery.noop;
				}

			// The transfer is complete and the data is available, or the request timed out
			} else if ( !requestDone && xhr && (xhr.readyState === 4 || isTimeout === "timeout") ) {
				requestDone = true;
				xhr.onreadystatechange = jQuery.noop;

				status = isTimeout === "timeout" ?
					"timeout" :
					!jQuery.httpSuccess( xhr ) ?
						"error" :
						s.ifModified && jQuery.httpNotModified( xhr, s.url ) ?
							"notmodified" :
							"success";

				var errMsg;

				if ( status === "success" ) {
					// Watch for, and catch, XML document parse errors
					try {
						// process the data (runs the xml through httpData regardless of callback)
						data = jQuery.httpData( xhr, s.dataType, s );
					} catch(err) {
						status = "parsererror";
						errMsg = err;
					}
				}

				// Make sure that the request was successful or notmodified
				if ( status === "success" || status === "notmodified" ) {
					// JSONP handles its own success callback
					if ( !jsonp ) {
						success();
					}
				} else {
					jQuery.handleError(s, xhr, status, errMsg);
				}

				// Fire the complete handlers
				complete();

				if ( isTimeout === "timeout" ) {
					xhr.abort();
				}

				// Stop memory leaks
				if ( s.async ) {
					xhr = null;
				}
			}
		};

		// Override the abort handler, if we can (IE doesn't allow it, but that's OK)
		// Opera doesn't fire onreadystatechange at all on abort
		try {
			var oldAbort = xhr.abort;
			xhr.abort = function() {
				if ( xhr ) {
					oldAbort.call( xhr );
				}

				onreadystatechange( "abort" );
			};
		} catch(e) { }

		// Timeout checker
		if ( s.async && s.timeout > 0 ) {
			setTimeout(function() {
				// Check to see if the request is still happening
				if ( xhr && !requestDone ) {
					onreadystatechange( "timeout" );
				}
			}, s.timeout);
		}

		// Send the data
		try {
			xhr.send( type === "POST" || type === "PUT" || type === "DELETE" ? s.data : null );
		} catch(e) {
			jQuery.handleError(s, xhr, null, e);
			// Fire the complete handlers
			complete();
		}

		// firefox 1.5 doesn't fire statechange for sync requests
		if ( !s.async ) {
			onreadystatechange();
		}

		function success() {
			// If a local callback was specified, fire it and pass it the data
			if ( s.success ) {
				s.success.call( callbackContext, data, status, xhr );
			}

			// Fire the global callback
			if ( s.global ) {
				trigger( "ajaxSuccess", [xhr, s] );
			}
		}

		function complete() {
			// Process result
			if ( s.complete ) {
				s.complete.call( callbackContext, xhr, status);
			}

			// The request was completed
			if ( s.global ) {
				trigger( "ajaxComplete", [xhr, s] );
			}

			// Handle the global AJAX counter
			if ( s.global && ! --jQuery.active ) {
				jQuery.event.trigger( "ajaxStop" );
			}
		}
		
		function trigger(type, args) {
			(s.context ? jQuery(s.context) : jQuery.event).trigger(type, args);
		}

		// return XMLHttpRequest to allow aborting the request etc.
		return xhr;
	},

	handleError: function( s, xhr, status, e ) {
		///	<summary>
		///		Este método es interno.
		///	</summary>
		///	<private />

		// If a local callback was specified, fire it
		if ( s.error ) {
			s.error.call( s.context || s, xhr, status, e );
		}

		// Fire the global callback
		if ( s.global ) {
			(s.context ? jQuery(s.context) : jQuery.event).trigger( "ajaxError", [xhr, s, e] );
		}
	},

	// Counter for holding the number of active queries
	active: 0,

	// Determines if an XMLHttpRequest was successful or not
	httpSuccess: function( xhr ) {
		///	<summary>
		///		Este método es interno.
		///	</summary>
		///	<private />

		try {
			// IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
			return !xhr.status && location.protocol === "file:" ||
				// Opera returns 0 when status is 304
				( xhr.status >= 200 && xhr.status < 300 ) ||
				xhr.status === 304 || xhr.status === 1223 || xhr.status === 0;
		} catch(e) {}

		return false;
	},

	// Determines if an XMLHttpRequest returns NotModified
	httpNotModified: function( xhr, url ) {
		///	<summary>
		///		Este método es interno.
		///	</summary>
		///	<private />

		var lastModified = xhr.getResponseHeader("Last-Modified"),
			etag = xhr.getResponseHeader("Etag");

		if ( lastModified ) {
			jQuery.lastModified[url] = lastModified;
		}

		if ( etag ) {
			jQuery.etag[url] = etag;
		}

		// Opera returns 0 when status is 304
		return xhr.status === 304 || xhr.status === 0;
	},

	httpData: function( xhr, type, s ) {
		///	<summary>
		///		Este método es interno.
		///	</summary>
		///	<private />

		var ct = xhr.getResponseHeader("content-type") || "",
			xml = type === "xml" || !type && ct.indexOf("xml") >= 0,
			data = xml ? xhr.responseXML : xhr.responseText;

		if ( xml && data.documentElement.nodeName === "parsererror" ) {
			jQuery.error( "parsererror" );
		}

		// Allow a pre-filtering function to sanitize the response
		// s is checked to keep backwards compatibility
		if ( s && s.dataFilter ) {
			data = s.dataFilter( data, type );
		}

		// The filter can actually parse the response
		if ( typeof data === "string" ) {
			// Get the JavaScript object, if JSON is used.
			if ( type === "json" || !type && ct.indexOf("json") >= 0 ) {
				data = jQuery.parseJSON( data );

			// If the type is "script", eval it in global context
			} else if ( type === "script" || !type && ct.indexOf("javascript") >= 0 ) {
				jQuery.globalEval( data );
			}
		}

		return data;
	},

	// Serialize an array of form elements or a set of
	// key/values into a query string
	param: function( a, traditional ) {
		///	<summary>
		///		Crear una representación serializada de una matriz o un objeto, aptos para usarlos en una cadena de consulta de dirección URL
		///		o una solicitud Ajax.
		///	</summary>
		///	<param name="a" type="Object">
		///		Matriz u objeto para serializar.
		///	</param>
		///	<param name="traditional" type="Boolean">
		///		Valor booleano que indica si se realiza una serialización "superficial" tradicional.
		///	</param>
		///	<returns type="String" />

		var s = [];
		
		// Set traditional to true for jQuery <= 1.3.2 behavior.
		if ( traditional === undefined ) {
			traditional = jQuery.ajaxSettings.traditional;
		}
		
		// If an array was passed in, assume that it is an array of form elements.
		if ( jQuery.isArray(a) || a.jquery ) {
			// Serialize the form elements
			jQuery.each( a, function() {
				add( this.name, this.value );
			});
			
		} else {
			// If traditional, encode the "old" way (the way 1.3.2 or older
			// did it), otherwise encode params recursively.
			for ( var prefix in a ) {
				buildParams( prefix, a[prefix] );
			}
		}

		// Return the resulting serialization
		return s.join("&").replace(r20, "+");

		function buildParams( prefix, obj ) {
			if ( jQuery.isArray(obj) ) {
				// Serialize array item.
				jQuery.each( obj, function( i, v ) {
					if ( traditional ) {
						// Treat each array item as a scalar.
						add( prefix, v );
					} else {
						// If array item is non-scalar (array or object), encode its
						// numeric index to resolve deserialization ambiguity issues.
						// Note that rack (as of 1.0.0) can't currently deserialize
						// nested arrays properly, and attempting to do so may cause
						// a server error. Possible fixes are to modify rack's
						// deserialization algorithm or to provide an option or flag
						// to force array serialization to be shallow.
						buildParams( prefix + "[" + ( typeof v === "object" || jQuery.isArray(v) ? i : "" ) + "]", v );
					}
				});
					
			} else if ( !traditional && obj != null && typeof obj === "object" ) {
				// Serialize object item.
				jQuery.each( obj, function( k, v ) {
					buildParams( prefix + "[" + k + "]", v );
				});
					
			} else {
				// Serialize scalar item.
				add( prefix, obj );
			}
		}

		function add( key, value ) {
			// If value is a function, invoke it and return its value
			value = jQuery.isFunction(value) ? value() : value;
			s[ s.length ] = encodeURIComponent(key) + "=" + encodeURIComponent(value);
		}
	}
});
var elemdisplay = {},
	rfxtypes = /toggle|show|hide/,
	rfxnum = /^([+-]=)?([\d+-.]+)(.*)$/,
	timerId,
	fxAttrs = [
		// height animations
		[ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
		// width animations
		[ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
		// opacity animations
		[ "opacity" ]
	];

jQuery.fn.extend({
	show: function( speed, callback ) {
		///	<summary>
		///		Mostrar todos los elementos coincidentes con una animación fluida y activando una devolución de llamada opcional al finalizar.
		///	</summary>
		///	<param name="speed" type="String">Cadena que representa una de las tres velocidades definidas ('slow', 'normal' o 'fast') o
		///		el número de milisegundos que se ejecuta la animación</param>
		///	<param name="callback" optional="true" type="Function">Función que se ejecuta cuando se completa la animación, una vez para cada elemento animado. Debe asignar una función callback() como esta, que será el elemento DOM que se va a animar.</param>
		///	<returns type="jQuery" />

		if ( speed || speed === 0) {
			return this.animate( genFx("show", 3), speed, callback);

		} else {
			for ( var i = 0, l = this.length; i < l; i++ ) {
				var old = jQuery.data(this[i], "olddisplay");

				this[i].style.display = old || "";

				if ( jQuery.css(this[i], "display") === "none" ) {
					var nodeName = this[i].nodeName, display;

					if ( elemdisplay[ nodeName ] ) {
						display = elemdisplay[ nodeName ];

					} else {
						var elem = jQuery("<" + nodeName + " />").appendTo("body");

						display = elem.css("display");

						if ( display === "none" ) {
							display = "block";
						}

						elem.remove();

						elemdisplay[ nodeName ] = display;
					}

					jQuery.data(this[i], "olddisplay", display);
				}
			}

			// Set the display of the elements in a second loop
			// to avoid the constant reflow
			for ( var j = 0, k = this.length; j < k; j++ ) {
				this[j].style.display = jQuery.data(this[j], "olddisplay") || "";
			}

			return this;
		}
	},

	hide: function( speed, callback ) {
		///	<summary>
		///		Oculta todos los elementos coincidentes con una animación fluida y activando una devolución de llamada opcional al finalizar.
		///	</summary>
		///	<param name="speed" type="String">Cadena que representa una de las tres velocidades definidas ('slow', 'normal' o 'fast') o
		///		el número de milisegundos que se ejecuta la animación</param>
		///	<param name="callback" optional="true" type="Function">Función que se ejecuta cuando se completa la animación, una vez para cada elemento animado. Debe asignar una función callback() como esta, que será el elemento DOM que se va a animar.</param>
		///	<returns type="jQuery" />

		if ( speed || speed === 0 ) {
			return this.animate( genFx("hide", 3), speed, callback);

		} else {
			for ( var i = 0, l = this.length; i < l; i++ ) {
				var old = jQuery.data(this[i], "olddisplay");
				if ( !old && old !== "none" ) {
					jQuery.data(this[i], "olddisplay", jQuery.css(this[i], "display"));
				}
			}

			// Set the display of the elements in a second loop
			// to avoid the constant reflow
			for ( var j = 0, k = this.length; j < k; j++ ) {
				this[j].style.display = "none";
			}

			return this;
		}
	},

	// Save the old toggle function
	_toggle: jQuery.fn.toggle,

	toggle: function( fn, fn2 ) {
		///	<summary>
		///		Alterna la presentación de cada uno de los elementos del conjunto de elementos coincidentes.
		///	</summary>
		///	<returns type="jQuery" />

		var bool = typeof fn === "boolean";

		if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {
			this._toggle.apply( this, arguments );

		} else if ( fn == null || bool ) {
			this.each(function() {
				var state = bool ? fn : jQuery(this).is(":hidden");
				jQuery(this)[ state ? "show" : "hide" ]();
			});

		} else {
			this.animate(genFx("toggle", 3), fn, fn2);
		}

		return this;
	},

	fadeTo: function( speed, to, callback ) {
		///	<summary>
		///		Establece la opacidad de todos los elementos coincidentes en una opacidad especificada.
		///	</summary>
		///	<param name="speed" type="String">Cadena que representa una de las tres velocidades definidas ('slow', 'normal' o 'fast') o
		///		el número de milisegundos que se ejecuta la animación</param>
		///	<param name="callback" optional="true" type="Function">Función que se ejecuta cuando se completa la animación, una vez para cada elemento animado. Debe asignar una función callback() como esta, que será el elemento DOM que se va a animar.</param>
		///	<returns type="jQuery" />

		return this.filter(":hidden").css("opacity", 0).show().end()
					.animate({opacity: to}, speed, callback);
	},

	animate: function( prop, speed, easing, callback ) {
		///	<summary>
		///		Función para crear animaciones personalizadas.
		///	</summary>
		///	<param name="prop" type="Options">Conjunto de atributos de estilo que se van a animar y hasta cuándo.</param>
		///	<param name="speed" optional="true" type="String">Cadena que representa una de las tres velocidades definidas ('slow', 'normal' o 'fast') o
		///		el número de milisegundos que se ejecuta la animación</param>
		///	<param name="easing" optional="true" type="String">Nombre del efecto de suavizado que se desea usar. Hay dos valores integrados, 'linear' y 'swing'.</param>
		///	<param name="callback" optional="true" type="Function">Función que se ejecuta cuando se completa la animación, una vez para cada elemento animado. Debe asignar una función callback() como esta, que será el elemento DOM que se va a animar.</param>
		///	<returns type="jQuery" />

		var optall = jQuery.speed(speed, easing, callback);

		if ( jQuery.isEmptyObject( prop ) ) {
			return this.each( optall.complete );
		}

		return this[ optall.queue === false ? "each" : "queue" ](function() {
			var opt = jQuery.extend({}, optall), p,
				hidden = this.nodeType === 1 && jQuery(this).is(":hidden"),
				self = this;

			for ( p in prop ) {
				var name = p.replace(rdashAlpha, fcamelCase);

				if ( p !== name ) {
					prop[ name ] = prop[ p ];
					delete prop[ p ];
					p = name;
				}

				if ( prop[p] === "hide" && hidden || prop[p] === "show" && !hidden ) {
					return opt.complete.call(this);
				}

				if ( ( p === "height" || p === "width" ) && this.style ) {
					// Store display property
					opt.display = jQuery.css(this, "display");

					// Make sure that nothing sneaks out
					opt.overflow = this.style.overflow;
				}

				if ( jQuery.isArray( prop[p] ) ) {
					// Create (if needed) and add to specialEasing
					(opt.specialEasing = opt.specialEasing || {})[p] = prop[p][1];
					prop[p] = prop[p][0];
				}
			}

			if ( opt.overflow != null ) {
				this.style.overflow = "hidden";
			}

			opt.curAnim = jQuery.extend({}, prop);

			jQuery.each( prop, function( name, val ) {
				var e = new jQuery.fx( self, opt, name );

				if ( rfxtypes.test(val) ) {
					e[ val === "toggle" ? hidden ? "show" : "hide" : val ]( prop );

				} else {
					var parts = rfxnum.exec(val),
						start = e.cur(true) || 0;

					if ( parts ) {
						var end = parseFloat( parts[2] ),
							unit = parts[3] || "px";

						// We need to compute starting value
						if ( unit !== "px" ) {
							self.style[ name ] = (end || 1) + unit;
							start = ((end || 1) / e.cur(true)) * start;
							self.style[ name ] = start + unit;
						}

						// If a +=/-= token was provided, we're doing a relative animation
						if ( parts[1] ) {
							end = ((parts[1] === "-=" ? -1 : 1) * end) + start;
						}

						e.custom( start, end, unit );

					} else {
						e.custom( start, val, "" );
					}
				}
			});

			// For JS strict compliance
			return true;
		});
	},

	stop: function( clearQueue, gotoEnd ) {
		///	<summary>
		///		Detiene todas las animaciones actuales en los elementos especificados.
		///	</summary>
		///	<param name="clearQueue" optional="true" type="Boolean">True para borrar las animaciones que están en la cola de ejecución.</param>
		///	<param name="gotoEnd" optional="true" type="Boolean">True para mover el valor del elemento al final de su destino de animación.</param>
		///	<returns type="jQuery" />

		var timers = jQuery.timers;

		if ( clearQueue ) {
			this.queue([]);
		}

		this.each(function() {
			// go in reverse order so anything added to the queue during the loop is ignored
			for ( var i = timers.length - 1; i >= 0; i-- ) {
				if ( timers[i].elem === this ) {
					if (gotoEnd) {
						// force the next step to be the last
						timers[i](true);
					}

					timers.splice(i, 1);
				}
			}
		});

		// start the next in the queue if the last step wasn't forced
		if ( !gotoEnd ) {
			this.dequeue();
		}

		return this;
	}

});

// Generate shortcuts for custom animations
//	jQuery.each({
//		slideDown: genFx("show", 1),
//		slideUp: genFx("hide", 1),
//		slideToggle: genFx("toggle", 1),
//		fadeIn: { opacity: "show" },
//		fadeOut: { opacity: "hide" }
//	}, function( name, props ) {
//		jQuery.fn[ name ] = function( speed, callback ) {
//			return this.animate( props, speed, callback );
//		};
//	});

jQuery.fn[ "slideDown" ] = function( speed, callback ) {
	///	<summary>
	///		Mostrar todos los elementos coincidentes ajustando su alto.
	///	</summary>
	///	<param name="speed" type="String">Cadena que representa una de las tres velocidades definidas ('slow', 'normal' o 'fast') o
	///		el número de milisegundos que se ejecuta la animación</param>
	///	<param name="callback" optional="true" type="Function">Función que se ejecuta cuando se completa la animación, una vez para cada elemento animado. Debe asignar una función callback() como esta, que será el elemento DOM que se va a animar.</param>
	///	<returns type="jQuery" />

	return this.animate( genFx("show", 1), speed, callback );
};

jQuery.fn[ "slideUp" ] = function( speed, callback ) {
	///	<summary>
	///		Ocultar todos los elementos coincidentes ajustando su alto.
	///	</summary>
	///	<param name="speed" type="String">Cadena que representa una de las tres velocidades definidas ('slow', 'normal' o 'fast') o
	///		el número de milisegundos que se ejecuta la animación</param>
	///	<param name="callback" optional="true" type="Function">Función que se ejecuta cuando se completa la animación, una vez para cada elemento animado. Debe asignar una función callback() como esta, que será el elemento DOM que se va a animar.</param>
	///	<returns type="jQuery" />

	return this.animate( genFx("hide", 1), speed, callback );
};

jQuery.fn[ "slideToggle" ] = function( speed, callback ) {
	///	<summary>
	///		Alterna la visibilidad de todos los elementos coincidentes ajustando su alto.
	///	</summary>
	///	<param name="speed" type="String">Cadena que representa una de las tres velocidades definidas ('slow', 'normal' o 'fast') o
	///		el número de milisegundos que se ejecuta la animación</param>
	///	<param name="callback" optional="true" type="Function">Función que se ejecuta cuando se completa la animación, una vez para cada elemento animado. Debe asignar una función callback() como esta, que será el elemento DOM que se va a animar.</param>
	///	<returns type="jQuery" />

	return this.animate( genFx("toggle", 1), speed, callback );
};

jQuery.fn[ "fadeIn" ] = function( speed, callback ) {
	///	<summary>
	///		Aplica un fundido a todos los elementos coincidentes ajustando su opacidad.
	///	</summary>
	///	<param name="speed" type="String">Cadena que representa una de las tres velocidades definidas ('slow', 'normal' o 'fast') o
	///		el número de milisegundos que se ejecuta la animación</param>
	///	<param name="callback" optional="true" type="Function">Función que se ejecuta cuando se completa la animación, una vez para cada elemento animado. Debe asignar una función callback() como esta, que será el elemento DOM que se va a animar.</param>
	///	<returns type="jQuery" />

	return this.animate( { opacity: "show" }, speed, callback );
};

jQuery.fn[ "fadeOut" ] = function( speed, callback ) {
	///	<summary>
	///		Establece la opacidad de todos los elementos coincidentes en una opacidad especificada.
	///	</summary>
	///	<param name="speed" type="String">Cadena que representa una de las tres velocidades definidas ('slow', 'normal' o 'fast') o
	///		el número de milisegundos que se ejecuta la animación</param>
	///	<param name="callback" optional="true" type="Function">Función que se ejecuta cuando se completa la animación, una vez para cada elemento animado. Debe asignar una función callback() como esta, que será el elemento DOM que se va a animar.</param>
	///	<returns type="jQuery" />

	return this.animate( { opacity: "hide" }, speed, callback );
};

jQuery.extend({
	speed: function( speed, easing, fn ) {
		///	<summary>
		///		Este miembro es interno.
		///	</summary>
		///	<private />

		var opt = speed && typeof speed === "object" ? speed : {
			complete: fn || !fn && easing ||
				jQuery.isFunction( speed ) && speed,
			duration: speed,
			easing: fn && easing || easing && !jQuery.isFunction(easing) && easing
		};

		opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
			jQuery.fx.speeds[opt.duration] || jQuery.fx.speeds._default;

		// Queueing
		opt.old = opt.complete;
		opt.complete = function() {
			if ( opt.queue !== false ) {
				jQuery(this).dequeue();
			}
			if ( jQuery.isFunction( opt.old ) ) {
				opt.old.call( this );
			}
		};

		return opt;
	},

	easing: {
		linear: function( p, n, firstNum, diff ) {
			///	<summary>
			///		Este miembro es interno.
			///	</summary>
			///	<private />

			return firstNum + diff * p;
		},
		swing: function( p, n, firstNum, diff ) {
			///	<summary>
			///		Este miembro es interno.
			///	</summary>
			///	<private />

			return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
		}
	},

	timers: [],

	fx: function( elem, options, prop ) {
		///	<summary>
		///		Este miembro es interno.
		///	</summary>
		///	<private />

		this.options = options;
		this.elem = elem;
		this.prop = prop;

		if ( !options.orig ) {
			options.orig = {};
		}
	}

});

jQuery.fx.prototype = {
	// Simple function for setting a style value
	update: function() {
		///	<summary>
		///		Este miembro es interno.
		///	</summary>
		///	<private />

		if ( this.options.step ) {
			this.options.step.call( this.elem, this.now, this );
		}

		(jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );

		// Set display property to block for height/width animations
		if ( ( this.prop === "height" || this.prop === "width" ) && this.elem.style ) {
			this.elem.style.display = "block";
		}
	},

	// Get the current size
	cur: function( force ) {
		///	<summary>
		///		Este miembro es interno.
		///	</summary>
		///	<private />

		if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) ) {
			return this.elem[ this.prop ];
		}

		var r = parseFloat(jQuery.css(this.elem, this.prop, force));
		return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
	},

	// Start an animation from one number to another
	custom: function( from, to, unit ) {
		this.startTime = now();
		this.start = from;
		this.end = to;
		this.unit = unit || this.unit || "px";
		this.now = this.start;
		this.pos = this.state = 0;

		var self = this;
		function t( gotoEnd ) {
			return self.step(gotoEnd);
		}

		t.elem = this.elem;

		if ( t() && jQuery.timers.push(t) && !timerId ) {
			timerId = setInterval(jQuery.fx.tick, 13);
		}
	},

	// Simple 'show' function
	show: function() {
		///	<summary>
		///		Muestra cada uno de los elementos del conjunto de elementos coincidentes si están ocultos.
		///	</summary>

		// Remember where we started, so that we can go back to it later
		this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
		this.options.show = true;

		// Begin the animation
		// Make sure that we start at a small width/height to avoid any
		// flash of content
		this.custom(this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur());

		// Start by showing the element
		jQuery( this.elem ).show();
	},

	// Simple 'hide' function
	hide: function() {
		///	<summary>
		///		Oculta cada uno de los elementos del conjunto de elementos coincidentes si se muestran.
		///	</summary>

		// Remember where we started, so that we can go back to it later
		this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
		this.options.hide = true;

		// Begin the animation
		this.custom(this.cur(), 0);
	},

	// Each step of an animation
	step: function( gotoEnd ) {
		///	<summary>
		///		Este método es interno.
		///	</summary>
		///	<private />

		var t = now(), done = true;

		if ( gotoEnd || t >= this.options.duration + this.startTime ) {
			this.now = this.end;
			this.pos = this.state = 1;
			this.update();

			this.options.curAnim[ this.prop ] = true;

			for ( var i in this.options.curAnim ) {
				if ( this.options.curAnim[i] !== true ) {
					done = false;
				}
			}

			if ( done ) {
				if ( this.options.display != null ) {
					// Reset the overflow
					this.elem.style.overflow = this.options.overflow;

					// Reset the display
					var old = jQuery.data(this.elem, "olddisplay");
					this.elem.style.display = old ? old : this.options.display;

					if ( jQuery.css(this.elem, "display") === "none" ) {
						this.elem.style.display = "block";
					}
				}

				// Hide the element if the "hide" operation was done
				if ( this.options.hide ) {
					jQuery(this.elem).hide();
				}

				// Reset the properties, if the item has been hidden or shown
				if ( this.options.hide || this.options.show ) {
					for ( var p in this.options.curAnim ) {
						jQuery.style(this.elem, p, this.options.orig[p]);
					}
				}

				// Execute the complete function
				this.options.complete.call( this.elem );
			}

			return false;

		} else {
			var n = t - this.startTime;
			this.state = n / this.options.duration;

			// Perform the easing function, defaults to swing
			var specialEasing = this.options.specialEasing && this.options.specialEasing[this.prop];
			var defaultEasing = this.options.easing || (jQuery.easing.swing ? "swing" : "linear");
			this.pos = jQuery.easing[specialEasing || defaultEasing](this.state, n, 0, 1, this.options.duration);
			this.now = this.start + ((this.end - this.start) * this.pos);

			// Perform the next step of the animation
			this.update();
		}

		return true;
	}
};

jQuery.extend( jQuery.fx, {
	tick: function() {
		var timers = jQuery.timers;

		for ( var i = 0; i < timers.length; i++ ) {
			if ( !timers[i]() ) {
				timers.splice(i--, 1);
			}
		}

		if ( !timers.length ) {
			jQuery.fx.stop();
		}
	},
		
	stop: function() {
		clearInterval( timerId );
		timerId = null;
	},
	
	speeds: {
		slow: 600,
 		fast: 200,
 		// Default speed
 		_default: 400
	},

	step: {
		opacity: function( fx ) {
			jQuery.style(fx.elem, "opacity", fx.now);
		},

		_default: function( fx ) {
			if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {
				fx.elem.style[ fx.prop ] = (fx.prop === "width" || fx.prop === "height" ? Math.max(0, fx.now) : fx.now) + fx.unit;
			} else {
				fx.elem[ fx.prop ] = fx.now;
			}
		}
	}
});

if ( jQuery.expr && jQuery.expr.filters ) {
	jQuery.expr.filters.animated = function( elem ) {
		return jQuery.grep(jQuery.timers, function( fn ) {
			return elem === fn.elem;
		}).length;
	};
}

function genFx( type, num ) {
	var obj = {};

	jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function() {
		obj[ this ] = type;
	});

	return obj;
}
if ( "getBoundingClientRect" in document.documentElement ) {
	jQuery.fn.offset = function( options ) {
		///	<summary>
		///		Establecer las coordenadas actuales de cada elemento del conjunto de elementos coincidentes,
		///		relativas al documento.
		///	</summary>
		///	<param name="options" type="Object">
		///		Objeto que contiene las propiedades top y left, que son enteros que indican las nuevas
		///		coordenadas superior e izquierda para los elementos.
		///	</param>
		///	<returns type="jQuery" />

		var elem = this[0];

		if ( options ) { 
			return this.each(function( i ) {
				jQuery.offset.setOffset( this, options, i );
			});
		}

		if ( !elem || !elem.ownerDocument ) {
			return null;
		}

		if ( elem === elem.ownerDocument.body ) {
			return jQuery.offset.bodyOffset( elem );
		}

		var box = elem.getBoundingClientRect(), doc = elem.ownerDocument, body = doc.body, docElem = doc.documentElement,
			clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0,
			top  = box.top  + (self.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop ) - clientTop,
			left = box.left + (self.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft) - clientLeft;

		return { top: top, left: left };
	};

} else {
	jQuery.fn.offset = function( options ) {
		///	<summary>
		///		Establecer las coordenadas actuales de cada elemento del conjunto de elementos coincidentes,
		///		relativas al documento.
		///	</summary>
		///	<param name="options" type="Object">
		///		Objeto que contiene las propiedades top y left, que son enteros que indican las nuevas
		///		coordenadas superior e izquierda para los elementos.
		///	</param>
		///	<returns type="jQuery" />

		var elem = this[0];

		if ( options ) { 
			return this.each(function( i ) {
				jQuery.offset.setOffset( this, options, i );
			});
		}

		if ( !elem || !elem.ownerDocument ) {
			return null;
		}

		if ( elem === elem.ownerDocument.body ) {
			return jQuery.offset.bodyOffset( elem );
		}

		jQuery.offset.initialize();

		var offsetParent = elem.offsetParent, prevOffsetParent = elem,
			doc = elem.ownerDocument, computedStyle, docElem = doc.documentElement,
			body = doc.body, defaultView = doc.defaultView,
			prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,
			top = elem.offsetTop, left = elem.offsetLeft;

		while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
			if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {
				break;
			}

			computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;
			top  -= elem.scrollTop;
			left -= elem.scrollLeft;

			if ( elem === offsetParent ) {
				top  += elem.offsetTop;
				left += elem.offsetLeft;

				if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && /^t(able|d|h)$/i.test(elem.nodeName)) ) {
					top  += parseFloat( computedStyle.borderTopWidth  ) || 0;
					left += parseFloat( computedStyle.borderLeftWidth ) || 0;
				}

				prevOffsetParent = offsetParent, offsetParent = elem.offsetParent;
			}

			if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) {
				top  += parseFloat( computedStyle.borderTopWidth  ) || 0;
				left += parseFloat( computedStyle.borderLeftWidth ) || 0;
			}

			prevComputedStyle = computedStyle;
		}

		if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) {
			top  += body.offsetTop;
			left += body.offsetLeft;
		}

		if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {
			top  += Math.max( docElem.scrollTop, body.scrollTop );
			left += Math.max( docElem.scrollLeft, body.scrollLeft );
		}

		return { top: top, left: left };
	};
}

jQuery.offset = {
	initialize: function() {
		var body = document.body, container = document.createElement("div"), innerDiv, checkDiv, table, td, bodyMarginTop = parseFloat( jQuery.curCSS(body, "marginTop", true) ) || 0,
			html = "<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";

		jQuery.extend( container.style, { position: "absolute", top: 0, left: 0, margin: 0, border: 0, width: "1px", height: "1px", visibility: "hidden" } );

		container.innerHTML = html;
		body.insertBefore( container, body.firstChild );
		innerDiv = container.firstChild;
		checkDiv = innerDiv.firstChild;
		td = innerDiv.nextSibling.firstChild.firstChild;

		this.doesNotAddBorder = (checkDiv.offsetTop !== 5);
		this.doesAddBorderForTableAndCells = (td.offsetTop === 5);

		checkDiv.style.position = "fixed", checkDiv.style.top = "20px";
		// safari subtracts parent border width here which is 5px
		this.supportsFixedPosition = (checkDiv.offsetTop === 20 || checkDiv.offsetTop === 15);
		checkDiv.style.position = checkDiv.style.top = "";

		innerDiv.style.overflow = "hidden", innerDiv.style.position = "relative";
		this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);

		this.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop);

		body.removeChild( container );
		body = container = innerDiv = checkDiv = table = td = null;
		jQuery.offset.initialize = jQuery.noop;
	},

	bodyOffset: function( body ) {
		var top = body.offsetTop, left = body.offsetLeft;

		jQuery.offset.initialize();

		if ( jQuery.offset.doesNotIncludeMarginInBodyOffset ) {
			top  += parseFloat( jQuery.curCSS(body, "marginTop",  true) ) || 0;
			left += parseFloat( jQuery.curCSS(body, "marginLeft", true) ) || 0;
		}

		return { top: top, left: left };
	},
	
	setOffset: function( elem, options, i ) {
		// set position first, in-case top/left are set even on static elem
		if ( /static/.test( jQuery.curCSS( elem, "position" ) ) ) {
			elem.style.position = "relative";
		}
		var curElem   = jQuery( elem ),
			curOffset = curElem.offset(),
			curTop    = parseInt( jQuery.curCSS( elem, "top",  true ), 10 ) || 0,
			curLeft   = parseInt( jQuery.curCSS( elem, "left", true ), 10 ) || 0;

		if ( jQuery.isFunction( options ) ) {
			options = options.call( elem, i, curOffset );
		}

		var props = {
			top:  (options.top  - curOffset.top)  + curTop,
			left: (options.left - curOffset.left) + curLeft
		};
		
		if ( "using" in options ) {
			options.using.call( elem, props );
		} else {
			curElem.css( props );
		}
	}
};


jQuery.fn.extend({
	position: function() {
		///	<summary>
		///		Obtiene las posiciones superior e izquierda de un elemento con respecto al desplazamiento de su elemento primario.
		///	</summary>
		///	<returns type="Object">Objeto con dos propiedades Integer, 'top' y 'left'.</returns>

		if ( !this[0] ) {
			return null;
		}

		var elem = this[0],

		// Get *real* offsetParent
		offsetParent = this.offsetParent(),

		// Get correct offsets
		offset       = this.offset(),
		parentOffset = /^body|html$/i.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();

		// Subtract element margins
		// note: when an element has margin: auto the offsetLeft and marginLeft
		// are the same in Safari causing offset.left to incorrectly be 0
		offset.top  -= parseFloat( jQuery.curCSS(elem, "marginTop",  true) ) || 0;
		offset.left -= parseFloat( jQuery.curCSS(elem, "marginLeft", true) ) || 0;

		// Add offsetParent borders
		parentOffset.top  += parseFloat( jQuery.curCSS(offsetParent[0], "borderTopWidth",  true) ) || 0;
		parentOffset.left += parseFloat( jQuery.curCSS(offsetParent[0], "borderLeftWidth", true) ) || 0;

		// Subtract the two offsets
		return {
			top:  offset.top  - parentOffset.top,
			left: offset.left - parentOffset.left
		};
	},

	offsetParent: function() {
		///	<summary>
		///		Este método es interno.
		///	</summary>
		///	<private />

		return this.map(function() {
			var offsetParent = this.offsetParent || document.body;
			while ( offsetParent && (!/^body|html$/i.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) {
				offsetParent = offsetParent.offsetParent;
			}
			return offsetParent;
		});
	}
});


// Create scrollLeft and scrollTop methods
jQuery.each( ["Left", "Top"], function( i, name ) {
	var method = "scroll" + name;

	jQuery.fn[ method ] = function(val) {
		///	<summary>
		///		Obtiene y opcionalmente establece el desplazamiento izquierdo del primer elemento coincidente.
		///	</summary>
		///	<param name="val" type="Number" integer="true" optional="true">Número positivo que representa el desplazamiento izquierdo deseado.</param>
		///	<returns type="Number" integer="true">Desplazamiento izquierdo del primer elemento coincidente.</returns>

		var elem = this[0], win;
		
		if ( !elem ) {
			return null;
		}

		if ( val !== undefined ) {
			// Set the scroll offset
			return this.each(function() {
				win = getWindow( this );

				if ( win ) {
					win.scrollTo(
						!i ? val : jQuery(win).scrollLeft(),
						 i ? val : jQuery(win).scrollTop()
					);

				} else {
					this[ method ] = val;
				}
			});
		} else {
			win = getWindow( elem );

			// Return the scroll offset
			return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" : "pageXOffset" ] :
				jQuery.support.boxModel && win.document.documentElement[ method ] ||
					win.document.body[ method ] :
				elem[ method ];
		}
	};
});

// Create scrollLeft and scrollTop methods
jQuery.each( ["Left", "Top"], function( i, name ) {
	var method = "scroll" + name;

	jQuery.fn[ method ] = function(val) {
		///	<summary>
		///		Obtiene y opcionalmente establece el desplazamiento superior del primer elemento coincidente.
		///	</summary>
		///	<param name="val" type="Number" integer="true" optional="true">Número positivo que representa el desplazamiento superior deseado.</param>
		///	<returns type="Number" integer="true">Desplazamiento superior del primer elemento coincidente.</returns>

		var elem = this[0], win;
		
		if ( !elem ) {
			return null;
		}

		if ( val !== undefined ) {
			// Set the scroll offset
			return this.each(function() {
				win = getWindow( this );

				if ( win ) {
					win.scrollTo(
						!i ? val : jQuery(win).scrollLeft(),
						 i ? val : jQuery(win).scrollTop()
					);

				} else {
					this[ method ] = val;
				}
			});
		} else {
			win = getWindow( elem );

			// Return the scroll offset
			return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" : "pageXOffset" ] :
				jQuery.support.boxModel && win.document.documentElement[ method ] ||
					win.document.body[ method ] :
				elem[ method ];
		}
	};
});

function getWindow( elem ) {
	return ("scrollTo" in elem && elem.document) ?
		elem :
		elem.nodeType === 9 ?
			elem.defaultView || elem.parentWindow :
			false;
}

// Create innerHeight, innerWidth, outerHeight and outerWidth methods
jQuery.each([ "Height" ], function( i, name ) {

	var type = name.toLowerCase();

	// innerHeight and innerWidth
	jQuery.fn["inner" + name] = function() {
		///	<summary>
		///		Obtiene el alto interior del primer elemento coincidente, sin incluir el borde pero sí el espaciado interno.
		///	</summary>
		///	<returns type="Number" integer="true">Alto exterior del primer elemento coincidente.</returns>

		return this[0] ?
			jQuery.css( this[0], type, false, "padding" ) :
			null;
	};

	// outerHeight and outerWidth
	jQuery.fn["outer" + name] = function( margin ) {
		///	<summary>
		///		Obtiene el alto exterior del primer elemento coincidente, sin incluir el borde pero sí el espaciado interno de forma predeterminada.
		///	</summary>
		///	<param name="margins" type="Map">Conjunto de pares clave-valor que especifican las opciones del método.</param>
		///	<returns type="Number" integer="true">Alto exterior del primer elemento coincidente.</returns>

		return this[0] ?
			jQuery.css( this[0], type, false, margin ? "margin" : "border" ) :
			null;
	};

	jQuery.fn[ type ] = function( size ) {
		///	<summary>
		///		Establece el alto CSS de cada elemento coincidente. Si no se específico
		///		ninguna unidad explícita (como 'em' o '%'), se agrega &quot;px&quot; al ancho. Si no se especifica ningún parámetro, obtiene
		///		el alto en píxeles actual calculado del primer elemento coincidente.
		///		Parte de CSS
		///	</summary>
		///	<returns type="jQuery" type="jQuery" />
		///	<param name="cssProperty" type="String">
		///		Establecer la propiedad CSS en el valor especificado. Omitir para obtener el valor del primer elemento coincidente.
		///	</param>

		// Get window width or height
		var elem = this[0];
		if ( !elem ) {
			return size == null ? null : this;
		}
		
		if ( jQuery.isFunction( size ) ) {
			return this.each(function( i ) {
				var self = jQuery( this );
				self[ type ]( size.call( this, i, self[ type ]() ) );
			});
		}

		return ("scrollTo" in elem && elem.document) ? // does it walk and quack like a window?
			// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
			elem.document.compatMode === "CSS1Compat" && elem.document.documentElement[ "client" + name ] ||
			elem.document.body[ "client" + name ] :

			// Get document width or height
			(elem.nodeType === 9) ? // is it a document
				// Either scroll[Width/Height] or offset[Width/Height], whichever is greater
				Math.max(
					elem.documentElement["client" + name],
					elem.body["scroll" + name], elem.documentElement["scroll" + name],
					elem.body["offset" + name], elem.documentElement["offset" + name]
				) :

				// Get or set width or height on the element
				size === undefined ?
					// Get width or height on the element
					jQuery.css( elem, type ) :

					// Set the width or height on the element (default to pixels if value is unitless)
					this.css( type, typeof size === "string" ? size : size + "px" );
	};

});

// Create innerHeight, innerWidth, outerHeight and outerWidth methods
jQuery.each([ "Width" ], function( i, name ) {

	var type = name.toLowerCase();

	// innerHeight and innerWidth
	jQuery.fn["inner" + name] = function() {
		///	<summary>
		///		Obtiene el ancho interior del primer elemento coincidente, sin incluir el borde pero sí el espaciado interno.
		///	</summary>
		///	<returns type="Number" integer="true">Ancho exterior del primer elemento coincidente.</returns>

		return this[0] ?
			jQuery.css( this[0], type, false, "padding" ) :
			null;
	};

	// outerHeight and outerWidth
	jQuery.fn["outer" + name] = function( margin ) {
		///	<summary>
		///		Obtiene el ancho exterior del primer elemento coincidente, sin incluir el borde pero sí el espaciado interno de forma predeterminada.
		///	</summary>
		///	<param name="margin" type="Map">Conjunto de pares clave-valor que especifican las opciones del método.</param>
		///	<returns type="Number" integer="true">Ancho exterior del primer elemento coincidente.</returns>

		return this[0] ?
			jQuery.css( this[0], type, false, margin ? "margin" : "border" ) :
			null;
	};

	jQuery.fn[ type ] = function( size ) {
		///	<summary>
		///		Establece el ancho CSS de cada elemento coincidente. Si no se específico
		///		ninguna unidad explícita (como 'em' o '%'), se agrega &quot;px&quot; al ancho. Si no se especifica ningún parámetro, obtiene
		///		el ancho en píxeles actual calculado del primer elemento coincidente.
		///		Parte de CSS
		///	</summary>
		///	<returns type="jQuery" type="jQuery" />
		///	<param name="cssProperty" type="String">
		///		Establecer la propiedad CSS en el valor especificado. Omitir para obtener el valor del primer elemento coincidente.
		///	</param>

		// Get window width or height
		var elem = this[0];
		if ( !elem ) {
			return size == null ? null : this;
		}
		
		if ( jQuery.isFunction( size ) ) {
			return this.each(function( i ) {
				var self = jQuery( this );
				self[ type ]( size.call( this, i, self[ type ]() ) );
			});
		}

		return ("scrollTo" in elem && elem.document) ? // does it walk and quack like a window?
			// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
			elem.document.compatMode === "CSS1Compat" && elem.document.documentElement[ "client" + name ] ||
			elem.document.body[ "client" + name ] :

			// Get document width or height
			(elem.nodeType === 9) ? // is it a document
				// Either scroll[Width/Height] or offset[Width/Height], whichever is greater
				Math.max(
					elem.documentElement["client" + name],
					elem.body["scroll" + name], elem.documentElement["scroll" + name],
					elem.body["offset" + name], elem.documentElement["offset" + name]
				) :

				// Get or set width or height on the element
				size === undefined ?
					// Get width or height on the element
					jQuery.css( elem, type ) :

					// Set the width or height on the element (default to pixels if value is unitless)
					this.css( type, typeof size === "string" ? size : size + "px" );
	};

});

// Expose jQuery to the global object
window.jQuery = window.$ = jQuery;

})(window);
