29 de abril de 2010

Sufijos para Tipos de Datos Numéricos

Este pequeño TIP está relacionado con una pregunta que me hicieron hoy. Resulta que esta persona quería realizar una operación matemática, multiplicar una constante double con un decimal (double * decimal):

decimal result = 16.5 * FuncionQueDevuelveDecimal()

Pues bien, el problema es que el compilador le daba lógicamente el siguiente error:

El operador '*' no se puede aplicar a operandos del tipo 'double' y 'decimal'

Para solucionarlo el colega convirtió la constante double en un decimal (Convert.ToDecimal(16.5)), y aunque es cierto que esto funciona, en realidad podríamos hacer lo siguiente:

decimal result = 16.5M * FuncionQueDevuelveDecimal()

Pues bien visto el caso, aprovecho y dejo la siguiente tabla que muestra los diferentes sufijos para tipos numéricos que podemos emplear en C#:

Sufijos C# para Tipos de Datos Numéricos

Tipo de Dato  C# Sufijo
long L
float F
double D
decimal M
uint UI
ulong UL
short, int, ushort No tienen sufijo.

 

 

Artículos Relacionados:

22 de abril de 2010

Nullable Types en C#

Los “Nullable Types” son tipos especiales de datos que permite que los tipos bases de .Net se puedan comportar como si fueran 'clases', o sea, no es otra cosa que permitir que un int (por ejemplo) permita también almacenar valores nulos.

int? a = 1;
int? b = null;

Nota:
En realidad un Nullable Type es una struct (estructura) por lo cual sigue siendo un tipo por valor y no por referencia. Más adelante veremos un ejemplo de esto.

Al ser una estructura posee un grupo de propiedades que podemos aprovechar. Por ejemplo, muchas veces me he encontrado código escrito de la siguiente manera (o alguna otra parecida):

int b = (a != null) ? Convert.ToInt32(a) : 0;

Nótese que en el código estamos convirtiendo la variable a (que es de tipo int?) a tipo entero (int Convert.ToInt32), de lo contrario el proyecto NO compilaría. Pero sabemos que a es de tipo nullable y por ende una estructura (struc) con ciertas propiedades que podríamos usar:

//Cualquiera de estas 2 variantes
int b = (a != null) ? a.Value : 0;
int b = (a.HasValue) ? a.Value : 0;

De esta forma nos estaríamos ahorrando la conversión a entero.

 

Nullable Type ¿Es una clase o estructura? ¿class or struct?

La mejor manera de comprobarlo, es mediante un ejemplo y chequeando los resultados. Antes debemos de partir de una de las principales diferencias entre clases y estructuras:

  • Las clases (class) son tipos por referencia.
  • Las estructuras (struc) son tipos por valor.
static void Main(string[] args)
{
  int? a = 1;
  int b = (a.HasValue) ? a.Value : 0;
 
  TestTypeNullable(a, ref b);
}
 
private static void TestTypeNullable(int? a, ref int b)
{
  a++;
  b++;
}

Types Nullables

La imagen muestra los valores de las variables a y b, después de ejecutar el método TestTypeNullable.

En las 2 primeras líneas, a = b = 1. Después llamamos al método pasándole a (por valor) y b (por referencia).

Como vemos, a mantiene el valor original (1) lo que demuestra que fue 'pasado' por valor; y como ya sabemos las clases son tipos por referencia, por ende a es una estructura (struct) y podemos llegar a la conclusión de que los tipos anulables son estructuras (struct).

 

Artículos Relacionados:

17 de abril de 2010

jQuery Tooltip qTip Optimización

Veremos, mediante un ejemplo, lo sencillo que es agregar Tooltip con jQuery, usando el plugin qTip. Además comentaré un ejemplo de rendimiento real que se me presentó y solventé usando algunas técnicas jQuery junto con este control (qTip).

Este post contará de 2 partes:

  1. Uso e implementación simple del plugin jQuery qTip.
  2. Optimización de páginas que usen Tooltip qTip.

 

jQuery qTip, Ejemplo Sencillo

El uso de los Tooltip es muy frecuente y muy vistoso, sobre todo cuando puedes insertar código HTML en el Tooltip, y este es el caso que hoy nos ocupa, hablaremos del plugin jQuery qTip. En esta primera parte veremos un ejemplo bien simple, no profundizaremos demasiado porque el sitio oficial de este plugin está bastante completo y documentado.

Para nuestro ejemplo tendremos que tener los .js de jQuery y también el del plugin qTip, ambos podrás descargártelos desde los sitios oficiales.

