Javascript, Jquery y Ajax

210
Fundamentos de jQuery Contenidos 1 Bienvenido/a o 1.1 Obtener el Material de Aprendizaje o 1.2 Software o 1.3 Añadir JavaScript a una Página o 1.4 Depuración del Código JavaScript o 1.5 Ejercicios o 1.6 Convenciones Utilizadas en el Libro o 1.7 Notas de la Traducción o 1.8 Material de Referencia 2 Conceptos Básicos de JavaScript o 2.1 Introducción o 2.2 Sintaxis Básica o 2.3 Operadores 2.3.1 Operadores Básicos 2.3.2 Operaciones con Números y Cadenas de Caracteres 2.3.3 Operadores Lógicos 2.3.4 Operadores de Comparación o 2.4 Código Condicional 2.4.1 Elementos Verdaderos y Falsos 2.4.2 Variables Condicionales Utilizando el Operador Ternario 2.4.3 Declaración Switch o 2.5 Bucles 2.5.1 Bucles Utilizando For 2.5.2 Bucles Utilizando While 2.5.3 Bucles Utilizando Do-while 2.5.4 Break y Continue o 2.6 Palabras Reservadas o 2.7 Vectores o 2.8 Objetos o 2.9 Funciones

description

Para JS

Transcript of Javascript, Jquery y Ajax

Fundamentos de jQueryContenidos 1Bienvenido/a 1.1Obtener el Material de Aprendizaje 1.2Software 1.3Aadir JavaScript a una Pgina 1.4Depuracin del Cdigo JavaScript 1.5Ejercicios 1.6Convenciones Utilizadas en el Libro 1.7Notas de la Traduccin 1.8Material de Referencia 2Conceptos Bsicos de JavaScript 2.1Introduccin 2.2Sintaxis Bsica 2.3Operadores 2.3.1Operadores Bsicos 2.3.2Operaciones con Nmeros y Cadenas de Caracteres 2.3.3Operadores Lgicos 2.3.4Operadores de Comparacin 2.4Cdigo Condicional 2.4.1Elementos Verdaderos y Falsos 2.4.2Variables Condicionales Utilizando el Operador Ternario 2.4.3Declaracin Switch 2.5Bucles 2.5.1Bucles Utilizando For 2.5.2Bucles Utilizando While 2.5.3Bucles Utilizando Do-while 2.5.4Break y Continue 2.6Palabras Reservadas 2.7Vectores 2.8Objetos 2.9Funciones 2.9.1Utilizacin de Funciones 2.9.2Funciones Annimas Autoejecutables 2.9.3Funciones como Argumentos 2.10Determinacin del Tipo de Variable 2.11La palabra clavethis 2.12Alcance 2.13Clausuras 3Conceptos Bsicos de jQuery 3.1$(document).ready() 3.2Seleccin de Elementos 3.2.1Comprobar Selecciones 3.2.2Guardar Selecciones 3.2.3Refinamiento y Filtrado de Selecciones 3.2.4Seleccin de Elementos de un Formulario 3.3Trabajar con Selecciones 3.3.1Encadenamiento 3.3.2Obtenedores (Getters) & Establecedores (Setters) 3.4CSS, Estilos, & Dimensiones 3.4.1Utilizar Clases para Aplicar Estilos CSS 3.4.2Dimensiones 3.5Atributos 3.6Recorrer el DOM 3.7Manipulacin de Elementos 3.7.1Obtener y Establecer Informacin en Elementos 3.7.2Mover, Copiar y Remover Elementos 3.7.3Crear Nuevos Elementos 3.7.4Manipulacin de Atributos 3.8Ejercicios 3.8.1Selecciones 3.8.2Recorrer el DOM 3.8.3Manipulacin 4El ncleo de jQuery 4.1$vs$() 4.2Mtodos Utilitarios 4.3Comprobacin de Tipos 4.4El Mtodo Data 4.5Deteccin de Navegadores y Caractersticas 4.6Evitar Conflictos con Otras Bibliotecas JavaScript 5Eventos 5.1Introduccin 5.2Vincular Eventos a Elementos 5.2.1Vincular Eventos para Ejecutar una vez 5.2.2Desvincular Eventos 5.2.3Espacios de Nombres para Eventos 5.2.4Vinculacin de Mltiples Eventos 5.3El Objeto del Evento 5.4Ejecucin automtica de Controladores de Eventos 5.5Incrementar el Rendimiento con la Delegacin de Eventos 5.5.1Desvincular Eventos Delegados 5.6Funciones Auxiliares de Eventos 5.6.1$.fn.hover 5.6.2$.fn.toggle 5.7Ejercicios 5.7.1Crear una Sugerencia para una Caja de Ingreso de Texto 5.7.2Aadir una Navegacin por Pestaas 6Efectos 6.1Introduccin 6.2Efectos Incorporados en la Biblioteca 6.2.1Cambiar la Duracin de los Efectos 6.2.2Realizar una Accin Cuando un Efecto fue Ejecutado 6.3Efectos Personalizados con$.fn.animate 6.3.1Easing 6.4Control de los Efectos 6.5Ejercicios 6.5.1Mostrar Texto Oculto 6.5.2Crear un Men Desplegable 6.5.3Crear un Slideshow 7Ajax 7.1Introduccin 7.2Conceptos Clave 7.2.1GET vs.POST 7.2.2Tipos de Datos 7.2.3Asincronismo 7.2.4Polticas de Mismo Origen y JSONP 7.2.5Ajax y Firebug 7.3Mtodos Ajax de jQuery 7.3.1$.ajax 7.3.2Mtodos Convenientes 7.3.3$.fn.load 7.4Ajax y Formularios 7.5Trabajar con JSONP 7.6Eventos Ajax 7.7Ejercicios 7.7.1Cargar Contenido Externo 7.7.2Cargar Contenido Utilizando JSON 8Extensiones 8.1Qu es una Extensin? 8.2Crear una Extensin Bsica 8.3Encontrar y Evaluar Extensiones 8.4Escribir Extensiones 8.5Escribir Extensiones con Mantenimiento de Estado Utilizando Widget Factory de jQuery UI 8.5.1Aadir Mtodos a un Widget 8.5.2Trabajar con las Opciones del Widget 8.5.3Aadir Funciones de Devolucin de Llamada 8.5.4Limpieza 8.5.5Conclusin 8.6Ejercicios 8.6.1Realizar una Tabla Ordenable 8.6.2Escribir una Extensin Para Cambiar el Color de Fondo en Tablas 9Mejores Prcticas para Aumentar el Rendimiento 9.1Guardar la Longitud en Bucles 9.2Aadir Nuevo Contenido por Fuera de un Bucle 9.3No Repetirse 9.4Cuidado con las Funciones Annimas 9.5Optimizacin de Selectores 9.5.1Selectores basados en ID 9.5.2Especificidad 9.5.3Evitar el Selector Universal 9.6Utilizar la Delegacin de Eventos 9.7Separar Elementos para Trabajar con Ellos 9.8Utilizar Estilos en Cascada para Cambios de CSS en Varios Elementos 9.9Utilizar$.dataen Lugar de$.fn.data 9.10No Actuar en Elementos no Existentes 9.11Definicin de Variables 9.12Condicionales 9.13No Tratar a jQuery como si fuera una Caja Negra 10Organizacin del Cdigo 10.1Introduccin 10.1.1Conceptos Clave 10.2Encapsulacin 10.2.1El Objeto Literal 10.2.2El Patrn Modular 10.3Gestin de Dependencias 10.3.1Obtener RequireJS 10.3.2Utilizar RequireJS con jQuery 10.3.3Crear Mdulos Reusables con RequireJS 10.3.4Optimizar el Cdigo con las Herramientas de RequireJS 10.4Ejercicios 10.4.1Crear un Mdulo Portlet 11Eventos Personalizados 11.1Introduccin a los Eventos Personalizados 11.1.1Un Ejemplo de Aplicacin 12Funciones y ejecuciones diferidas a travs del objeto$.Deferred 12.1Introduccin 12.2El objeto diferido y Ajax 12.2.1deferred.then 12.3Creacin de objetos diferidos con$.Deferred 12.3.1deferred.pipe 12.3.2$.when

1Bienvenido/ajQuery se est convirtiendo rpidamente en una herramienta que todo desarrollador de interfaces web debera de conocer. El propsito de este libro es proveer un resumen de la biblioteca, de tal forma que para cuando lo haya terminado de leer, ser capaz de realizar tareas bsicas utilizando jQuery y tendr una slida base para continuar el aprendizaje. El libro fue diseado para ser utilizado como material en un saln de clases, pero tambin puede ser til para estudiarlo de forma individual.La modalidad de trabajo es la siguiente: En primer lugar se dedicar tiempo a comprender un concepto para luego realizar un ejercicio relacionado. Algunos de los ejercicios pueden llegar a ser triviales, mientras que otros no tanto. El objetivo es aprender a resolver de manera fcil lo que normalmente se resolvera con jQuery. Las soluciones a todos los ejercicios estn incluidas en el mismo material de aprendizaje.1.1Obtener el Material de AprendizajeEl material de aprendizaje y el cdigo fuente de los ejemplos que se utilizan en el libro estn hospedados enun repositorio de Github. Desde all es posible descargar un archivo .zip o .tar con el cdigo para utilizar en un servidor web.Si usted suele utilizarGit, es bienvenido de clonar o modificar el repositorio.1.2SoftwarePara trabajar con los contenidos del libro, necesitar las siguientes herramientas: navegador web Firefox; laextensin Firebug, para Firefox; un editor de textos planos (comoNotepad++/Sublime Text 2para Windows,gedit/Katepara Linux oTextMatepara Mac OS X); para las secciones dedicadas a Ajax: Un servidor local (comoWAMPoMAMP) o un cliente FTP/SSH (comoFileZilla) para acceder a un servidor remoto.1.3Aadir JavaScript a una PginaExisten dos formas de insertar cdigo JavaScript dentro de una pgina: escribiendo cdigo en la misma (en ingles inline) o a travs de un archivo externo utilizando la etiqueta script. El orden en el cual se incluye el cdigo es importante: un cdigo que depende de otro debe ser incluido despus del que referencia (Ejemplo: Si la funcin B depende de A, el orden debe ser A,B y no B,A).Para mejorar el rendimiento de la pgina, el cdigo JavaScript debe ser incluido al final del HTML. Adems, cuando se trabaja en un ambiente de produccin con mltiples archivos JavaScript, stos deben ser combinados en un solo archivo.Ejemplo de cdigo JavaScript en lnea

console.log('hello'); Ejemplo de inclusin de un archivo externo JavaScript

1.4Depuracin del Cdigo JavaScriptLa utilizacin de una herramienta de depuracin es esencial para trabajar con JavaScript. Firefox provee un depurador a travs de la extensin Firebug; mientras queSafariyChromeya traen uno integrado.Cada depurador ofrece: un editor multi-linea para experimentar con JavaScript; un inspector para revisar el cdigo generado en la pgina; un visualizador de red o recursos, para examinar las peticiones que se realizan.Cuando usted este escribiendo cdigo JavaScript, podr utilizar alguno de los siguientes mtodos para enviar mensajes a la consola del depurador: console.log()para enviar y registrar mensajes generales; console.dir()para registrar un objeto y visualizar sus propiedades; console.warn()para registrar mensajes de alerta; console.error()para registrar mensajes de error.Existen otros mtodos para utilizar desde la consola, pero estos pueden variar segn el navegador. La consola adems provee la posibilidad de establecer puntos de interrupcin y observar expresiones en el cdigo con el fin de facilitar su depuracin.1.5EjerciciosLa mayora de los captulos concluyen con uno o ms ejercicios. En algunos, podr trabajar directamente con Firebug; en otros deber escribir cdigo JavaScript luego de incluir la biblioteca jQuery en el documento.An as, para completar ciertos ejercicios, necesitar consultar la documentacin oficial de jQuery. Aprender a encontrar respuestas, es una parte importante del proceso de aprendizaje.Estas son algunas sugerencias para hacer frente a los problemas: en primer lugar, asegrese de entender bien el problema que est tratando de resolver; luego, averige a qu elementos tendr que acceder con el fin de resolver el problema, y determine cmo accederlos. Puede utilizar Firebug para verificar que esta obteniendo el resultado esperado; finalmente, averige qu necesita hacer con esos elementos para resolver el problema. Puede ser til, antes de comenzar, escribir comentarios explicando lo que va a realizar.No tenga miedo de cometer errores. Tampoco trate en el primer intento escribir de forma perfecta su cdigo. Cometer errores y experimentar con soluciones es parte del proceso de aprendizaje y le ayudar a que sea un mejor desarrollador.Podr encontrar en la carpeta/ejercicios/solucionesejemplos de soluciones a los ejercicios del libro.1.6Convenciones Utilizadas en el LibroExisten una serie de convenciones utilizadas en el libro:Los mtodos que pueden ser llamados desde el objeto jQuery, sern referenciados como$.fn.nombreDelMetodo. Los mtodos que existen en el espacio de nombres (en inglsnamespace) de jQuery pero que no pueden ser llamados desde el objeto jQuery sern referenciados como$.nombreDelMetodo. Si esto no significa mucho para usted, no se preocupe ser ms claro a medida que vaya progresando en el libro.Ejemplo de un cdigo// el cdigo de ejemplo aparecer de esta formaLas remarcaciones aparecern de esta forma.NotaLas notas sobre algn tema aparecern de esta forma.1.7Notas de la Traduccin Debido a que el material tiene como fin el aprendizaje y la enseanza, el mismo se encuentra traducido a espaol formal (usted). Muchos conceptos tcnicos son nombrados en su versin traducida a espaol. Sin embargo, para tener de referencia, tambin se explica como es llamado en ingls. Los ejemplos y soluciones a ejercicios no estn completamente traducidos. Esto es debido a que, cuando est trabajando en un proyecto real, el cdigo que encuentre en otros sitios probablemente est en ingls. An as, se han traducido los comentarios incorporados en los cdigos de ejemplos y algunos textos particulares para facilitar la comprensin.1.8Material de ReferenciaExiste una gran cantidad de artculos que se ocupan de algn aspecto de jQuery. Algunos son excelentes pero otros, francamente, son errneos. Cuando lea un artculo sobre jQuery, este seguro que se est abarcando la misma versin de la biblioteca que est utilizando, y resstase a la tentacin de copiar y pegar el cdigo tmese un tiempo para poder entenderlo.A continuacin se listan una serie de excelentes recursos para utilizar durante el aprendizaje. El ms importante de todos es el cdigo fuente de jQuery, el cual contiene (en su formato sin comprimir) una completa documentacin a travs de comentarios. La biblioteca no es una caja negra el entendimiento de ella ir incrementndose exponencialmente si la revisa de vez en cuando y es muy recomendable que la guarde en los favoritos de su navegador para tenerla como gua de referencia. El cdigo fuente de jQuery Documentacin de jQuery Foro de jQuery Favoritos en Delicious Canal IRC #jquery en Freenode2Conceptos Bsicos de JavaScript2.1IntroduccinjQuery se encuentra escrito en JavaScript, un lenguaje de programacin muy rico y expresivo.El captulo est orientado a personas sin experiencia en el lenguaje, abarcando conceptos bsicos y problemas frecuentes que pueden presentarse al trabajar con el mismo. Por otro lado, la seccin puede ser beneficiosa para quienes utilicen otros lenguajes de programacin para entender las peculiaridades de JavaScript.Si usted esta interesado en aprender el lenguaje ms en profundidad, puede leer el libroJavaScript: The Good Partsescrito por Douglas Crockford.2.2Sintaxis BsicaComprensin de declaraciones, nombres de variables, espacios en blanco, y otras sintaxis bsicas de JavaScript.Declaracin simple de variablevar foo = 'hola mundo';Los espacios en blanco no tienen valor fuera de las comillasvar foo = 'hola mundo';Los parntesis indican prioridad2 * 3 + 5; // es igual a 11, la multiplicacin ocurre primero 2 * (3 + 5); // es igual a 16, por los parntesis, la suma ocurre primeroLa tabulacin mejora la lectura del cdigo, pero no posee ningn significado especialvar foo = function() { console.log('hola'); };2.3Operadores2.3.1Operadores BsicosLos operadores bsicos permiten manipular valores.Concatenacinvar foo = 'hola'; var bar = 'mundo'; console.log(foo + ' ' + bar); // la consola de depuracin muestra 'hola mundo'Multiplicacin y divisin2 * 3; 2 / 3;Incrementacin y decrementacinvar i = 1; var j = ++i; // incrementacin previa: j es igual a 2; i es igual a 2 var k = i++; // incrementacin posterior: k es igual a 2; i es igual a 32.3.2Operaciones con Nmeros y Cadenas de CaracteresEn JavaScript, las operaciones con nmeros y cadenas de caracteres (en inglsstrings) pueden ocasionar resultados no esperados.Suma vs.concatenacinvar foo = 1; var bar = '2'; console.log(foo + bar); // error: La consola de depuracin muestra 12Forzar a una cadena de caracteres actuar como un nmerovar foo = 1; var bar = '2'; // el constructor 'Number' obliga a la cadena comportarse como un nmero console.log(foo + Number(bar)); // la consola de depuracin muestra 3El constructorNumber, cuando es llamado como una funcin (como se muestra en el ejemplo) obliga a su argumento a comportarse como un nmero. Tambin es posible utilizar el operador desuma unaria, entregando el mismo resultado:Forzar a una cadena de caracteres actuar como un nmero (utilizando el operador de suma unaria)console.log(foo + +bar);2.3.3Operadores LgicosLos operadores lgicos permiten evaluar una serie de operandos utilizando operaciones AND y OR.Operadores lgicos AND y ORvar foo = 1; var bar = 0; var baz = 2; foo || bar; // devuelve 1, el cual es verdadero (true) bar || foo; // devuelve 1, el cual es verdadero (true) foo && bar; // devuelve 0, el cual es falso (false) foo && baz; // devuelve 2, el cual es verdadero (true) baz && foo; // devuelve 1, el cual es verdadero (true)El operador||(OR lgico) devuelve el valor del primer operando, si ste es verdadero; caso contrario devuelve el segundo operando. Si ambos operandos son falsos devuelve falso (false). El operador&&(AND lgico) devuelve el valor del primer operando si ste es falso; caso contrario devuelve el segundo operando. Cuando ambos valores son verdaderos devuelve verdadero (true), sino devuelve falso.Puede consultar la seccinElementos Verdaderos y Falsospara ms detalles sobre que valores se evalan comotruey cuales se evalan comofalse.NotaPuede que a veces note que algunos desarrolladores utilizan esta lgica en flujos de control en lugar de utilizar la declaracinif. Por ejemplo:// realizar algo con foo si foo es verdadero foo && doSomething(foo); // establecer bar igual a baz si baz es verdadero; // caso contrario, establecer a bar igual al // valor de createBar() var bar = baz || createBar();Este estilo de declaracin es muy elegante y conciso; pero puede ser difcil para leer (sobretodo para principiantes). Por eso se explcita, para reconocerlo cuando este leyendo cdigo. Sin embargo su utilizacin no es recomendable a menos que est cmodo con el concepto y su comportamiento.2.3.4Operadores de ComparacinLos operadores de comparacin permiten comprobar si determinados valores son equivalentes o idnticos.Operadores de Comparacinvar foo = 1; var bar = 0; var baz = '1'; var bim = 2; foo == bar; // devuelve falso (false) foo != bar; // devuelve verdadero (true) foo == baz; // devuelve verdadero (true); tenga cuidado foo === baz; // devuelve falso (false) foo !== baz; // devuelve verdadero (true) foo === parseInt(baz); // devuelve verdadero (true) foo > bim; // devuelve falso (false) bim > baz; // devuelve verdadero (true) foo 0 && height > 0 && !skip ? // entonces debe estar visible false : // si nos encontramos aqu, es porque el elemento posee ancho // y alto, pero adems es un , // entonces se verifica el valor del estilo display // aplicado a travs de CSS // para decidir si est oculto o no jQuery.curCSS(elem, "display") === "none"; }; jQuery.expr.filters.visible = function( elem ) { return !jQuery.expr.filters.hidden( elem ); };Eleccin de SelectoresLa eleccin de buenos selectores es un punto importante cuando se desea mejorar el rendimiento del cdigo. Una pequea especificidad por ejemplo, incluir el tipo de elemento (comodiv) cuando se realiza una seleccin por el nombre de clase puede ayudar bastante. Por eso, es recomendable darle algunas pistas a jQuery sobre en que lugar del documento puede encontrar lo que desea seleccionar. Por otro lado, demasiada especificidad puede ser perjudicial. Un selector como#miTabla thead tr th.especiales un exceso, lo mejor sera utilizar#miTabla th.especial.jQuery ofrece muchos selectores basados en atributos, que permiten realizar selecciones basadas en el contenido de los atributos utilizando simplificaciones de expresiones regulares.// encontrar todos los cuyo atributo rel terminan en "thinger" $("a[rel$='thinger']");Estos tipos de selectores pueden resultar tiles pero tambin ser muy lentos. Cuando sea posible, es recomendable realizar la seleccin utilizando IDs, nombres de clases y nombres de etiquetas.Si desea conocer ms sobre este asunto,Paul Irish realiz una gran presentacin sobre mejoras de rendimiento en JavaScript(en ingles), la cual posee varias diapositivas centradas en selectores.3.2.1Comprobar SeleccionesUna vez realizada la seleccin de los elementos, querr conocer si dicha seleccin entreg algn resultado. Para ello, pueda que escriba algo as:if ($('div.foo')) { ... }Sin embargo esta forma no funcionar. Cuando se realiza una seleccin utilizando$(), siempre es devuelto un objeto, y si se lo evala, ste siempre devolvertrue. Incluso si la seleccin no contiene ningn elemento, el cdigo dentro del bloqueifse ejecutar.En lugar de utilizar el cdigo mostrado, lo que se debe hacer es preguntar por la cantidad de elementos que posee la seleccin que se ejecut. Esto es posible realizarlo utilizando la propiedad JavaScriptlength. Si la respuesta es 0, la condicin evaluar falso, caso contrario (ms de 0 elementos), la condicin ser verdadera.Evaluar si una seleccin posee elementosif ($('div.foo').length) { ... }3.2.2Guardar SeleccionesCada vez que se hace una seleccin, una gran cantidad de cdigo es ejecutado. jQuery no guarda el resultado por si solo, por lo tanto, si va a realizar una seleccin que luego se har de nuevo, deber salvar la seleccin en una variable.Guardar selecciones en una variablevar $divs = $('div');NotaEn el ejemplo Guardar selecciones en una variable, la variable comienza con el signo de dlar. Contrariamente a otros lenguajes de programacin, en JavaScript este signo no posee ningn significado especial es solamente otro carcter. Sin embargo aqu se utilizar para indicar que dicha variable posee un objeto jQuery. Esta prctica una especie deNotacin Hngara es solo una convencin y no es obligatoria.Una vez que la seleccin es guardada en la variable, se la puede utilizar en conjunto con los mtodos de jQuery y el resultado ser igual que utilizando la seleccin original.NotaLa seleccin obtiene slo los elementos que estn en la pgina cuando se realiz dicha accin. Si luego se aaden elementos al documento, ser necesario repetir la seleccin o aadir los elementos nuevos a la seleccin guardada en la variable. En otras palabras, las selecciones guardadas no se actualizan mgicamente cuando el DOM se modifica.3.2.3Refinamiento y Filtrado de SeleccionesA veces, puede obtener una seleccin que contiene ms de lo que necesita; en este caso, es necesario refinar dicha seleccin. jQuery ofrece varios mtodos para poder obtener exactamente lo que desea.Refinamiento de selecciones$('div.foo').has('p'); // el elemento div.foo contiene elementos $('h1').not('.bar'); // el elemento h1 no posse la clase 'bar' $('ul li').filter('.current'); // un item de una lista desordenada // que posse la clase 'current' $('ul li').first(); // el primer item de una lista desordenada $('ul li').eq(5); // el sexto item de una lista desordenada3.2.4Seleccin de Elementos de un FormulariojQuery ofrece varios pseudo-selectores que ayudan a encontrar elementos dentro de los formularios, stos son especialmente tiles ya que dependiendo de los estados de cada elemento o su tipo, puede ser difcil distinguirlos utilizando selectores CSS estndar.:buttonSelecciona elementosy con el atributotype='button':checkboxSelecciona elementoscon el atributotype='checkbox':checkedSelecciona elementosdel tipocheckboxseleccionados:disabledSelecciona elementos del formulario que estn deshabitados:enabledSelecciona elementos del formulario que estn habilitados:fileSelecciona elementoscon el atributotype='file':imageSelecciona elementoscon el atributotype='image':inputSelecciona elementos,y:passwordSelecciona elementoscon el atributotype='password':radioSelecciona elementoscon el atributotype='radio':resetSelecciona elementoscon el atributotype='reset':selectedSelecciona elementosque estn seleccionados:submitSelecciona elementoscon el atributotype='submit':textSelecciona elementoscon el atributotype='text'Utilizando pseudo-selectores en elementos de formularios$('#myForm :input'); // obtiene todos los elementos inputs // dentro del formulario #myForm3.3Trabajar con SeleccionesUna vez realizada la seleccin de los elementos, es posible utilizarlos en conjunto con diferentes mtodos. stos, generalmente, son de dos tipos: obtenedores (en inglsgetters) y establecedores (en inglssetters). Los mtodos obtenedores devuelven una propiedad del elemento seleccionado; mientras que los mtodos establecedores fijan una propiedad a todos los elementos seleccionados.3.3.1EncadenamientoSi en una seleccin se realiza una llamada a un mtodo, y ste devuelve un objeto jQuery, es posible seguir un encadenado de mtodos en el objeto.Encadenamiento$('#content').find('h3').eq(2).html('nuevo texto para el tercer elemento h3');Por otro lado, si se est escribiendo un encadenamiento de mtodos que incluyen muchos pasos, es posible escribirlos lnea por lnea, haciendo que el cdigo luzca ms agradable para leer.Formateo de cdigo encadenado$('#content') .find('h3') .eq(2) .html('nuevo texto para el tercer elemento h3');Si desea volver a la seleccin original en el medio del encadenado, jQuery ofrece el mtodo$.fn.endpara poder hacerlo.Restablecer la seleccin original utilizando el mtodo$.fn.end$('#content') .find('h3') .eq(2) .html('nuevo texto para el tercer elemento h3') .end() // reestablece la seleccin a todos los elementos h3 en #content .eq(0) .html('nuevo texto para el primer elemento h3');NotaEl encadenamiento es muy poderoso y es una caracterstica que muchas bibliotecas JavaScript han adoptado desde que jQuery se hizo popular. Sin embargo, debe ser utilizado con cuidado. Un encadenamiento de mtodos extensivo pueden hacer un cdigo extremadamente difcil de modificar y depurar. No existe una regla que indique que tan largo o corto debe ser el encadenado pero es recomendable que tenga en cuenta este consejo.3.3.2Obtenedores (Getters) & Establecedores (Setters)jQuery sobrecarga sus mtodos, en otras palabras, el mtodo para establecer un valor posee el mismo nombre que el mtodo para obtener un valor. Cuando un mtodo es utilizado para establecer un valor, es llamado mtodo establecedor (en inglssetter). En cambio, cuando un mtodo es utilizado para obtener (o leer) un valor, es llamado obtenedor (en inglsgetter).El mtodo$.fn.htmlutilizado como establecedor$('h1').html('hello world');El mtodo html utilizado como obtenedor$('h1').html();Los mtodos establecedores devuelven un objeto jQuery, permitiendo continuar con la llamada de ms mtodos en la misma seleccin, mientras que los mtodos obtenedores devuelven el valor por el cual se consult, pero no permiten seguir llamando a ms mtodos en dicho valor.3.4CSS, Estilos, & DimensionesjQuery incluye una manera til de obtener y establecer propiedades CSS a los elementos.NotaLas propiedades CSS que incluyen como separador un guin del medio, en JavaScript deben ser transformadas a su estiloCamelCase. Por ejemplo, cuando se la utiliza como propiedad de un mtodo, el estilo CSSfont-sizedeber ser expresado comofontSize. Sin embargo, esta regla no es aplicada cuando se pasa el nombre de la propiedad CSS al mtodo$.fn.css en este caso, los dos formatos (enCamelCaseo con el guin del medio) funcionarn.Obtener propiedades CSS$('h1').css('fontSize'); // devuelve una cadena de caracteres como "19px" $('h1').css('font-size'); // tambin funcionaEstablecer propiedades CSS$('h1').css('fontSize', '100px'); // establece una propiedad individual CSS $('h1').css({ 'fontSize' : '100px', 'color' : 'red' }); // establece mltiples propiedades CSSNotar que el estilo del argumento utilizado en la segunda lnea del ejemplo es un objeto que contiene mltiples propiedades. Esta es una forma comn de pasar mltiples argumentos a una funcin, y muchos mtodos establecedores de la biblioteca aceptan objetos para fijar varias propiedades de una sola vez.A partir de la versin 1.6 de la biblioteca, utilizando$.fn.csstambin es posible establecer valores relativos en las propiedades CSS de un elemento determinado:Establecer valores CSS relativos$('h1').css({ 'fontSize' : '+=15px', // suma 15px al tamao original del elemento 'paddingTop' : '+=20px' // suma 20px al padding superior original del elemento });3.4.1Utilizar Clases para Aplicar Estilos CSSPara obtener valores de los estilos aplicados a un elemento, el mtodo$.fn.csses muy til, sin embargo, su utilizacin como mtodo establecedor se debe evitar (ya que, para aplicar estilos a un elemento, se puede hacer directamente desde CSS). En su lugar, lo ideal, es escribir reglas CSS que se apliquen a clases que describan los diferentes estados visuales de los elementos y luego cambiar la clase del elemento para aplicar el estilo que se desea mostrar.Trabajar con clasesvar $h1 = $('h1'); $h1.addClass('big'); $h1.removeClass('big'); $h1.toggleClass('big'); if ($h1.hasClass('big')) { ... }Las clases tambin pueden ser tiles para guardar informacin del estado de un elemento, por ejemplo, para indicar que un elemento fue seleccionado.3.4.2DimensionesjQuery ofrece una variedad de mtodos para obtener y modificar valores de dimensiones y posicin de un elemento.El cdigo mostrado en el ejemplo Mtodos bsicos sobre Dimensiones es solo un breve resumen de las funcionalidades relaciones a dimensiones en jQuery; para un completo detalle puede consultarhttp://api.jquery.com/category/dimensions/.Mtodos bsicos sobre Dimensiones$('h1').width('50px'); // establece el ancho de todos los elementos H1 $('h1').width(); // obtiene el ancho del primer elemento H1 $('h1').height('50px'); // establece el alto de todos los elementos H1 $('h1').height(); // obtiene el alto del primer elemento H1 $('h1').position(); // devuelve un objeto conteniendo // informacin sobre la posicin // del primer elemento relativo al // "offset" (posicin) de su elemento padre3.5AtributosLos atributos de los elementos HTML que conforman una aplicacin pueden contener informacin til, por eso es importante poder establecer y obtener esa informacin.El mtodo$.fn.attracta tanto como mtodo establecedor como obtenedor. Adems, al igual que el mtodo$.fn.css, cuando se lo utiliza como mtodo establecedor, puede aceptar un conjunto de palabra clave-valor o un objeto conteniendo ms conjuntos.Establecer atributos$('a').attr('href', 'allMyHrefsAreTheSameNow.html'); $('a').attr({ 'title' : 'all titles are the same too', 'href' : 'somethingNew.html' });En el ejemplo, el objeto pasado como argumento est escrito en varias lneas. Como se explic anteriormente, los espacios en blanco no importan en JavaScript, por lo cual, es libre de utilizarlos para hacer el cdigo ms legible. En entornos de produccin, se pueden utilizar herramientas de minificacin, los cuales quitan los espacios en blanco (entre otras cosas) y comprimen el archivo final.Obtener atributos$('a').attr('href'); // devuelve el atributo href perteneciente // al primer elemento del documento3.6Recorrer el DOMUna vez obtenida la seleccin, es posible encontrar otros elementos utilizando a la misma seleccin.Enhttp://api.jquery.com/category/traversing/puede encontrar una completa documentacin sobre los mtodos de recorrido de DOM (en inglstraversing) que posee jQuery.NotaDebe ser cuidadoso en recorrer largas distancias en un documento recorridos complejos obligan que la estructura del documento sea siempre la misma, algo que es difcil de garantizar. Uno -o dos- pasos para el recorrido esta bien, pero generalmente hay que evitar atravesar desde un contenedor a otro.Moverse a travs del DOM utilizando mtodos de recorrido$('h1').next('p'); // seleccionar el inmediato y prximo // elemento con respecto a H1 $('div:visible').parent(); // seleccionar el elemento contenedor // a un div visible $('input[name=first_name]').closest('form'); // seleccionar el elemento // ms cercano a un input $('#myList').children(); // seleccionar todos los elementos // hijos de #myList $('li.selected').siblings(); // seleccionar todos los items // hermanos del elemento Tambin es posible interactuar con la seleccin utilizando el mtodo$.fn.each. Dicho mtodo interacta con todos los elementos obtenidos en la seleccin y ejecuta una funcin por cada uno. La funcin recibe como argumento el ndice del elemento actual y al mismo elemento. De forma predeterminada, dentro de la funcin, se puede hacer referencia al elemento DOM a travs de la declaracinthis.Interactuar en una seleccin$('#myList li').each(function(idx, el) { console.log( 'El elemento ' + idx + 'contiene el siguiente HTML: ' + $(el).html() ); });3.7Manipulacin de ElementosUna vez realizada la seleccin de los elementos que desea utilizar, la diversin comienza. Es posible cambiar, mover, remover y duplicar elementos. Tambin crear nuevos a travs de una sintaxis simple.La documentacin completa sobre los mtodos de manipulacin puede encontrarla en la seccinManipulation:http://api.jquery.com/category/manipulation/.3.7.1Obtener y Establecer Informacin en ElementosExisten muchas formas por las cuales de puede modificar un elemento. Entre las tareas ms comunes estn las de cambiar el HTML interno o algn atributo del mismo. Para este tipo de tareas, jQuery ofrece mtodos simples, funcionales en todos los navegadores modernos. Incluso es posible obtener informacin sobre los elementos utilizando los mismos mtodos pero en su forma de mtodo obtenedor.NotaRealizar cambios en los elementos, es un trabajo trivial, pero hay debe recordar que el cambio afectar atodoslos elementos en la seleccin, por lo que, si desea modificar un slo elemento, tiene que estar seguro de especificarlo en la seleccin antes de llamar al mtodo establecedor.NotaCuando los mtodos actan como obtenedores, por lo general, solamente trabajan con el primer elemento de la seleccin. Adems no devuelven un objeto jQuery, por lo cual no es posible encadenar ms mtodos en el mismo. Una excepcin es el mtodo$.fn.text, el cual permite obtener el texto de los elementos de la seleccin.$.fn.htmlObtiene o establece el contenido HTML de un elemento.$.fn.textObtiene o establece el contenido en texto del elemento; en caso se pasarle como argumento cdigo HTML, este es despojado.$.fn.attrObtiene o establece el valor de un determinado atributo.$.fn.widthObtiene o establece el ancho en pixeles del primer elemento de la seleccin como un entero.$.fn.heightObtiene o establece el alto en pixeles del primer elemento de la seleccin como un entero.$.fn.positionObtiene un objeto con informacin sobre la posicin del primer elemento de la seleccin, relativo al primer elemento padre posicionado.Este mtodo es solo obtenedor.$.fn.valObtiene o establece el valor (value) en elementos de formularios.Cambiar el HTML de un elemento$('#myDiv p:first') .html('Nuevo primer prrafo');3.7.2Mover, Copiar y Remover ElementosExisten varias maneras para mover elementos a travs del DOM; las cuales se pueden separar en dos enfoques: querer colocar el/los elementos seleccionados de forma relativa a otro elemento; querer colocar un elemento relativo a el/los elementos seleccionados.Por ejemplo, jQuery provee los mtodos$.fn.insertAftery$.fn.after. El mtodo$.fn.insertAftercoloca a el/los elementos seleccionados despus del elemento que se haya pasado como argumento; mientras que el mtodo$.fn.aftercoloca al elemento pasado como argumento despus del elemento seleccionado. Otros mtodos tambin siguen este patrn:$.fn.insertBeforey$.fn.before;$.fn.appendToy$.fn.append; y$.fn.prependToy$.fn.prepend.La utilizacin de uno u otro mtodo depender de los elementos que tenga seleccionados y el tipo de referencia que se quiera guardar con respecto al elemento que se esta moviendo.Mover elementos utilizando diferentes enfoques// hacer que el primer item de la lista sea el ltimo var $li = $('#myList li:first').appendTo('#myList'); // otro enfoque para el mismo problema $('#myList').append($('#myList li:first')); // debe tener en cuenta que no hay forma de acceder a la // lista de items que se ha movido, ya que devuelve // la lista en s3.7.2.1Clonar ElementosCuando se utiliza un mtodo como$.fn.appendTo, lo que se est haciendo es mover al elemento; pero a veces en lugar de eso, se necesita mover un duplicado del mismo elemento. En este caso, es posible utilizar el mtodo$.fn.clone.Obtener una copia del elemento// copiar el primer elemento de la lista y moverlo al final de la misma $('#myList li:first').clone().appendTo('#myList');NotaSi se necesita copiar informacin y eventos relacionados al elemento, se debe pasartruecomo argumento de$.fn.clone.3.7.2.2Remover elementosExisten dos formas de remover elementos de una pgina: Utilizando$.fn.removeo$.fn.detach. Cuando desee remover de forma permanente al elemento, utilize el mtodo$.fn.remove. Por otro lado, el mtodo $.fn.detach tambin remueve el elemento, pero mantiene la informacin y eventos asociados al mismo, siendo til en el caso que necesite reinsertar el elemento en el documento.NotaEl mtodo$.fn.detaches muy til cuando se esta manipulando de forma severa un elemento, ya que es posible eliminar al elemento, trabajarlo en el cdigo y luego restaurarlo en la pgina nuevamente. Esta forma tiene como beneficio no tocar el DOM mientras se est modificando la informacin y eventos del elemento.Por otro lado, si se desea mantener al elemento pero se necesita eliminar su contenido, es posible utiliza el mtodo$.fn.empty, el cual vaciar el contenido HTML del elemento.3.7.3Crear Nuevos ElementosjQuery provee una forma fcil y elegante para crear nuevos elementos a travs del mismo mtodo$()que se utiliza para realizar selecciones.Crear nuevos elementos$('Un nuevo prrafo'); $('nuevo item de la lista');Crear un nuevo elemento con atributos utilizando un objeto$('', { html : 'Un nuevo enlace', 'class' : 'new', href : 'foo.html' });Note que en el objeto que se pasa como argumento, la propiedad class est entre comillas, mientras que la propiedad href y html no lo estn. Por lo general, los nombres de propiedades no deben estar entre comillas, excepto en el caso que se utilice como nombre una palabra reservada (como es el caso de class).Cuando se crea un elemento, ste no es aadido inmediatamente a la pgina, sino que se debe hacerlo en conjunto con un mtodo.Crear un nuevo elemento en la pginavar $myNewElement = $('Nuevo elemento'); $myNewElement.appendTo('#content'); $myNewElement.insertAfter('ul:last'); // eliminar al elemento // existente en #content $('ul').last().after($myNewElement.clone()); // clonar al elemento // para tener las dos versionesEstrictamente hablando, no es necesario guardar al elemento creado en una variable es posible llamar al mtodo para aadir el elemento directamente despus de $(). Sin embargo, la mayora de las veces se desear hacer referencia al elemento aadido, por lo cual, si se guarda en una variable no es necesario seleccionarlo despus.Crear y aadir al mismo tiempo un elemento a la pgina$('ul').append('item de la lista');NotaLa sintaxis para aadir nuevos elementos a la pgina es muy fcil de utilizar, pero es tentador olvidar que hay un costo enorme de rendimiento al agregar elementos al DOM de forma repetida. Si esta aadiendo muchos elementos al mismo contenedor, en lugar de aadir cada elemento uno por vez, lo mejor es concatenar todo el HTML en una nica cadena de caracteres para luego anexarla al contenedor. Una posible solucin es utilizar un vector que posea todos los elementos, luego reunirlos utilizandojoiny finalmente anexarla.var myItems = [], $myList = $('#myList'); for (var i=0; i Foo (page.html)Tambin es posible optimizar la extensin:(function($){ $.fn.showLinkLocation = function() { return this.filter('a').append(function(){ return ' (' + this.href + ')'; }); }; })(jQuery);El mtodoappendpermite especificar una funcin de devolucin de llamada, y el valor devuelto determinar que es lo que se aadir a cada elemento. Note tambin que no se utiliza el mtodoattr, debido a que la API nativa del DOM permite un fcil acceso a la propiedadhref.A continuacin se muestra otro ejemplo de extensin. En este caso, no se requiere realizar un bucle en cada elemento ya que se delega la funcionalidad directamente en otro mtodo jQuery:(function($){ $.fn.fadeInAndAddClass = function(duration, className) { return this.fadeIn(duration, function(){ $(this).addClass(className); }); }; })(jQuery); // Ejemplo de utilizacin: $('a').fadeInAndAddClass(400, 'finishedFading');8.3Encontrar y Evaluar ExtensionesUno de los aspectos ms populares de jQuery es la diversidad de extensiones que existen.Sin embargo, la calidad entre extensiones puede variar enormemente. Muchas son intensivamente probadas y bien mantenidas, pero otras son creadas de forma apresurada y luego ignoradas, sin seguir buenas prcticas.Google es la mejor herramienta para encontrar extensiones (aunque el equipo de jQuery este trabajando para mejorar su repositorio de extensiones). Una vez encontrada la extensin, posiblemente quiera consultar la lista de correos de jQuery o el canal IRC #jquery para obtener la opinin de otras personas sobre dicha extensin.Asegrese que la extensin este bien documentada, y que se ofrecen ejemplos de su utilizacin. Tambin tenga cuidado con las extensiones que realizan ms de lo que necesita, estas pueden llegar a sobrecargar su pgina. Para ms consejos sobre como detectar una extensin mediocre, puede leer el artculo (en ingls)Signs of a poorly written jQuery pluginpor Remy Sharp.Una vez seleccionada la extensin, necesitar aadirla a su pgina. Primero, descargue la extensin, descomprimala (si es necesario) y muvala a la carpeta de su aplicacin. Finalmente insertela utilizando el elemento script (luego de la inclusin de jQuery).8.4Escribir ExtensionesA veces, desee realizar una funcionalidad disponible en todo el cdigo, por ejemplo, un mtodo que pueda ser llamado desde una seleccin el cual realice una serie de operaciones.La mayora de las extensiones son mtodos creados dentro del espacio de nombres$.fn. jQuery garantiza que un mtodo llamado sobre el objeto jQuery sea capaz de acceder a dicho objeto a travs dethis. En contrapartida, la extensin debe garantizar de devolver el mismo objeto recibido (a menos que se explicite lo contrario).A continuacin se muestra un ejemplo:Crear una extensin para aadir y remover una clase en un elemento al suceder el evento hover// definicin de la extensin (function($){ $.fn.hoverClass = function(c) { return this.hover( function() { $(this).toggleClass(c); } ); }; })(jQuery); // utilizar la extensin $('li').hoverClass('hover');Para ms informacin sobre el desarrollo de extensiones, puede consultar el artculo (en ingls)A Plugin Development Patternde Mike Alsup. En dicho artculo, se desarrolla una extensin llamada$.fn.hilight, la cual provee soporte para la extensinmetadata(en caso de estar presente) y provee un mtodo descentralizado para establecer opciones globales o de instancias de la extensin.El patrn de desarrollo de extensiones para jQuery explicado por Mike Alsup// // crear una clausura // (function($) { // // definicin de la extensin // $.fn.hilight = function(options) { debug(this); // generacin de las opciones principales antes de interactuar var opts = $.extend({}, $.fn.hilight.defaults, options); // se iteractua y formatea cada elemento return this.each(function() { $this = $(this); // generacin de las opciones especificas de cada elemento var o = $.meta ? $.extend({}, opts, $this.data()) : opts; // actualizacin de los estilos de cada elemento $this.css({ backgroundColor: o.background, color: o.foreground }); var markup = $this.html(); // se llama a la funcin de formateo markup = $.fn.hilight.format(markup); $this.html(markup); }); }; // // funcin privada para realizar depuracin // function debug($obj) { if (window.console && window.console.log) window.console.log('hilight selection count: ' + $obj.size()); }; // // definir y exponer la funcin de formateo // $.fn.hilight.format = function(txt) { return '' + txt + ''; }; // // opciones predeterminadas // $.fn.hilight.defaults = { foreground: 'red', background: 'yellow' }; // // fin de la clausura // })(jQuery);8.5Escribir Extensiones con Mantenimiento de Estado Utilizando Widget Factory de jQuery UINotaEsta seccin esta basada, con permiso del autor, en el artculoBuilding Stateful jQuery Pluginsde Scott Gonzalez.Mientras que la mayora de las extensiones para jQuery son sin mantenimiento de estado (en inglsstateless) es decir, extensiones que se ejecutan solamente sobre un elemento, siendo esa su nica interaccin existe un gran conjunto de funcionalidades que no se aprovechan en el patrn bsico con que se desarrollan las extensiones.Con el fin de llenar ese vaco, jQuery UI (jQuery User Interface) ha implementado un sistema ms avanzado de extensiones. Este sistema permite manejar estados y admite mltiples funciones para ser expuestas en una nica extensin. Dicho sistema es llamadowidget factoryy forma parte de la versin 1.8 de jQuery UI a travs dejQuery.widget, aunque tambin puede ser utilizado sin depender de jQuery UI.Para demostrar las capacidades dewidget factory, se crear una extensin que tendr como funcionalidad ser una barra de progreso.Por ahora, la extensin solo permitir establecer el valor de la barra de progreso una sola vez. Esto se realizar llamando ajQuery.widgetcon dos parmetros: el nombre de la extensin a crear y un objeto literal que contendr las funciones soportadas por la extensin. Cuando la extensin es llamada, una instancia de ella es creada y todas las funciones se ejecutaran en el contexto de esa instancia.Existen dos importantes diferencias en comparacin con una extensin estndar de jQuery: En primer lugar, el contexto es un objeto, no un elemento DOM. En segundo lugar, el contexto siempre es un nico objeto, nunca una coleccin.Una simple extensin con mantenimiento de estado utilizando widget factory de jQuery UI$.widget("nmk.progressbar", { _create: function() { var progress = this.options.value + "%"; this.element .addClass("progressbar") .text(progress); } });El nombre de la extensin debe contener un espacio de nombres, en este caso se utilizanmk. Los espacios de nombres tienen una limitacin de un solo nivel de profundidad es decir que por ejemplo, no es posible utilizarnmk.foo. Como se puede ver en el ejemplo,widget factoryprovee dos propiedades para ser utilizadas. La primera,this.elementes un objeto jQuery que contiene exactamente un elemento. En caso que la extensin sea ejecutada en ms de un elemento, una instancia separada de la extensin ser creada por cada elemento y cada una tendr su propiothis.element. La segunda propiedad,this.options, es un conjunto de pares clave/valor con todas las opciones de la extensin. Estas opciones pueden pasarse a la extensin como se muestra a continuacin:NotaCuando est realizando sus propias extensiones es recomendable utilizar su propio espacio de nombres, ya que deja en claro de donde proviene la extensin y si es parte de una coleccin mayor. Por otro lado, el espacio de nombresuiest reservado para las extensiones oficiales de jQuery UI.Pasar opciones al widget$("") .appendTo( "body" ) .progressbar({ value: 20 });Cuando se llama ajQuery.widgetse extiende a jQuery aadiendo el mtodo ajQuery.fn(de la misma forma que cuando se crea una extensin estndar). El nombre de la funcin que se aade esta basado en el nombre que se pasa ajQuery.widget, sin el espacio de nombres (en este caso el nombre serjQuery.fn.progressbar).Como se muestra a continuacin, es posible especificar valores predeterminados para cualquier opcin. Estos valores deberan basarse en la utilizacin ms comn de la extensin.Establecer opciones predeterminadas para un widget$.widget("nmk.progressbar", { // opciones predeterminadas options: { value: 0 }, _create: function() { var progress = this.options.value + "%"; this.element .addClass( "progressbar" ) .text( progress ); } });8.5.1Aadir Mtodos a un WidgetAhora que es posible inicializar la extensin, es necesario aadir la habilidad de realizar acciones a travs de mtodos definidos en la extensin. Para definir un mtodo en la extensin es necesario incluir la funcin en el objeto literal que se pasa ajQuery.widget. Tambin es posible definir mtodos privados anteponiendo un guin bajo al nombre de la funcin.Crear mtodos en el Widget$.widget("nmk.progressbar", { options: { value: 0 }, _create: function() { var progress = this.options.value + "%"; this.element .addClass("progressbar") .text(progress); }, // crear un mtodo pblico value: function(value) { // no se pasa ningn valor, entonces acta como mtodo obtenedor if (value === undefined) { return this.options.value; // se pasa un valor, entonces acta como mtodo establecedor } else { this.options.value = this._constrain(value); var progress = this.options.value + "%"; this.element.text(progress); } }, // crear un mtodo privado _constrain: function(value) { if (value > 100) { value = 100; } if (value < 0) { value = 0; } return value; } });Para llamar a un mtodo en una instancia de la extensin, se debe pasar el nombre de dicho mtodo a la extensin. En caso que se llame a un mtodo que acepta parmetros, estos se deben pasar a continuacin del nombre del mtodo.Llamar a mtodos en una instancia de extensinvar bar = $("") .appendTo("body") .progressbar({ value: 20 }); // obtiene el valor actual alert(bar.progressbar("value")); // actualiza el valor bar.progressbar("value", 50); // obtiene el valor nuevamente alert(bar.progressbar("value"));NotaEjecutar mtodos pasando el nombre del mtodo a la misma funcin jQuery que se utiliza para inicializar la extensin puede parecer extrao, sin embargo es realizado as para prevenir la contaminacin del espacio de nombres de jQuery manteniendo al mismo tiempo la capacidad de llamar a mtodos en cadena.8.5.2Trabajar con las Opciones del WidgetUno de los mtodos disponibles automticamente para la extensin esoption. Este mtodo permite obtener y establecer opciones despus de la inicializacin y funciona exactamente igual que los mtodosattrycssde jQuery: pasando nicamente un nombre como argumento el mtodo funciona como obtenedor, mientras que pasando uno o ms conjuntos de nombres y valores el mtodo funciona como establecedor. Cuando es utilizado como mtodo obtenedor, la extensin devolver el valor actual de la opcin correspondiente al nombre pasado como argumento. Por otro lado, cuando es utilizado como un mtodo establecedor, el mtodo_setOptionde la extensin ser llamado por cada opcin que se desea establecer.Responder cuando una opcin es establecida$.widget("nmk.progressbar", { options: { value: 0 }, _create: function() { this.element.addClass("progressbar"); this._update(); }, _setOption: function(key, value) { this.options[key] = value; this._update(); }, _update: function() { var progress = this.options.value + "%"; this.element.text(progress); } });8.5.3Aadir Funciones de Devolucin de LlamadaUno de las maneras ms fciles de extender una extensin es aadir funciones de devolucin de llamada, para que de esta forma el usuario puede reaccionar cuando el estado de la extensin cambie. A continuacin se mostrar como aadir una funcin de devolucin de llamada a la extensin creada para indicar cuando la barra de progreso haya alcanzado el 100%. El mtodo_triggerobtiene tres parmetros: el nombre de la funcin de devolucin, el objeto de evento nativo que inicializa la funcin de devolucin y un conjunto de informacin relevante al evento. El nombre de la funcin de devolucin es el nico parmetro obligatorio, pero los otros pueden ser muy tiles si el usuario desea implementar funcionalidades personalizadas.Proveer funciones de devolucin de llamada$.widget("nmk.progressbar", { options: { value: 0 }, _create: function() { this.element.addClass("progressbar"); this._update(); }, _setOption: function(key, value) { this.options[key] = value; this._update(); }, _update: function() { var progress = this.options.value + "%"; this.element.text(progress); if (this.options.value == 100) { this._trigger("complete", null, { value: 100 }); } } });Las funciones de devolucin son esencialmente slo opciones adicionales, por lo cual, pueden ser establecidas como cualquier otra opcin. Cada vez que una funcin de devolucin es ejecutada, un evento correspondiente se activa tambin. El tipo de evento se determina mediante la concatenacin del nombre de la extensin y el nombre de la funcin de devolucin. Dicha funcin y evento reciben dos mismos parmetros: un objeto de evento y un conjunto de informacin relevante al evento.Si la extensin tendr alguna funcionalidad que podr ser cancelada por el usuario, la mejor manera de hacerlo es creando funciones de devolucin cancelables. El usuario podr cancelar una funcin de devolucin o su evento asociado de la misma manera que se cancela cualquier evento nativo: llamando aevent.preventDefault()o utilizandoreturn false.Vincular a eventos del widgetvar bar = $("") .appendTo("body") .progressbar({ complete: function(event, data) { alert( "Funcin de devolucin" ); } }) .on("progressbarcomplete", function(event, data) { alert("El valor de la barra de progreso es " + data.value); }); bar.progressbar("option", "value", 100);En profundidad: Widget FactoryCuando se llama ajQuery.widget, sta crea una funcin constructora para la extensin y establece el objeto literal que se pasa como el prototipo para todas las instancias de la extensin. Todas las funcionalidades que automticamente se aaden a la extensin provienen del prototipo base del widget, el cual es definido comojQuery.Widget.prototype. Cuando una instancia de la extensin es creada, es guardada en el elemento DOM original utilizandojQuery.data, con el nombre de la extensin como palabra clave.Debido a que la instancia de la extensin esta directamente vinculada al elemento DOM, es posible acceder a la instancia de la extensin de forma directa. Esto permite llamar a mtodos directamente en la instancia de la extensin en lugar de pasar el nombre del mtodo como una cadena de caracteres, dando la posibilidad de acceder a las propiedades de la extensin.var bar = $("") .appendTo("body") .progressbar() .data("progressbar" ); // llamar a un mtodo directamente en la instancia de la extensin bar.option("value", 50); // acceder a propiedades en la instancia de la extensin alert(bar.options.value);Uno de los mayores beneficios de tener un constructor y un prototipo para una extensin es la facilidad de extender la extensin. El hecho de aadir o cambiar mtodos en el prototipo de la extensin, permite tambin modificarlos en todas las instancias de la extensin. Por ejemplo, si deseamos aadir un mtodo a la extensin de barra de progreso para permitir restablecer el progreso a 0%, es posible hacerlo aadiendo este mtodo al prototipo y automticamente estar disponible para ser llamada desde cualquier instancia de la extensin.$.nmk.progressbar.prototype.reset = function() { this._setOption("value", 0); };8.5.4LimpiezaEn algunos casos, tendr sentido permitir a los usuarios aplicar y desaplicar la extensin. Esto es posible hacerlo a travs del mtododestroy. Con dicho mtodo, es posible deshacer todo lo realizado con la extensin. Tambin ste es llamado automticamente si el elemento vinculado a la extensin es eliminado del DOM (por lo cual tambin es posible utilizarlo para la recoleccin de basura). El mtododestroypredeterminado remueve el vnculo entre el elemento DOM y la instancia de la extensinAadir un mtodo destroy al widget$.widget( "nmk.progressbar", { options: { value: 0 }, _create: function() { this.element.addClass("progressbar"); this._update(); }, _setOption: function(key, value) { this.options[key] = value; this._update(); }, _update: function() { var progress = this.options.value + "%"; this.element.text(progress); if (this.options.value == 100 ) { this._trigger("complete", null, { value: 100 }); } }, destroy: function() { this.element .removeClass("progressbar") .text(""); // llama a la funcin base destroy $.Widget.prototype.destroy.call(this); } });8.5.5ConclusinLa utilizacin deWidget factoryes solo una manera de crear extensiones con mantenimiento de estado. Existen algunos modelos diferentes que pueden ser utilizados y cada uno posee sus ventajas y desventajas.Widget factoryresuelve muchos problemas comunes, mejora significativamente la productividad y la reutilizacin de cdigo.8.6Ejercicios8.6.1Realizar una Tabla OrdenablePara este ejercicio, la tarea es identificar, descargar e implementar una extensin que permita ordenar la tabla existente en la pgina index.html. Cuando est listo, todas las columnas de la tabla deben poder ser ordenables.8.6.2Escribir una Extensin Para Cambiar el Color de Fondo en TablasAbra el archivo/ejercicios/index.htmlen el navegador. Realice el ejercicio utilizando el archivo/ejercicios/js/stripe.js. La tarea es escribir una extensin llamada stripe la cual podr ser llamada desde cualquier elemento table y deber cambiar el color de fondo de las filas impares en el cuerpo de la tabla. El color podr ser especificado como parmetro de la extensin.$('#myTable').stripe('#cccccc');No olvide de devolver la tabla para que otros mtodos puedan ser encadenados luego de la llamada a la extensin.9Mejores Prcticas para Aumentar el RendimientoEste captulo cubre numerosas mejores prcticas de JavaScript y jQuery,sin un orden en particular. Muchas de estas prcticas estn basadas en la presentacinjQuery Anti-Patterns for Performance(en ingls) de Paul Irish.9.1Guardar la Longitud en BuclesEn un bucle, no es necesario acceder a la longitud de un vector cada vez que se evala la condicin; dicho valor se puede guardar previamente en una variable.var myLength = myArray.length; for (var i = 0; i < myLength; i++) { // do stuff }9.2Aadir Nuevo Contenido por Fuera de un BucleSi va a insertar muchos elementos en el DOM, hgalo todo de una sola vez, no de una por vez.// mal $.each(myArray, function(i, item) { var newListItem = '' + item + ''; $('#ballers').append(newListItem); }); // mejor: realizar esto var frag = document.createDocumentFragment(); $.each(myArray, function(i, item) { var newListItem = '' + item + ''; frag.appendChild(newListItem); }); $('#ballers')[0].appendChild(frag); // o esto: var myHtml = ''; $.each(myArray, function(i, item) { myHtml += '' + item + ''; }); $('#ballers').html(myHtml);9.3No RepetirseNo se repita; realice las cosas una vez y slo una, caso contrario lo estar haciendo mal.// MAL if ($eventfade.data('currently') != 'showing') { $eventfade.stop(); } if ($eventhover.data('currently') != 'showing') { $eventhover.stop(); } if ($spans.data('currently') != 'showing') { $spans.stop(); } // BIEN var $elems = [$eventfade, $eventhover, $spans]; $.each($elems, function(i,elem) { if (elem.data('currently') != 'showing') { elem.stop(); } });9.4Cuidado con las Funciones AnnimasNo es aconsejable utilizar de sobremanera las funciones annimas. Estas son difciles de depurar, mantener, probar o reutilizar. En su lugar,utilice un objeto literal para organizar y nombrar sus controladores y funciones de devolucin de llamada.// MAL $(document).ready(function() { $('#magic').click(function(e) { $('#yayeffects').slideUp(function() { // ... }); }); $('#happiness').load(url + ' #unicorns', function() { // ... }); }); // MEJOR var PI = { onReady : function() { $('#magic').click(PI.candyMtn); $('#happiness').load(PI.url + ' #unicorns', PI.unicornCb); }, candyMtn : function(e) { $('#yayeffects').slideUp(PI.slideCb); }, slideCb : function() { ... }, unicornCb : function() { ... } }; $(document).ready(PI.onReady);9.5Optimizacin de SelectoresLa optimizacin de selectores es menos importante de lo que sola ser, debido a la implementacin en algunos navegadores dedocument.querySelectorAll(), pasando la carga de jQuery hacia el navegador. Sin embargo, existen algunos consejos que debe tener en cuenta.9.5.1Selectores basados en IDSiempre es mejor comenzar las selecciones con un ID.// rpido $('#container div.robotarm'); // super-rpido $('#container').find('div.robotarm');El ejemplo que utiliza$.fn.findes ms rpido debido a que la primera seleccin utiliza el motor de seleccin internoSizzle mientras que la seleccin realizada nicamente por ID utilizadocument.getElementById(), el cual es extremadamente rpido debido a que es una funcin nativa del navegador.9.5.2EspecificidadTrate de ser especifico para el lado derecho de la seleccin y menos especfico para el izquierdo.// no optimizado $('div.data .gonzalez'); // optimizado $('.data td.gonzalez');Use en lo posibleetiqueta.clasedel lado derecho de la seleccin, y soloetiquetao.claseen la parte izquierda.$('.data table.attendees td.gonzalez'); // mucho mejor: eliminar la parte media de ser posible $('.data td.gonzalez');La segunda seleccin tiene mejor rendimiento debido a que atraviesa menos capas para buscar el elemento.9.5.3Evitar el Selector UniversalSelecciones en donde se especifica de forma implcita o explcita una seleccin universal puede resultar muy lento.$('.buttons > *'); // muy lento $('.buttons').children(); // mucho mejor $('.gender :radio'); // seleccin universal implcita $('.gender *:radio'); // misma forma, pero de forma explcita $('.gender input:radio'); // mucho mejor9.6Utilizar la Delegacin de EventosLa delegacin de eventos permite vincular un controlador de evento a un elemento contenedor (por ejemplo, una lista desordenada) en lugar de mltiples elementos contenidos (por ejemplo, los tems de una lista). jQuery hace fcil este trabajo a travs de$.fn.livey$.fn.delegate. En lo posible, es recomendable utilizar$.fn.delegateen lugar de$.fn.live, ya que elimina la necesidad de una seleccin y su contexto explcito reduce la carga en aproximadamente un 80%.Adems, la delegacin de eventos permite aadir nuevos elementos contenedores a la pgina sin tener que volver a vincular sus controladores de eventos.// mal (si existen muchos items en la lista) $('li.trigger').click(handlerFn); // mejor: delegacin de eventos con $.fn.live $('li.trigger').live('click', handlerFn); // mucho mejor: delegacin de eventos con $.fn.delegate // permite especificar un contexto de forma fcil $('#myList').delegate('li.trigger', 'click', handlerFn);9.7Separar Elementos para Trabajar con EllosEn lo posible, hay que evitar la manipulacin del DOM. Para ayudar con este propsito, a partir de la versin 1.4, jQuery introduce$.fn.detachel cual permite trabajar elementos de forma separada del DOM para luego insertarlos.var $table = $('#myTable'); var $parent = $table.parent(); $table.detach(); // ... se aaden muchas celdas a la tabla $parent.append(table);9.8Utilizar Estilos en Cascada para Cambios de CSS en Varios ElementosSi va a cambiar el CSS en ms de 20 elementos utilizando$.fn.css, considere realizar los cambios de estilos aadindolos en una etiquetastyle. De esta forma se incrementa un 60% el rendimiento.// correcto hasta 20 elementos, lento en ms elementos $('a.swedberg').css('color', '#asd123'); $('a.swedberg { color : #asd123 }') .appendTo('head');9.9Utilizar$.dataen Lugar de$.fn.dataUtilizar$.dataen un elemento del DOM en lugar de$.fn.dataen una seleccin puede ser hasta 10 veces ms rpido. Antes de realizarlo, este seguro de comprender la diferencia entre un elemento DOM y una seleccin jQuery.// regular $(elem).data(key,value); // 10 veces ms rpido $.data(elem,key,value);9.10No Actuar en Elementos no ExistentesjQuery no le dir si esta tratando de ejecutar cdigo en una seleccin vaca esta se ejecutar como si nada estuviera mal. Depender de usted comprobar si la seleccin contiene elementos.// MAL: el cdigo a continuacin ejecuta tres funciones // sin comprobar si existen elementos // en la seleccin $('#nosuchthing').slideUp(); // Mejor var $mySelection = $('#nosuchthing'); if ($mySelection.length) { $mySelection.slideUp(); } // MUCHO MEJOR: aadir una extensin doOnce jQuery.fn.doOnce = function(func){ this.length && func.apply(this); return this; } $('li.cartitems').doOnce(function(){ // realizar algo });Este consejo es especialmente aplicable para widgets de jQuery UI, los cuales poseen mucha carga incluso cuando la seleccin no contiene elementos.9.11Definicin de VariablesLas variables pueden ser definidas en una sola declaracin en lugar de varias.// antiguo var test = 1; var test2 = function() { ... }; var test3 = test2(test); // mejor forma var test = 1, test2 = function() { ... }, test3 = test2(test);En funciones autoejecutables, las definiciones de variables pueden pasarse todas juntas.(function(foo, bar) { ... })(1, 2);9.12Condicionales// antiguo if (type == 'foo' || type == 'bar') { ... } // mejor if (/^(foo|bar)$/.test(type)) { ... } // bsqueda en objeto literal if (({ foo : 1, bar : 1 })[type]) { ... }9.13No Tratar a jQuery como si fuera una Caja NegraUtilice el cdigo fuente de la biblioteca como si fuera su documentacin guarde el enlacehttp://bit.ly/jqsourcecomo marcador para tener de referencia.10Organizacin del Cdigo10.1IntroduccinCuando se emprende la tarea de realizar aplicaciones complejas del lado del cliente, es necesario considerar la forma en que se organizar el cdigo. Este capitulo est dedicado a analizar algunos patrones de organizacin de cdigo para utilizar en una aplicacin realizada con jQuery. Adems se explorar el sistema de gestin de dependencias de RequireJS.10.1.1Conceptos ClaveAntes de comenzar con los patrones de organizacin de cdigo, es importante entender algunos conceptos clave: el cdigo debe estar divido en unidades funcionales mdulos, servicios, etc. Y se debe evitar la tentacin de tener todo en un nico bloque$(document).ready(). Este concepto se conoce como encapsulacin; no repetir cdigo. Identificar piezas similares y utilizar tcnicas de heredacin; a pesar de la naturaleza de jQuery, no todas las aplicaciones JavaScript trabajan (o tienen la necesidad de poseer una representacin) en el DOM; las unidades de funcionalidad deben tener una articulacin flexible (en inglsloosely coupled) es decir, una unidad de funcionalidad debe ser capaz de existir por si misma y la comunicacin con otras unidades debe ser a travs de un sistema de mensajes como los eventos personalizados o pub/sub. Por otro lado, siempre que sea posible, de debe mantener alejada la comunicacin directa entre unidades funcionales.El concepto de articulacin flexible puede ser especialmente problemtico para desarrolladores que hacen su primera incursin en aplicaciones complejas. Por lo tanto, si usted esta empezando a crear aplicaciones, solamente sea consciente de este concepto.10.2EncapsulacinEl primer paso para la organizacin del cdigo es separar la aplicacin en distintas piezas.Muchas veces, este esfuerzo suele ser suficiente para mantener al cdigo en orden.10.2.1El Objeto LiteralUn objeto literal es tal vez la manera ms simple de encapsular cdigo relacionado. Este no ofrece ninguna privacidad para propiedades o mtodos, pero es til para eliminar funciones annimas, centralizar opciones de configuracin, y facilitar el camino para la reutilizacin y refactorizacin.Un objeto literalvar myFeature = { myProperty : 'hello', myMethod : function() { console.log(myFeature.myProperty); }, init : function(settings) { myFeature.settings = settings; }, readSettings : function() { console.log(myFeature.settings); } }; myFeature.myProperty; // 'hello' myFeature.myMethod(); // registra 'hello' myFeature.init({ foo : 'bar' }); myFeature.readSettings(); // registra { foo : 'bar' }El objeto posee una propiedad y varios mtodos, los cuales son pblicos (es decir, cualquier parte de la aplicacin puede verlos). Cmo se puede aplicar este patrn con jQuery? Por ejemplo, en el siguiente cdigo escrito en el estilo tradicional:// haciendo click en un item de la lista se carga cierto contenido, // luego utilizando el ID de dicho item se ocultan // los items aledaos $(document).ready(function() { $('#myFeature li') .append('') .click(function() { var $this = $(this); var $div = $this.find('div'); $div.load('foo.php?item=' + $this.attr('id'), function() { $div.show(); $this.siblings() .find('div').hide(); } ); }); });Si el ejemplo mostrado representa el 100% de la aplicacin, es conveniente dejarlo como esta, ya que no amerita hacer una reestructuracin. En cambio, si la pieza es parte de una aplicacin ms grande, estara bien separar dicha funcionalidad de otras no relacionadas. Por ejemplo, es conveniente mover la URL a la cual se hace la peticin fuera del cdigo y pasarla al rea de configuracin. Tambin romper la cadena de mtodos para hacer luego ms fcil la modificacin.Utilizar un objeto literal para una funcionalidad jQueryvar myFeature = { init : function(settings) { myFeature.config = { $items : $('#myFeature li'), $container : $(''), urlBase : '/foo.php?item=' }; // permite sobreescribir la configuracin predeterminada $.extend(myFeature.config, settings); myFeature.setup(); }, setup : function() { myFeature.config.$items .each(myFeature.createContainer) .click(myFeature.showItem); }, createContainer : function() { var $i = $(this), $c = myFeature.config.$container.clone() .appendTo($i); $i.data('container', $c); }, buildUrl : function() { return myFeature.config.urlBase + myFeature.$currentItem.attr('id'); }, showItem : function() { var myFeature.$currentItem = $(this); myFeature.getContent(myFeature.showContent); }, getContent : function(callback) { var url = myFeature.buildUrl(); myFeature.$currentItem .data('container').load(url, callback); }, showContent : function() { myFeature.$currentItem .data('container').show(); myFeature.hideContent(); }, hideContent : function() { myFeature.$currentItem.siblings() .each(function() { $(this).data('container').hide(); }); } }; $(document).ready(myFeature.init);La primera caracterstica a notar es que el cdigo es ms largo que el original como se dijo anteriormente, si este fuera el alcance de la aplicacin, utilizar un objeto literal seria probablemente una exageracin.Con la nueva organizacin, las ventajas obtenidas son: separacin de cada funcionalidad en pequeos mtodos. En un futuro, si se quiere cambiar la forma en que el contenido se muestra, ser claro en donde habr que hacerlo. En el cdigo original, este paso es mucho ms difcil de localizar; se eliminaron los usos de funciones annimas; las opciones de configuracin se movieron a una ubicacin central; se eliminaron las limitaciones que poseen las cadenas de mtodos, haciendo que el cdigo sea ms fcil para refactorizar, mezclar y reorganizar.Por sus caractersticas, la utilizacin de objetos literales permiten una clara mejora para tramos largos de cdigo insertados en un bloque$(document).ready(). Sin embargo, no son ms avanzados que tener varias declaraciones de funciones dentro de un bloque$(document).ready().10.2.2El Patrn ModularEl patrn modular supera algunas limitaciones del objeto literal, ofreciendo privacidad para variables y funciones, exponiendo a su vez (si se lo desea) una API pblica.El patrn modularvar feature =(function() { // variables y funciones privadas var privateThing = 'secret', publicThing = 'not secret', changePrivateThing = function() { privateThing = 'super secret'; }, sayPrivateThing = function() { console.log(privateThing); changePrivateThing(); }; // API publica return { publicThing : publicThing, sayPrivateThing : sayPrivateThing } })(); feature.publicThing; // registra 'not secret' feature.sayPrivateThing(); // registra 'secret' y cambia el valor // de privateThingEn el ejemplo, se autoejecuta una funcin annima la cual devuelve un objeto. Dentro de la funcin, se definen algunas variables. Debido a que ellas son definidas dentro de la funcin, desde afuera no se tiene acceso a menos que se pongan dentro del objeto que se devuelve. Esto implica que ningn cdigo fuera de la funcin tiene acceso a la variableprivateThingo a la funcinsayPrivateThing. Sin embargo,sayPrivateThingposee acceso aprivateThingychangePrivateThingdebido a estar definidos en el mismo alcance.El patrn es poderoso debido a que permite tener variables y funciones privadas, exponiendo una API limitada consistente en devolver propiedades y mtodos de un objeto.A continuacin se muestra una revisin del ejemplo visto anteriormente, con las mismas caractersticas, pero exponiendo un nico mtodo pblico del modulo,showItemByIndex().Utilizar el patrn modular para una funcionalidad jQuery$(document).ready(function() { var feature = (function() { var $items = $('#myFeature li'), $container = $(''), $currentItem, urlBase = '/foo.php?item=', createContainer = function() { var $i = $(this), $c = $container.clone().appendTo($i); $i.data('container', $c); }, buildUrl = function() { return urlBase + $currentItem.attr('id'); }, showItem = function() { var $currentItem = $(this); getContent(showContent); }, showItemByIndex = function(idx) { $.proxy(showItem, $items.get(idx)); }, getContent = function(callback) { $currentItem.data('container').load(buildUrl(), callback); }, showContent = function() { $currentItem.data('container').show(); hideContent(); }, hideContent = function() { $currentItem.siblings() .each(function() { $(this).data('container').hide(); }); }; $items .each(createContainer) .click(showItem); return { showItemByIndex : showItemByIndex }; })(); feature.showItemByIndex(0); });10.3Gestin de DependenciasNotaEsta seccin esta basada en la excelentedocumentacin de RequireJSy es utilizada con el permiso de James Burke, autor de RequireJS.Cuando un proyecto alcanza cierto tamao, comienza a ser difcil el manejo de los mdulos de una aplicacin, ya que es necesario saber ordenarlos de forma correcta, y comenzar a combinarlos en un nico archivo para lograr la menor cantidad de peticiones. Tambin es posible que se quiera cargar cdigo al vuelo luego de la carga de la pgina.RequireJS es una herramienta de gestin de dependencias creada por James Burke, la cual ayuda a manejar los mdulos, cargarlos en un orden correcto y combinarlos de forma fcil sin tener que realizar ningn cambio. A su vez, otorga una manera fcil de cargar cdigo una vez cargada la pgina, permitiendo minimizar el tiempo de descarga.RequireJS posee un sistema modular, que sin embargo, no es necesario seguirlo para obtener sus beneficios. El formato modular de RequireJS permite la escritura de cdigo encapsulado, incorporacin de internacionalizacin (i18n) a los paquetes (para permitir utilizarlos en diferentes lenguajes) e incluso la utilizacin de servicios JSONP como dependencias.10.3.1Obtener RequireJSLa manera ms fcil de utilizar RequireJS con jQuery es descargandoel paquete de jQuery con RequireJSya incorporado en l. Este paquete excluye porciones de cdigo que duplican funciones de jQuery. Tambin es til descargarun ejemplo de proyecto jQuery que utiliza RequireJS.10.3.2Utilizar RequireJS con jQueryUtilizar RequireJS es simple, tan solo es necesario incorporar en la pgina la versin de jQuery que posee RequireJS incorporado y a continuacin solicitar los archivos de la aplicacin. El siguiente ejemplo asume que tanto jQuery como los otros archivos estn dentro de la carpetascripts/.Utilizar RequireJS: Un ejemplo simple

jQuery+RequireJS Sample Page require(["app"]); jQuery+RequireJS Sample Page La llamada arequire(["app"])le dice a RequireJS que cargue el archivoscripts/app.js. RequireJS cargar cualquier dependencia pasada arequire()sin la extensin.jsdesde el mismo directorio que en que se encuentra el archivorequire-jquery.js, aunque tambin es posible especificar la ruta de la siguiente forma:require(["scripts/app.js"]);El archivoapp.jses otra llamada arequire.jspara cargar todos los archivos necesarios para la aplicacin. En el siguiente ejemplo,app.jssolicita dos extensionesjquery.alpha.jsyjquery.beta.js(no son extensiones reales, solo ejemplos). Estas extensiones estn en la misma carpeta querequire-jquery.js:Un simple archivo JavaScript con dependenciasrequire(["jquery.alpha", "jquery.beta"], function() { //las extensiones jquery.alpha.js y jquery.beta.js han sido cargadas. $(function() { $('body').alpha().beta(); }); });10.3.3Crear Mdulos Reusables con RequireJSRequireJS hace que sea fcil definir mdulos reusables a travs derequire.def(). Un modulo RequireJS puede tener dependencias que pueden ser utilizadas para definir un mdulo, adems de poder devolver un valor un objeto, una funcin, u otra cosa que puede ser incluso utilizado otros mdulos.Si el mdulo no posee ninguna dependencia, tan solo se debe especificar el nombre como primer argumento derequire.def(). El segundo argumento es un objeto literal que define las propiedades del mdulo. Por ejemplo:Definicin de un mdulo RequireJS que no posee dependenciasrequire.def("my/simpleshirt", { color: "black", size: "unisize" } );El ejemplo debe ser guardado en el archivomy/simpleshirt.js.Si el modulo posee dependencias, es posible especificarlas en el segundo argumento derequire.def()a travs de un vector) y luego pasar una funcin como tercer argumento. Esta funcin ser llamada para definir el mdulo una vez cargadas todos las dependencias. Dicha funcin recibe los valores devueltos por las dependencias como un argumento (en el mismo orden en que son requeridas en el vector) y luego la misma debe devolver un objeto que defina el mdulo.Definicin de un mdulo RequireJS con dependenciasrequire.def("my/shirt", ["my/cart", "my/inventory"], function(cart, inventory) { //devuelve un objeto que define a "my/shirt" return { color: "blue", size: "large" addToCart: function() { inventory.decrement(this); cart.add(this); } } } );En este ejemplo, el modulomy/shirtes creado. Este depende demy/cartymy/inventory. En el disco, los archivos estn estructurados de la siguiente forma:my/cart.js my/inventory.js my/shirt.jsLa funcin que definemy/shirtno es llamada hasta quemy/cartymy/inventoryhayan sido cargadas, y dicha funcin recibe como argumentos a los mdulos comocartyinventory. El orden de los argumentos de la funcin debe coincidir con el orden en que las dependencias se requieren en el vector. El objeto devuelto define el mdulomy/shirt. Definiendo los mdulos de esta forma,my/shirtno existe como un objeto global, ya que mltiples mdulos pueden existir en la pgina al mismo tiempo.Los mdulos no tienen que devolver un objeto; cualquier tipo de valor es permitido.Definicin de un mdulo RequireJS que devuelve una funcinrequire.def("my/title", ["my/dependency1", "my/dependency2"], function(dep1, dep2) { // devuelve una funcin para definir "my/title". // Este devuelve o establece // el titulo de la ventana return function(title) { return title ? (window.title = title) : window.title; } } );Solo un mdulo debe ser requerido por archivo JavaScript.10.3.4Optimizar el Cdigo con las Herramientas de RequireJSUna vez incorporado RequireJS para el manejo de dependencias, la optimizacin del cdigo es muy fcil. Descargue el paquete de RequireJS y colquelo en cualquier lugar, preferentemente fuera del rea de desarrollo web. Para los propsitos de este ejemplo, el paquete de RequireJS esta ubicado en una carpeta paralela al directoriowebapp(la cual contiene la pgina HTML y todos los archivos JavaScript de la aplicacin). La estructura de directorios es:requirejs/ (utilizado para ejecutar las herramientas) webapp/app.html webapp/scripts/app.js webapp/scripts/require-jquery.js webapp/scripts/jquery.alpha.js webapp/scripts/jquery.beta.jsLuego, en la carpeta en donde se encuentranrequire-jquery.jsyapp.js, crear un archivo llamadoapp.build.jscon el siguiente contenido:Archivo de configuracin para las herramientas de optimizacin de RequireJS{ appDir: "../", baseUrl: "scripts/", dir: "../../webapp-build", //Comentar la siguiente lnea si se desea //minificar el cdigo por el compilador //en su modo "simple" optimize: "none", modules: [ { name: "app" } ] }Para utilizar la herramienta, es necesario tener instalado Java 6.Closure Compileres utilizado para la minificacin del cdigo (en caso queoptimize: "none"est comentado).Para comenzar a procesar los archivos, abrir una ventana de comandos, dirigirse al directoriowebapp/scriptsy ejecutar:# para sistemas que no son windows ../../requirejs/build/build.sh app.build.js # para sistemas windows ..\..\requirejs\build\build.bat app.build.jsUna vez ejecutado, el archivoapp.jsde la carpetawebapp-buildcontendr todo el cdigo deapp.jsms el dejquery.alpha.jsyjquery.beta.js. Si se abre el archivoapp.html(tambin en la carpetawebapp-build) podr notar que ninguna peticin se realiza para cargarjquery.alpha.jsyjquery.beta.js.10.4Ejercicios10.4.1Crear un Mdulo PortletAbra el archivo/ejercicios/portlets.htmlen el navegador. Realice el ejercicio utilizando el archivo/ejercicios/js/portlets.js. El ejercicio consiste en crear una funcin creadora de portlet que utilice el patrn modular, de tal manera que el siguiente cdigo funcione:var myPortlet = Portlet({ title : 'Curry', source : 'data/html/curry.html', initialState : 'open' // or 'closed' }); myPortlet.$element.appendTo('body');Cada portlet deber ser undivcon un ttulo, un rea de contenido, un botn para abrir/cerrar el portlet, un botn para removerlo y otro para actualizarlo. El portlet devuelto por la funcin deber tener la siguiente API pblica:myPortlet.open(); // fuerza a abrir myPortlet.close(); // fuerza a cerrar myPortlet.toggle(); // alterna entre los estados abierto y cerrado myPortlet.refresh(); // actualiza el contenido myPortlet.destroy(); // remueve el portlet de la pgina myPortlet.setSource('data/html/onions.html'); // cambia el cdigo11Eventos Personalizados11.1Introduccin a los Eventos PersonalizadosTodos estamos familiarizados con los eventos bsicos click,mouseover,focus,blur,submit, etc. que surgen a partir de la interaccin del usuario con el navegador.Los eventos personalizados permiten conocer el mundo de la programacin orientada a eventos (en inglsevent-driven programming). En este captulo, se utilizar el sistema de eventos personalizados de jQuery para crear una simple aplicacin de bsqueda enTwitter.En un primer momento puede ser difcil entender el requisito de utilizar eventos personalizados, ya que los eventos convencionales permiten satisfacer todas las necesidades. Sin embargo, los eventos personalizados ofrecen una nueva forma de pensar la programacin en JavaScript. En lugar de enfocarse en el elemento que ejecuta una accin, los eventos personalizados ponen la atencin en el elemento en donde la accin va a ocurrir. Este concepto brinda varios beneficios: los comportamientos del elemento objetivo pueden ser ejecutados por diferentes elementos utilizando el mismo cdigo; los comportamientos pueden ser ejecutados en mltiples, similares elementos objetivos a la vez; los comportamientos son asociados de forma ms clara con el elemento objetivo, haciendo que el cdigo sea ms fcil de leer y mantener.Un ejemplo es la mejor forma de explicar el asunto. Suponga que posee una lmpara incandescente en una habitacin de una casa. La lmpara actualmente esta encendida. La misma es controlada por dos interruptores de tres posiciones y unclapper(interruptor activado por aplausos):

Ejecutando elclappero alguno de los interruptores, el estado de la lampara cambia. A los interruptores o alclapperno le interesan si la lmpara esta prendida o apagada, tan solo quieren cambiar su estadoSin la utilizacin de eventos personalizados, es posible escribir la rutina de la siguiente manera:$('.switch, .clapper').click(function() { var $light = $(this).parent().find('.lightbulb'); if ($light.hasClass('on')) { $light.removeClass('on').addClass('off'); } else { $light.removeClass('off').addClass('on'); } });Por otro lado, utilizando eventos personalizados, el cdigo queda as:$('.lightbulb').on('changeState', function(e) { var $light = $(this); if ($light.hasClass('on')) { $light.removeClass('on').addClass('off'); } else { $light.removeClass('off').addClass('on'); } }); $('.switch, .clapper').click(function() { $(this).parent().find('.lightbulb').trigger('changeState'); });Algo importante ha sucedido: el comportamiento de la lmpara se ha movido, antes estaba en los interruptores y en elclapper, ahora se encuentra en la misma lmpara.Tambin es posible hacer el ejemplo un poco ms interesante. Suponga que se ha aadido otra habitacin a la casa, junto con un interruptor general, como se muestra a continuacin:

Si existe alguna lmpara prendida en la casa, es posible apagarlas a travs del interruptor general, de igual forma si existen luces apagadas, es posible prenderlas con dicho interruptor. Para realizar esta tarea, se agregan dos eventos personalizados ms a la lmpara:turnOnyturnOff. A travs de una lgica en el eventochangeStatese decide qu evento personalizado utilizar:$('.lightbulb') .on('changeState', function(e) { var $light = $(this); if ($light.hasClass('on')) { $light.trigger('turnOff'); } else { $light.trigger('turnOn'); } }) .on('turnOn', function(e) { $(this).removeClass('off').addClass('on'); }) .on('turnOff', function(e) { $(this).removeClass('off').addClass('on'); }); $('.switch, .clapper').click(function() { $(this).parent().find('.lightbulb').trigger('changeState'); }); $('#master_switch').click(function() { if ($('.lightbulb.on').length) { $('.lightbulb').trigger('turnOff'); } else { $('.lightbulb').trigger('turnOn'); } });Note como el comportamiento del interruptor general se ha vinculado al interruptor general mientras que el comportamiento de las lmparas pertenece a las lmparas.NotaSi esta acostumbrado a la programacin orientada a objetos, puede resultar til pensar de los eventos personalizados como mtodos de objetos. En trminos generales, el objeto al que pertenece el mtodo se crea a partir del selector jQuery. Vincular el evento personalizadochangeStatea todos los elementos$(.light)es similar a tener una clase llamadaLightcon un mtodochangeState, y luego instanciar nuevos objetosLightpor cada elemento.Recapitulacin:.fn.ony.fn.triggerEn el mundo de los eventos personalizados, existen dos mtodos importantes de jQuery:$.fn.ony$.fn.trigger. En el captulo dedicado