Mostrando entradas con la etiqueta jquery. Mostrar todas las entradas
Mostrando entradas con la etiqueta jquery. Mostrar todas las entradas

miércoles, 16 de noviembre de 2011

jQuery: Cómo saber si un objeto pertenece a una clase

Supongamos que estamos iterando sobre una serie de elementos del DOM con jQuery y que realizaremos algunas operaciones dependiendo de la clase a la que pertenezca cada elemento. ¿Cómo saber si un elemento pertenece a una determinada clase?

Sencillo, utilizando la función is() de jQuery. Por ejemplo:

if ($(#elementoID).is('.nombreclase')) {
  alert('pertenece a la clase nombreclase');
} else {
  alert('No pertenece a la clase nombreclase');
}

Además, el argumento que recibe is(), puede ser básicamente cualquier expresión, por lo que podemos preguntar cosas como: is(":first-child"), is(":contains('Peter')"), etc.

Reseteando botones JQuery UI

Tenemos un pequeño formulario en el que incluímos algunos radios hechos con jQueryUI Button. Por alguna razón, en algún momento queremos resetear dichos radios (de manera que ninguno esté seleccionado o que esté seleccionado alguno en específico). Hacemos lo obvio: recorremos los radios y ponemos checked = false a todos (y opcionalmente checked = true al que queremos quede seleccionado). Acto seguido, nos damos cuenta que no sirve.

Más concretamente, el campo checked si se actualizará, pero no así la parte gráfica. Cada vez que cambiemos los Buttons de jQueryUI, necesitamos refrescarlos para que también se actualice la apariencia.

El método clave para esto es "refresh", que según la documentación oficial "Refreshes the visual state of the button. Useful for updating button state after the native element's checked or disabled state is changed programatically."

Invocarlo sobre cualquier botón es muy sencillo, por el ID, sería algo como:

  $('#botonId').button("refresh");


Por poner un segundo ejemplo, yo tengo una función en javascript para limpiar formularios que invoco después de hacer envío de formularios via Ajax. Para resetear todos los radios, sólo tendría que incluir en esta función las siguientes líneas:

$('input:radio').each(function() {
  $(this).button("refresh");
});


Vale, eso es todo. Sencillo

martes, 4 de octubre de 2011

Bloquear interfaz con jQuery

Sigo en la onda de jQuery, esta vez con un plugin muy útil cuando trabajamos con ajax.

Es una práctica muy común hoy en día, realizar solicitudes POST o GET mediante ajax, de esta forma no tenemos que recargar la página completa cada vez, sino una pequeña parte de la misma.


Seguramente hemos visto en algun sitio que cuando subimos una foto a un servidor o realizamos alguna consulta, toda la interfaz se bloquea y aparece en medio un mensaje que nos informa que la página está realizando alguna tarea, que esperemos.

Esto se hace por 2 motivos. El primero es informarle al usuario que ya se está procesando su solicitud; el segundo, que viene a ser consecuencia del primero, es evitar el doble envío de data. Si por ejemplo lo que el usuario está realizando es una búsqueda compleja y no se le informa que ya se está procesando, al pasar unos segundos, el usuario puede pensar que el navegador no "agarró" la orden y volver a presionar el botón de envío, e inclusive hacerlo varias veces al no ver respuesta. Peor aún, si se trata de una inserción en base de datos, la data podría estar insertándose varias veces, lo cual sería fatal.

Bloqueando la interfaz, resolvemos los 2 problemas: le informamos al usuario que su solicitud se está procesando y a la vez protejemos nuestra aplicación de múltiples envíos de data. Esto le da además un comportamiento síncrono a nuestras aplicaciones asíncronas.

¿Cómo lo hacemos? Bien, con un poco de manejo del DOM y CSS podemos lograr el efecto, sin embargo, para jQuery ya existen varios plugins para hacerlo de forma realmente simple. Uno de ellos, se llama BlockUI, y su uso es tan sencillo como incluir el plugin, por supuesto, y luego lo usamos de la siguiente forma.

Para bloquear la pantalla:

$.blockUI({ message: '<h1><img src="busy.gif" /> Por favor espere...</h1>' });

Para desbloquear la pantalla:

$.unblockUI();

Si queremos que la interfaz se bloquee, cada vez que hacemos una solicitud ajax y se desbloquee al terminarla:

$(document).ajaxStart($.blockUI).ajaxStop($.unblockUI);

Supongamos que tenemos un formulario para buscar datos de clientes y mostrarlos en una tabla. Con jQuery ponemos un manejador al submit del formulario, para que realice la búsqueda por POST via ajax e incruste el código HTML de la tabla en un DIV que tengamos destinado para tal fin, podemos bloquear/desbloquear la interfaz de la siguiente manera:

<script type="text/javascript">
$(function() {
	$('#formulario').submit(function() {
		var url = $(location).attr('href');
		var key = $('#keyword').val();

		$.blockUI({ message: '<h1><img src="busy.gif" /> Por favor espere...</h1>' });

		$.post( url,
		{ search_key: key },
			function(data){
			var datos = $('#divdatos');
			datos.html(data);
			$.unblockUI();
		});
		return false;
	});
});
^lt;/script>

Si queremos que la interfaz se desbloquee después de cierto tiempo, podemos hacerlo con la función setTimeout:

setTimeout($.unblockUI, 2000);


Como siempre, recomiendo ir directamente a la fuente y revisar todos los demos, que se pueden hacer muchas más cosas.

lunes, 3 de octubre de 2011

jQueryUI datepicker

En entradas anteriores he trabajado un poco con jQuery, una de las mejores bibliotecas JavaScript (y de las más fáciles de usar) que existen hoy en día. Todo el mundo debería utilizarla.

Todo el mundo debería utilizar también jQueryUI, una biblioteca de componentes gráficos/visuales para jQuery. Uno de los aspectos más destacables de jQuery/jQueryUI es el de la compatibilidad; cuantos dolores de cabeza te quita de entrada, al saber que cualquier componente que utilices, será compatible con los grandes navegadores.

En esta entrada, abordo uno de los widgets de jQueryUI: el datepicker. Muy elegante, funcional y sencillo de manipular. Incluir uno, es tan sencillo como colocar este código:

<script>
  $(function(){
    $("#datepicker").datepicker();
  });
</script>

<div class="demo">
<p>Date: </p>
</div>

Es sólo colocar un input de tipo texto, y con un sencillo script datepickficarlo. Lógicamente, nos gustaría especificar ciertas opciones, como poner los nombres en español, seleccionar alguna fecha por defecto, especificar el formato de la fecha, etc. Bien, todo esto (y más) es posible, gracias a la gran cantidad de opciones y métodos que provee el widget. Veamos un ejemplo más completo:

<script>
	$(function(){
		$("#datepicker").datepicker({
			autoSize: true,
			dayNames: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado'],
			dayNamesMin: ['Dom', 'Lu', 'Ma', 'Mi', 'Je', 'Vi', 'Sa'],
			firstDay: 1,
			monthNames: ['Enero','Febrero','Marzo','Abril','Mayo','Junio','Julio','Agosto','Septiembre','Octubre','Noviembre','Diciembre'],
			monthNamesShort: 'Ene','Feb','Mar','Abr','May','Jun','Jul','Ago','Sep','Oct','Nov','Dic'],
			dateFormat: 'dd/mm/yy',
			changeMonth: true,
			changeYear: true});
 		                
	});
</script>

En este segundo ejemplo hemos agregado algunas opciones. Por ejemplo, hemos especificado los nombres de los días de la semana con dayNames y dayNamesShort, también hemos especificado los nombres de los meses con monthNames y monthNamesShort y hemos dicho que tanto los meses como los años se podrán cambiar a partir de listas desplegables, con changeMonth y changeYear.

Así podemos especificar muchas otras opciones. Es bueno ver la lista completa en la documentación oficial del widget aquí.

Cuando se despliega el calendario, vemos que por omisión aparece seleccionada la fecha actual (de la máquina en la que estamos). Esta es una opción que podemos cambiar, con la opción defaultDate. Por ejemplo, podríamos agregar algo como defaultDate: '03/10/2011' (debe ser consistente con el formato de fecha dateFormat) y siempre aparecerá seleccionada la fecha 3 de octubre de 2011. También, podemos especificar alguna otra fecha que obtengamos dinámicamente.

Sólo hay que estar claro en que con defaultDate especificamos la fecha que aparece por omisión al levantar el calendario, de ninguna manera esto significa que si no se selecciona alguna, esta opción nos dará la fecha por defecto.

Si lo que queremos es modificar la fecha actual, esto debemos hacerlo a través del método setDate, que podemos utilizar en cualquier momento, como cualquier otro elemento de jQuery. Agreguemos un evento setDate al script anterior:

<script>
	$(function(){
		$("#datepicker").datepicker({
			autoSize: true,
			dayNames: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado'],
			dayNamesMin: ['Dom', 'Lu', 'Ma', 'Mi', 'Je', 'Vi', 'Sa'],
			firstDay: 1,
			monthNames: ['Enero','Febrero','Marzo','Abril','Mayo','Junio','Julio','Agosto','Septiembre','Octubre','Noviembre','Diciembre'],
			monthNamesShort: 'Ene','Feb','Mar','Abr','May','Jun','Jul','Ago','Sep','Oct','Nov','Dic'],
			dateFormat: 'dd/mm/yy',
			changeYear: true});

		var myDate = "'"+ <?php echo $_SESSION['fecha_hoy'] ?>+"'";
		$("#datepicker").datepicker('setDate', myDate);
 		                
	});
</script>

En este ejemplo, asumimos que estamos trabajando en PHP y que tenemos en sesión una variable 'fecha_hoy' y esa es la fecha que le asignamos al datepicker, justo después de su creación. Podemos utilizar el mismo método en cualquier otra parte del documento, por supuesto.

Otra opción interesante es disabled, la cual dice si el widget estará deshabilitado (true) o habilitado (false).

Si queremos que nuestro datepicker tenga una fecha por defecto y además esté bloqueado, debemos deshabilitar el widget posterior a que hemos asignado la fecha. Cierro la entrada, precisamente con este ejemplo:

<script>
	$(function(){
		$("#datepicker").datepicker({
			autoSize: true,
			dayNames: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado'],
			dayNamesMin: ['Dom', 'Lu', 'Ma', 'Mi', 'Je', 'Vi', 'Sa'],
			firstDay: 1,
			monthNames: ['Enero','Febrero','Marzo','Abril','Mayo','Junio','Julio','Agosto','Septiembre','Octubre','Noviembre','Diciembre'],
			monthNamesShort: 'Ene','Feb','Mar','Abr','May','Jun','Jul','Ago','Sep','Oct','Nov','Dic'],
			dateFormat: 'dd/mm/yy',
			changeYear: true});

		var myDate = "'"+ <?php echo $_SESSION['fecha_hoy'] ?>+"'";
		$(\"#" . $field . "\").datepicker('setDate', myDate);
		$(\"#" . $field . "\").datepicker( 'option', 'disabled', true);
 		                
	});
</script>

Sólo agregamos una línea de código al final, que dice que la opción disabled a partir de ese momento, comienza a tener el valor true, por lo que no se podrá seleccionar ninguna otra fecha. Posteriormente, por supuesto, podemos habilitar el widget, volver a deshabilitarlo, volver a habilitarlo, etc. Eso sí, si esto es parte de un formulario y al momento de enviarlo, el widget está deshabilitado, también lo estará el input, y por tanto NO se enviará el campo, así que pendiente.

Espero la entrada haya sido de utilidad.

viernes, 30 de septiembre de 2011

Peticiones Ajax síncronas con jQuery

En la entrada pasada publiqué un código para asignar variables de sesión PHP desde jQuery con un POST enviado via Ajax. El código del script es el siguiente:

<script type="text/javascript">
  $(function() {
    $('.print_link').click(function() {
		var fixedurl = 'http://localhost/miapp/main/set_session_var';

		$.post( fixedurl,
		{ object_name: 'tmprow',
          id: $(this).attr('id'),
          monto: $(this).parent().parent().find('.monto').html()
		 },
			function(data){
			//donothing
		});

      return true;
    });
  });
</script>

Luego, en set_session_var (ya en PHP) se hacía el trabajo ordinario de asignar la variable de sesión. Hice la prueba con un ejemplo sencillo en que se tenían 2 vistas, test1 y test2, y cuando se hacía click a un enlace en test1 que llevaba a test2, se ejecutaba la función, justo antes de abandonar la página, de manera que ya en test2, "con suerte" se pudieran usar las variables recién asignadas.

He dicho "con suerte", porque, tratándose de Ajax y su asincronía, no tenemos la certeza de que cuando se cargue test2, ya las variables estén asignadas. El ejemplo mostrado era realmente sencillo, por lo que esto practicamente siempre se cumplía, pero luego comencé a hacer otras cosas en la función set_session_var, que hicieron que eventualmente, cuando cargara test2, aún no estaban mis variables de sesión.

¿La solución? Hacer el envío de forma síncrona, de manera que en el "return true;" garantice que ya se haya ejecutado el POST. Esto con $.post() de jQuery no se puede hacer, hay que utilizar $.ajax() directamente. Recordemos que $.post() es un atajo/simplificador de $.ajax para envío de POST asíncronos, el cual no permite especificar todas las opciones de $.ajax().

Bien, a $.ajax() podemos especificar la opción 'async' (que por omisión está en true, es decir, todo es enviado de forma asíncrona). Lo que tenemos que hacer es ponerla en false y ya. Es muy simple, en realidad. Dejo el código del script, sustituyendo el $.post() por $.ajax():

<script type="text/javascript">
  $(function() {
    $('.print_link').click(function() {
		var fixedurl = 'http://localhost/miapp/main/set_session_var';

		$.ajax({url: fixedurl,
		  type: 'POST',
		  async: false,
		  data: { object_name: 'tmprow',
           id: $(this).attr('id'),
           monto: $(this).parent().parent().find('.monto').html() }
		});
      return true;
    });
  });
</script>