Pero veamos el código del ejemplo:

<HTML xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title>jQuery Tooltip Simple</title>
 
  <script src="../Scripts/jquery-1.3.2.min.js" type="text/javascript"></script>
  <script src="../Scripts/jquery.qtip-1.0.0.js" type="text/javascript"></script>
 
  <script type="text/javascript">
    $(document).ready(function() {
      $('p').qtip({
        content: 'El texto a mostrar <b>jQuery Tooltip</b>'
       });
     });
   </script>  
</head>
<body>
  <p style="width:110px;">Mostrar Tooltip</p>
</body>
</HTML>

hasta aquí el uso simple y estándar de este plugin jQuery. Veamos en la segunda parte el problema que se me presentó en un proyecto real.

 

jQuery Tooltip, Ejemplo Optimización

Recientemente estaba trabajando en un proyecto donde mostrábamos distintos Tooltip usando este plugin jQuery. Ver imagen:

jQuery Tooltip 

Al pasar por encima del cuadro resaltado en amarillo, aparecía el Tooltip relacionado (HTML marcado en azul), y todo estaba bien, pero, y siempre hay un pero:

Problema:

El problema estaba en que el HTML correspondiente al Tooltip lo generábamos dinámicamente del lado del servidor, y al mostrar unos 200 resultados aproximadamente, pues nada, que la página se recargaba bastante con información que en la mayoría de los casos no se usaba.

Solución:

Para solucionarlo lo que hicimos fue una mezcla de varias cosas:

  1. En lugar de construir todo el HTML en el servidor, almacenamos solo los datos necesario para poder construir el HTML en el navegador (javascript).
  2. Construir el HTML por javascript en el navegador, solo cuando se necesita (solo si se pasa por encima (mouseover)).
  3. Asociar el HTML generado con el plugin jQuery Tooltip qTip.

Por simplicidad, solo mostraré el código que puede resultar interesante y no el ejemplo integro.

1. Generando en el el servidor los datos en JSON:

litEscalas.Attributes.Add("jsonData", DevToolTipJsonEscalas(itinerario));

Aquí adicionamos un atributo "jsonData"al literal, este atributo contendrá los datos necesarios en formato JSON, veamos el código de la función DevToolTipJsonEscalas:

private string DevToolTipJsonEscalas(Itinerario itinerario)
{
  StringBuilder sb = new StringBuilder("[");
  . . . .
  . . . .
 
  sb.Append("{ ");
  sb.Append("'Var1': '1', 'Var2': 'Val2'" . . . .
  sb.Append(" }");
  . . . .
  . . . .
 
  sb.Append("]");
  return sb.ToString();
}

 

Nota: Esta función no está completa, lo importante que debes saber es que el string devuelto debe estar en formato JSON ( [{}, {}, {}] )

 

2. Construir el HTML por javascript en el navegador:

En la página web tendríamos una función que dado el JSON recién construido sea capaz de formar el HTML que necesitamos para mostrar en el Tooltip:

//Construir la tabla del Tooltip Itinerario
function BuildToolTipItinery(jsonData) {
  var arrData = eval('(' + jsonData + ')');
 
  if (arrData == undefined) return 'Nada...';
 
  var table = "<div>";
  table += "<table width='100%'>";
 
  for (var i = 0; i < arrData.length; i++) {
    var isHead = parseInt(arrData[i].IsHead);
    if (isHead == 1) {
      table += "<tr><td colspan='4'>"
               + arrData[i].HeadTest
               + "</td></tr>";
    }
    else {
      table += "<tr>" +
                  '<td>' + arrData[i].Date1 + '</td>' +
                  '<td>' + arrData[i].Time1 + '</td>' +
                  '<td>' + arrData[i].AirPort1 + '</td>' +
                  '<td>Terminal: ' + arrData[i].Terminal1 + '</td>' +
                '</tr>';
      table += "<tr>" +
                  '<td>' + arrData[i].Date2 + '</td>' +
                  '<td>' + arrData[i].Time2 + '</td>' +
                  '<td>' + arrData[i].AirPort2 + '</td>' +
                  '<td>Terminal: ' + arrData[i].Terminal2 + '</td>' +
                '</tr>';
    }
  }
 
  table += "</table></div>";
  return table;
}

Nota: Esta función javascript si la dejaré tal como estaba para no perder tiempo, el lector deberá tener en cuenta cuales han sido las propiedades de su caso en particular.

 

3. Asociar el HTML generado con el plugin jQuery Tooltip qTip:

Por último hacemos la asociación:

$(document).ready(function() {
    $('.ShowToolTipItinerario').one('mouseover', function(event) {
      event.preventDefault();
      $this = $(this);
      $this.attr('title', BuildToolTipItinery($this.attr('jsonData')));
      var optionTT = {
        position: {
          corner: { target: 'topLeft'
                    tooltip: 'bottomRight'} },
          style: { padding: 5, width: 450}
        };    
      $this.qtip(optionTT);
     
      $this.trigger('mouseover');
    });
});

Aquí debemos tener algunas cosas en cuenta:

  1. Los literales a los que asociaremos los Tooltip tendrán como clase '.ShowToolTipItinerario'.
  2. Nótese que usamos el método jQuery one(), que solo se lanzara una única vez.
  3. Posteriormente asociamos el elemento al que se le ha pasado el mouse por encima ('mouseover'), con el plugin qTip (Además hemos personalizado algunos comportamientos del plugin qTip).
  4. Y por ultimo lanzamos o forzamos el evento 'mouseover', de lo contrario tendríamos un efecto extraño debido a que la primera vez que pasaras por encima del literal no se mostraría Tooltip alguno.

Y eso fue todo, así pudimos solucionar nuestro problema, y la página que inicialmente pesaba unos 1500 KB (y si digo bien 1500 KB) la rebajamos a 385 KB.

 

Artículos relacionados:

15 de abril de 2010

jQuery Resumen Selectores (jQuery Selectors)

En este post pretendo resumir (a modo chuleta jQuery) los principales selectores de jQuery.

Los selectores jQuery los usamos para encontrar elementos en una página web; y la sintaxis sería la siguiente:

$('Selector')

 

Selectores jQuery

Selector Elementos que Selecciona...
* Todos los elementos.
#id El elemento con el ID dado.
element Todos los elementos del tipo dado.
.class Todos los elementos con la clase dada.
a, b Elementos que coincidan con la a o con b.
a b Elementos b que son descendientes de a.
a > b Elementos b que son hijos de a.
a + b Elementos b a continuación de a.
a ~ b Elementos que son hermanos de a.
:first El primer elemento en el conjunto resultado.
:last El último elemento en el conjunto resultado
:not(a) Todos los elementos en el conjunto resultado que coinciden por a.
:even Elementos pares en el conjunto resultado (en base 0).
:odd Elementos impares en el conjunto resultado (en base 0).
:eq (index) Un elemento numerado en el conjunto resultado (en base 0).
:gt (index) Todos los elementos en el conjunto resultado (mayor que) después del índice dado (en base 0).
:lt (index) Todos los elementos en el conjunto resultado antes (menor que) el índice dado (en base 0).
:header Elementos de encabezado (por ejemplo. <h1>, <h2>).modo chuleta
:animated Elementos con una animación en progreso.
: contains (text) Elementos que contienen el texto facilitado.
:empty Elementos sin nodos hijos.
:has (a) Elementos que contienen un elemento descendientes que coincide con a.
:parent Elementos que tienen nodos hijos.
:hidden Elementos que están ocultos por medio de CSS o porque son <input type="hidden" />.
:visible Lo inverso de: hidden.
[attr] Elementos que tienen el atributo attr.
[attr=value] Elementos cuyo atributo attr es value.
[attr!=value] Elementos cuyo atributo attr no es value.
[attr^=value] Elementos cuyo atributo attr empieza con value.
[attr$=value] Elementos cuyo atributo attr termina con value.
[attr*=value] Elementos cuyo atributo attr contiene la subcadena value.
:nth-child (index) Elementos que son el hijo index de su elemento padre (base 1).
:nth-child (even) Elementos que son un hijo par de su elemento padre (base 1).
:nth-child (odd) Elementos que son un hijo impar de su elemento padre (base 1).
:nth-child (formula) Elementos que son el hijo n de su elemento padre (base 1). Las formulas son de la forma an+b para enteros a y b.
:first-child Elementos que son el primer hijo de su padre.
:last-child Elementos que son el último hijo de su padre.
:only-child Elementos que son el único hijo de su padre.
:input Todos los elementos <input>, <select>, <textarea> y <button>.
:text Elementos <input> con type="text".
:password Elementos <input> con type="password".
:radio Elementos <input> con type="radio".
:checkbox Elementos <input> con type="checkbox".
:submit Elementos <input> con type="submit".
:image Elementos <input> con type="image".
:reset Elementos <input> con type="reset".
:button Elementos <input> con type="button", y elementos <button>.
:file Elementos <input> con type="file".
:enable Elementos de formulario activados.
:disable Elementos de formulario desactivados.
:checked Casillas de verificación y botones de opción seleccionados.
:selected Elementos <option> seleccionados.

 

Nota: Estos son algunos de los principales selectores jQuery

Referencia: Learning jQuery 1.3, un excelente libro.

 

Artículos relacionados:

9 de abril de 2010

HttpContext.Current: Obtener variables de Session en metodos Static

En esta ocasión quiero compartir una nota rápida, y es el uso de la propiedad Current de la clase HttpContext (HttpContext.Current).

HttpContext.Current: Obtiene o establece el objeto HttpContext de la solicitud HTTP actual.

Esta propiedad tiene muchos usos interesantes, pero quiero compartir uno que recientemente usé en un caso práctico. Así que como siempre paso a contar la problemática y colocarnos en contexto.

 

Ejemplo de uso de HttpContext.Current

Recientemente estaba modificando una página web; esta tenía una llamada Ajax a un WebMethod que se encontraba en la misma página. Dicho método era evidentemente estático, por lo que no se podía obtener de forma directa el valor de la variable de Session. Como se necesitaba poder leer la variable de Session, lo que se hizo inicialmente fue declarar una propiedad estática para su uso posterior, como se muestra en el código:

public partial class Page_Ajax_Test : Page
{
  public static string strUsuario = string.Empty;
 
  protected void Page_Load(object sender, EventArgs e)
  {
    strUsuario = Session["idUsuario"].ToString();
  }
 
  [WebMethod]
  public static bool RecuperarReserva(string datos)
  {
    string usuario = strUsuario;
    ... ...

Para la segunda y definitiva variante (más elegante) se usó la propiedad HttpContext.Current y así no tuvimos la necesidad de crear una variable estática a la página, el código quedó así:

public partial class Page_Ajax_Test: Page
{
  protected void Page_Load(object sender, EventArgs e) {}
 
  [WebMethod]
  public static bool RecuperarReserva(string datos)
  {
    int idUsuario;
    string usuario = HttpContext.Current.Session["idUsuario"].ToString();
 
    if (int.TryParse(usuario, out idUsuario))
      return DoSomething(idUsuario);
 
    return false;
  }

Esta propiedad HttpContext.Current tiene otros muchos usos prácticos, te invito a que dejes algún comentario sobre posibles usos.

 

Artículos relacionados:

1 de abril de 2010

Como Crear Plugin jQuery (Plug-ins en jQuery)

Veamos un ejemplo simple de como crear un Plugin jQuery.

Sin dudas la aceptación de jQuery está basada en su robustez y sencillez de uso, pero también en la gran cantidad de plugins que la comunidad a desarrollado para el Framework jQuery. Hoy veremos lo extremadamente sencillo que resulta crear un plugin para jQuery. En realidad exploraremos 2 variantes distintas de crear plugins jQuery (las 2 primeras):

  1. Plugin, Función Global jQuery.
  2. Plugin jQuery asociado a un objeto jQuery.
  3. Métodos Abreviados jQuery. (De estos hablaré en otra ocasión.)

 

Función Global jQuery

jQuery dispone de un determinado grupo de funciones globales ($.each(), $.ajax(), $.data(), etc.), pero además nos da la posibilidad de que nosotros implementemos nuestras propias utilidades o métodos globales jQuery. Para explicarles como lograrlo desarrollaremos una simple función o método $.showAlert() que recibirá un mensaje y mostrará el archiconocido alert() de javascript.

Nota: El ejemplo carece de sentido pero nos dará la idea concreta de lo que podemos lograr.

Después de implementada esta función ($.showAlert()), en teoría podrías hacer esta llamada en nuestras páginas web:

$.showAlert('Probando la creación de funciones jQuery globales.');

Pero pasemos al código. Lo primero que haremos es crear un archivo js donde implementar nuestra función global jQuery, en mi ejemplo lo nombraremos "jQuery.MiEmpresa.FuncionesGlobales.js", y contendrá el siguiente código:

//JQuery.MiEmpresa - Funciones Globales
jQuery.showAlert = function (mensaje) {
  alert(mensaje);
}

Nuestra función global jQuery $.showAlert() lo único que hace es recibir un parámetro y mostrarlo en un alert() básico. Ya habíamos comentado que apenas tenía sentido nuestro ejemplo, pero es solo para dar una idea, a lo mejor este ejemplo sería mucho más útil sí en lugar de mostrar un alert(), creamos un dialogo modal jQueryUI para mostrar el mensaje con un aspecto más elegante.

Y así de simple es crear una Función Global jQuery.

Nota: Al crear plugins o métodos jQuery, NO deberíamos usar el método abreviado $. Debemos tener en cuenta que (bajo determinadas circunstancias y para evitar conflictos) puede abandonarse el uso del método abreviado con $.noConflict().

 

Plugin jQuery asociado a Objeto jQuery

Además de las funciones globales, jQuery también dispone de un amplio grupo de métodos de objetos ($('Selector').css(), $('Selector').attr(), $('Selector').val(), etc.), pero además la comunidad de desarrolladores jQuery ha implementado un sin número de plugins ($('Selector').autocomplete(), $('Selector').dialog(), $('Selector').jqGrid(), etc.). Veamos entonces como crear nuestro propio plugin jQuery.

Como siempre lo haremos a través de la implementación de un ejemplo. Imaginemos que tenemos un input text (TextBox) y que en él solo queremos captar valores alfanuméricos, por ejemplo es un valor de cantidad lo que captaremos. Pues este será nuestro objetivo, crear un plugin jQuery que nos cree una mascara que solo nos permita captar dígitos (input mask alfanuméricos). Al Plugin jQuery creado le nombraremos .soloDigitos().

Ver demo del plugin jQuery que crearemos.

Para mejor comprensión del plugin jQuery .soloDigitos(), dividiremos el artículo en 2 partes:

  1. En la primera, solo haremos la funcionalidad de que al input no se le puedan entrar caracteres que NO sean alfanuméricos.
  2. Posteriormente convertiremos dicha funcionalidad en un plugin para jQuery.

Input Mask Alfanuméricos

Como el objetivo de este artículo no es la funcionalidad en sí, sino más bien la creación del plugin, pues me limitaré a escribir el código y hacer algún escaso comentario:

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title>Crear Plugin jQuery</title>
 
  <script type="text/javascript"
    src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script>
 
  <script type="text/javascript">
    $(document).ready(function () {
      $('.NumberInteger').keypress(function (event) {
        if (event.which && (event.which < 48 || event.which > 57)) {
          event.preventDefault();
        }
      });
    });
  </script>
</head>
<body>
  <label for='cantidad'>Cantidad:</label>
  <input id='cantidad' class='NumberInteger' type="text" />
  <br /><span>Solo valores númericos</span>
</body>
</html>

En el ejemplo solo creamos un input al cual le pusimos como class='NumberInteger', lo hicimos para usar el selector jQuery $('.NumberInteger').

Para el selector anterior estamos implementando el evento keypress, dicho evento nos ofrece la propiedad .which que nos informa del código ASCII pulsado. Lo que hacemos es preguntar si la tecla pulsada no es un digito (menor que 48 o mayor que 57), en caso de no serlo invocamos al evento .preventDefault(), impidiendo que se inserte el caracter.

Con esto ya logramos que solo podamos insertar dígitos en el input; veamos ahora como convertir esta funcionalidad en un Plugin jQuery.

Crear Plugin jQuery

Para ello nos crearemos un fichero .js que contendrá el siguiente código:

jQuery.fn.SoloDigitos = function () {
  this.keypress(function (event) {
    if (event.which && (event.which < 48 || event.which > 57)) {
      event.preventDefault();
    }
  });
 
  return this;
};

La función escrita aquí es similar a la de la página, aunque hemos hecho algunos pequeños cambios para convertirla en plugin jQuery:

  1. Hemos definido la función como una nueva propiedad de jQuery.fn. Esto registra la función como un plugin jQuery.
  2. Utilizamos la palabra clave this para hacer referencia al objeto jQuery sobre el que actuará el plugin.
  3. Por último devolvemos this para garantizar que nuestro nuevo método se pueda encadenar.

Y con esto ya hemos creado un nuevo plugin jQuery, así de fácil… ahora podemos hacer lo siguiente en la página:

$('.NumberInteger').soloDigitos();

Al hacerlo de esta nueva forma, el código de la página queda mucho más claro e intuitivo.

Ver demo del plugin jQuery que crearemos.

Nota: Hemos implementado un Plugin jQuery extremadamente sencillo, pero si estas pensando en crear algo más complejo para compartir deberás tener en cuenta otros aspectos (Parámetros Opcionales, Métodos Transversales, Funciones Callback, entre otras reglas).

Artículos relacionados: