Introducción a Linq to JavaScript

Linq es un lenguaje de consulta sobre colecciones de objetos, generalmente escuchamos sobre LinqToSQL , LinqToXML, LinqToDataSet entre otros, pero también lo puedes ocupar con Javascript, el lenguaje de moda Sonrisa

Primero que nada LinqToJavascript  (JSLINQ) es una implementación de Linq to Object en JavaScript. Está creado usando un conjunto de métodos de extensión en Arreglos de Objetos de Javascript. Si estamos utilizando un Arreglo, podemos entonces utilizar LINQ to Javascript.

Ejemplo de Uso

Primero que nada, debes descargar la librería en jslinq.codeplex.com, con la descarga tienes los script y bastantes ejemplos que sin duda, son de gran ayuda. Primero que nada vamos a agregar las referencias a los Script y luego crear un arreglo de objetos

<script type=“text/javascript” src=“scripts/JSLINQ.js”></script>

<script>

  var Personas =[

                {Rut:1, Nombre:“Gonzalo”,Apellido:“Perez”,Edad:32},

                {Rut:2, Nombre:“Pedro”,Apellido:“Correa”,Edad:31},

                {Rut:3, Nombre:“Carlos”,Apellido:“Jerez”,Edad:26},

                {Rut:4, Nombre:“Gonzalo”,Apellido:“Diaz”,Edad:23},

                {Rut:5, Nombre:“Juan”,Apellido:“Rocha”,Edad:19},

                {Rut:6, Nombre:“Jose”,Apellido:“Osses”,Edad:27},

                {Rut:7, Nombre:“Gonzalo”,Apellido:“Mellado”,Edad:21}

            ];

</script>

Debemos crear ahora una instancia del objeto JSLINQ con nuestro arreglo Personas:

var ejemploPersonas = JSLINQ(Personas);

Podemos además ocupar el operador Where para especificar el criterio de selección y además ocupar el método Count()

 

var cantPersonas =JSLINQ(Personas).Where(function(persona){
                         return persona.Nombre == “Gonzalo”;}).Count();

Veamos ahora como recorrer el arreglo de personas resultantes de una consulta por Nombre:

var ejemploPersonas =JSLINQ(Personas).Where(function(persona){
                                return persona.Nombre == “Gonzalo”;
                      });

           

var rs = ejemploPersonas.ToArray();

for (var i in rs) {

    alert( rs[i].Nombre +” “

         + rs[i].Apellido +” “

         + rs[i].Edad);

    }

En el caso que queramos obtener una consulta ordenada por algún campo, en este caso edad, debemos modificar la consulta para incluir el campo edad en el orden:

var ejemploPersonas =JSLINQ(Personas).Where(function(persona){ 

                                  return persona.Nombre == “Gonzalo”;

                        }).OrderBy(function(persona){return persona.Edad;});

           

var rs = ejemploPersonas.ToArray();

for (var i in rs) {

    alert( rs[i].Nombre +” “

         + rs[i].Apellido +” “

         + rs[i].Edad);

}

Y listo!, bastante útil para manejar nuestros objetos JSON que podemos obtener a través de un WS, revisa la página del proyecto y los ejemplos que se descargan para mayor detalle.

Espero que te sirva!

Saludos

@chalalo

 

Dándole más caña, agregando sonido con HTML5 a animaciones jQuery

Este post viene a modificar el ejemplo anterior, es uno en donde ocupamos elementos HTML5  y Modernizr para cargar distintos polyfills para solucionar el problema de la compatibilidad.

Ahora, para darle un poco más “choreza” como decimos por acá, vamos agregar audio con HTML5. Ahora bien, no creo que mucha gente le interese escuchar el sonido a cada rato, pero bueno, es para fines demostrativos.

La modificación al ejemplo consistirá en dejar el formulario oculto y crear una especia de acordeón, de tal manera de ejecutar un sonido cuando se abra y cierre el acordeón.

Algo así:

image image

Estado Cerrado (inicial)

Estado Abierto

En cada abrir y cerrar reproduciremos un sonido, el resultado es el del siguiente video:

Entonces manos a la obra, primero vamos a agregar los tags de audio

    <audio id=“abrir” preload=“auto”>

            <source src=“audio/abrir.mp3” type=“audio/mpeg” />

            <source src=“audio/abrir.ogg” type=“audio/ogg” />

    </audio>

    <audio id=“cerrar” preload=“auto”>

            <source src=“audio/cerrar.ogg” type=“audio/ogg” />

            <source src=“audio/cerrar.mp3” type=“audio/mpeg” />

    </audio>

Como vemos no es necesario mostrar los controles del tag audio, luego, mediante jQuery vamos a hacer play a esto controles.

Los archivos de audio mp3 y ogg los convertí desde wav mediante esta herramienta gratuita (cuidado con sus barras para IE instalables)http://www.koyotesoft.com/audio-software/free-mp3-wma-converter.html imagino que hay mucho mejores, pero fue lo primero que encontré. Entonces, en la carpeta audio agregamos los archivos y listo!

image

PD: Recuerda que no todos los navegadores soportan los mismos codec para reproducción de audio y video, por eso tenemos que agregar diferentes formatos para asegurar compatibilidad. Puedes ver el siguiente cuadro para tener el escenario con el que vas a tener que lidiar:

image

 

Ahora el código jQuery, muy simple para crear el efecto y puedes notar el atributo play para el tag audio con id abrir y el otro tag con el id cerrar:

$(document).ready(function(){

            $(“form”).hide();

            $(“#texto”).toggle(function(){

                $(“form”).slideDown(“slow”);

                $(“#texto”).html(“- Cerrar”);

                $(“#abrir”)[0].play();

        },function(){

               $(“form”).slideUp(“slow”);

               $(“#texto”).html(“+ Abrir”);

               $(“#cerrar”)[0].play();

        });  

});  

 

Y estamos ok, ya tenemos nuestro ejemplo balls breaker con sonido Sonrisa

Espero que te sirva!
@chalalo

Modernizr–Ejemplo práctico 2 : Utilizando Border Radius, elemento date y atributo required

Hola que tal, este vez revisaremos tres ejemplos prácticos en donde podemos utilizar modernizer para detectar características del browser y decidir según la disponibilidad de ellas que hacer, como por ejemplo, incluir librerías o polyfills para mitigar el problema. Puedes ver mi articulo anterior en donde iniciamos esta serie de ejemplos prácticos.

Vamos dos problemáticas , la de la archi nombrada característica de HTML5 de bordes redondeados,también el nuevo elemento date formulario y por ultimo la propiedad “required” de los elementos del formulario.

Ejemplo:

Veamos que cuenta con las siguientes características HTML5:

  1. Bordes Redondeados
  2. Campo Date en el formulario
  3. Campo Date es obligatorio

<!DOCTYPE html>
<html lang=“en”>
    <head>

        <meta charset=“utf-8” />

        <title>Demo</title>

        <style type=“text/css”>

            form{

                 background-color:#9fbfa3;

                 width:300px;

                 padding:15px;

                 border-radius:10px;

                }

           

        </style>

    </head>

    <body>

        <form id=“formulario” action=“#”>

           <label for=“TxFecha”>Seleccione Fecha</label>

           <input type=“date” name=“TxFecha” id=“TxFecha” required>

           <input type=“submit” id=“btEnviar” value=“Enviar”>

        </form>

    </body>

</html>

El resultado en un IE9 es:

image

Si bien existen el soporte a bordes redondeados, no se soporta el campo email ni el atributo “required”

IE7 (Probando con IE9 En modo explorador IE7), no existe soporte para ninguna funcionalidad.

image

En Chrome (16.0.912.77 m), si bien se soporta además el atributo required, no se soporta el campo date:

image

Veamos ahora en Firefox 9.0.1, al igual que Chrome, no se soporta el campo date.

image

El turno de Safari, no soporta required y si bien soporta el campo fecha, lo hace de una manera deficiente a mi parecer, pero al fin y al cabo, lo soporta.

image

Opera, al menos para nuestro ejemplo, lleva la delantera soportando todas las funcionalidades.

image

Ahora vemos como arreglar el código para que exista soporte para bordes redondeados para todos los navegadores:

Primero vamos a ver como solucionar el tema del Borde Redondeado.

Los pasos a seguir serán:

  • Agregar librería Modernizr y jQuery (estoy utilizando versiones de desarrollo)
  • Agregar, solo para asegurarnos de compatibilidad hacia atrás, las propiedades CSS para border radius propietarias.
  • Agregar y ejecutar la librería jquery.corner en el caso de que el browser no soporte nativamente la característica de bordes redondeados, de manera que este script proporcione la funcionalidad, notar que es lazy download, es decir solo se va cargar esta librería cuando se necesite.

<!DOCTYPE html>

<html lang=“en”>

    <head>

        <meta charset=“utf-8” />

        <title>Demo</title>

       <script type=“text/javascript” src=“http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.1.min.js”></script>

        <script type=“text/javascript” src=“http://ajax.aspnetcdn.com/ajax/modernizr/modernizr-2.0.6-development-only.js”></script>

        <style type=“text/css”>

            form{

                 background-color:#9fbfa3;

                 width:300px;

                 padding:15px;

                 -moz-border-radius: 10px;

                 -webkit-border-radius:10px;

                 border-radius: 10px;

                }

           

        </style>

    </head>

    <body>

        <form id=“formulario” action=“#”>

           <label for=“TxFecha”>Seleccione Fecha</label>

           <input type=“date” name=“TxFecha” id=“TxFecha” required=“true”>

           <input type=“submit” id=“btEnviar” value=“Enviar”>

        </form>

    </body>

 

</html>

<script type=“text/javascript”>

        if (!Modernizr.borderradius) {

            $.getScript(“js/jquery.corner.js”, function () {

                $(“form”).corner();

            });

        }

</script>

Si ejecutamos esta página en IE7 veremos:

image

Es decir, ya no hay problema de los bordes redondeados, ahora continuemos con el calendario, para esto vamos a utilizar JqueryUI, el script de calendario, para ello seguiremos los siguientes pasos:

  • Determinar si el navegador soporta el tag input type=”date” mediante modernizer
  • En caso que el browser no cuente con esta característica, cargar el script de jQueryUI y asignárselo al campo fecha, además de cargar dinámicamente el CSS asociado.

if (!Modernizr.inputtypes.date) {

$.getScript(“http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.17/jquery-ui.min.js”, 
function ()
{
 

  var css = jQuery(“<link>”);

  css.attr({ rel:  “stylesheet”,

         type: “text/css”,

         href: “http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.17/themes/ui-lightness/jquery-ui.css”

                           });

       $(“head”).append(css);

       $(“#TxFecha”).datepicker();

    });

}

Ahora ejecutamos en IE y veremos

image

Tenemos bordes redondeados y calendario, pero falta el validador, esta vez no usé jQuery-Validator, ya que lo consideré mucho para un solo campo, pero obviamente consideraría JV para la próxima, en este caso, yo mismo hice una validación de requerido, obviamente es solo a modo de ejemplo, le queda mucho ser algo para producción.

if (!Modernizr.input.required){

               $(“#formulario”).submit(function(){

                  if ($(“#TxFecha”).val().length==0){

                    return fallo();

                   }else{

                    return normal();

                   }

 

               });

 

               $(“#TxFecha”).focus(normal);

        }

               function normal(){

                     $(“#TxFecha”).css(“background”,“white”);

                     $(“#TxFecha”).css(“color”,“black”);

                     $(“#TxFecha”).val(“”);

                     return true;

               }

 

               function fallo(){

                       $(“#TxFecha”).css(“background”,“red”);

                       $(“#TxFecha”).css(“color”,“white”);

                       $(“#TxFecha”).val(“Este campo es necesario”);

                       return false;

                  

                   }

Luego al probarlo, tenemos lo siguiente:

image

Si bien no es lo mismo, podemos lograr un efecto más deseado con distintos plugins.

Para terminar veamos las cargas de archivos con los dos navegadores (obviamente todos van a cargar jQuery y Modernizr)

IE7 (todos los polyfills)

image

IE9(Solo jQueryUI, ya que soporta bordes redondeados)

image

Firefox(Solo jQueryUI, ya que soporta bordes redondeados)

image

Chrome(Solo jQueryUI, ya que soporta bordes redondeados)

image

Opera (No necesita cargar pollyfills)

image

Como puedes ver, solo se cargan los scripts cuando se les necesita, aumentando el rendimiento.

Espero que les sirva!
Saludos,

[Tips]Ejecutar métodos en paralelo en ASP.NET 3.5

Hola, en esta ocasión quiero volver a tocar el tema de la ejecución en paralelo de métodos en ASP.NET, que si bien está muy optimizado en la versión 4.5, que aún está en desarrollo, muchos de nosotros no tenemos planes a corto plazo de migrar para aprovechar las ventajas.

Veamos un escenario común, grillas grillas combos combos, a que me refiero con esto, es que muchas veces nuestros sistemas cargan una cantidad considerable de combos que no están asociados e igual cantidad de grillas en el Page Load. Generalmente no es necesario que esto se cargue secuencialmente, y podemos aprovechar las ventajas en términos de tiempo al utilizar la carga en paralelo.

Para explicar un poco más vamos a crear un pequeño proyecto, que tenga 2 DropDownList (o combos, como le llamamos universalmente). Cada uno de estos combos va a tener una duración de carga de 3 segundos, obviamente de manera secuencial se va a demorar mínimo 6 segundos la carga de la página, mientras que en paralelo, claro como el agua, mínimo 3 segundos:

image image

Carga Secuencial Triste

Carga Paralela Sonrisa

Ahora veamos el código

El código de la página con carga secuencial:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

        If Not Page.IsPostBack Then

            dd_ciudades.DataSource = Obtciudades()

            dd_ciudades.DataBind()

            dd_regiones.DataSource = Obtregiones()

            dd_regiones.DataBind()

        End If

End Sub

 

 

Public Function Obtciudades() As List(Of Ciudad)

   System.Threading.Thread.Sleep(3000)

   Dim ciudades As New List(Of Ciudad)

   ciudades.Add(New Ciudad With {.id = 1, .nombre = “Concepcion”})

   ciudades.Add(New Ciudad With {.id = 2, .nombre = “Santiago”})

   ciudades.Add(New Ciudad With {.id = 3, .nombre = “Viña del Mar”})

   ciudades.Add(New Ciudad With {.id = 4, .nombre = “Puerto Montt”})

   ciudades.Add(New Ciudad With {.id = 5, .nombre = “Cañete”})

   Return ciudades

End Function

 

 

Public Function Obtregiones() As List(Of Region)

   System.Threading.Thread.Sleep(3000)

   Dim regiones As New List(Of Region)

   regiones.Add(New Region With {.id = 1, .nombre = “Primera Region”})

   regiones.Add(New Region With {.id = 2, .nombre = “Segunda Region”})

   regiones.Add(New Region With {.id = 3, .nombre = “Tercera Region”})

   regiones.Add(New Region With {.id = 4, .nombre = “Cuarta Region”})

   regiones.Add(New Region With {.id = 5, .nombre = “Quinta Region”})

   Return regiones

End Function

Puedes notar los métodos Sleep para causar la demora en el thread de ejecución en cada uno de los métodos que sirvan para poblar los dropdownlist.Ahora si vemos la carga del la página con el IE Developer Toolbar, el resultado son 6.07 segundos:

image

Veamos el código para ASP.NET 3.5, es más largo pero la relación costo beneficio es muy buena, ya que vamos a bajar los tiempos casi a la mitad. Como dije anteriormente, implementar esta misma funcionalidad en ASP.NET 4.5 es mucho más sencillo, ya que elimina las complejidades al momento de especificar cuales métodos serán ejecutados de manera Asíncrona, pero eso lo dejaremos para otro post Sonrisa

Imports Microsoft.VisualBasic
Imports System.Threading 

 

Partial Class Paralelo

    Inherits System.Web.UI.Page

 

    Private ehRecuperarDatosDeDropDownList1 As EventHandler = Nothing

    Private ehRecuperarDatosDeDropDownList2 As EventHandler = Nothing

    Private listaRegiones As New List(Of Region)

    Private listaCiudades As New List(Of Ciudad)

Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load

  Dim pat1 As New PageAsyncTask(New BeginEventHandler(AddressOf
 
   Me.RecuperarDatosDeDropDownList1), New EndEventHandler(AddressOf
      Me
.CargarDropDownList1), Nothing, Nothing, True)

  Dim pat2 As New PageAsyncTask(New BeginEventHandler(AddressOf
      Me
.RecuperarDatosDeDropDownList2), New EndEventHandler(AddressOf
        Me
.CargarDropDownList2), Nothing, Nothing, True)

  Page.RegisterAsyncTask(pat1)

  Page.RegisterAsyncTask(pat2)

End Sub

 

#Region “dd_regiones”

Private Function RecuperarDatosDeDropDownList1(sender As Object, e As
      EventArgs
, cb As AsyncCallback, state As Object) As
IAsyncResult

      Me.ehRecuperarDatosDeDropDownList1 = New EventHandler(AddressOf
         Me.RecuperarRegiones)

     Return Me.ehRecuperarDatosDeDropDownList1.BeginInvoke(Me, 
     EventArgs
.Empty, cb, Nothing)
End Function

 

Private Sub RecuperarRegiones(sender As Object, e As EventArgs)

    Me.listaRegiones = Obtregiones()

End Sub

 

Private Sub CargarDropDownList1(ar As IAsyncResult)

  Me.ehRecuperarDatosDeDropDownList1.EndInvoke(ar)

  Me.dd_regiones.DataSource = Me.listaRegiones

  Me.dd_regiones.DataBind()

End Sub

 

Public Function Obtregiones() As List(Of Region)

   System.Threading.Thread.Sleep(3000)

   Dim regiones As New List(Of Region)

   regiones.Add(New Region With {.id = 1, .nombre = “Primera Region”})

   regiones.Add(New Region With {.id = 2, .nombre = “Segunda Region”})

   regiones.Add(New Region With {.id = 3, .nombre = “Tercera Region”})

   regiones.Add(New Region With {.id = 4, .nombre = “Cuarta Region”})

   regiones.Add(New Region With {.id = 5, .nombre = “Quinta Region”})

   Return regiones

 End Function

#End Region

 

#Region “dd_ciudades”

 Private Function RecuperarDatosDeDropDownList2(sender As Object, e As EventArgs, cb As AsyncCallback, state As Object) As IAsyncResult

 

   Me.ehRecuperarDatosDeDropDownList2 = New EventHandler(AddressOf Me.RecuperarCiudades)

   Return Me.ehRecuperarDatosDeDropDownList2.BeginInvoke(Me,
    EventArgs
.Empty, cb, Nothing)

 End Function

 

Private Sub RecuperarCiudades(sender As Object, e As EventArgs)

        Me.listaCiudades = Obtciudades()

End Sub

 

Private Sub CargarDropDownList2(ar As IAsyncResult)

  Me.ehRecuperarDatosDeDropDownList2.EndInvoke(ar)

  Me.dd_ciudades.DataSource = Me.listaCiudades

  Me.dd_ciudades.DataBind()

End Sub

 

Public Function Obtciudades() As List(Of Ciudad)

  System.Threading.Thread.Sleep(3000)

  Dim ciudades As New List(Of Ciudad)

  ciudades.Add(New Ciudad With {.id = 1, .nombre = “Concepcion”})

  ciudades.Add(New Ciudad With {.id = 2, .nombre = “Santiago”})

  ciudades.Add(New Ciudad With {.id = 3, .nombre = “Viña del Mar”})

  ciudades.Add(New Ciudad With {.id = 4, .nombre = “Puerto Montt”})

  ciudades.Add(New Ciudad With {.id = 5, .nombre = “Cañete”})

  Return ciudades

End Function

#End Region

 

End Class

 

Ciertamente el código puede resultar confuso,(adjunto el código fuente, ya que se ve mejor en Visual Studio que en el blog), primero se registran las “tareas” que vamos a correr en paralelo, cada tarea tiene un método de inicio(BeginEventHandler), y método de finalización (EndEventHandler), luego registramos cada una de estas tareas, en este caso son dos, lo hacemos llamando al método RegisterAsyncTask de la página.

Los métodos ObtCiudades y ObtieneRegiones no sufren alteraciones, ahora al momento de ejecutar la página, obtenemos mejores tiempo, tal cual habíamos estimado, 3,16 segundos.

image

Claro está que solo estoy usando esta funcionalidad con dos métodos, puedes utilizarlos con más según tu conveniencia.

Puedes bajar el código desde acá

image

Espero que te sirva!
@chalalo

Modernizr–Ejemplo práctico 1 : Utilizando Placeholder

image

Como ya saben Modernizr es una librería JavaScript que nos permite detectar las capacidades del soportadas por el navegador en relación a HTML5 y CSS3. Esto nos será en extremo útil cuando estemos desarrollando nuestras páginas con funcionalidades incluidas  HTML5 y deseemos que, en la medida de lo posible, usuarios con navegadores antiguos puedan tener la misma experiencia de usuarios, es decir, simular la característica nativa de HTML5 con un pollyfill, que básicamente son códigos o plugins que proveen la tecnología que nosotros, los desarrolladores, esperaríamos que el browser soportara nativamente.

Ejemplo práctico – PlaceHolder

El atributo Placeholder

Atributo HTML5, que podemos describirlo como el texto que aparece dentro de un campo de texto antes de que este tenga el foco, cuando el campo pierde el foco y si el campo está vacío, aparece nuevamente el texto. Ejemplo:

<label for="Rut">Ingrese su Rut:</label>
<input type="text" placeholder ="Ej: 13657654-K" id="rut" />

Lo que resulta en lo siguiente:

image

Ahora bien, que pasa y con browser que no soporten esta característica? y como detectamos si el browser que navega nuestra página no soporta esta funcionalidad? Tenemos dos opciones:

La más fácil : No hacer nada, simplemente las personas que naveguen con browser antiguos no van a tener esta funcionalidad

Lo mejor, mantener la experiencia de usuario, utilizando Modernizer y PollyFills

Paso 1, Agregar la librería Modernizr

<script src="js/modernizr-1.5.min.js"></script>¨

Paso 2, Agregar el código de detección y Pollyfill

if(!Modernizr.input.placeholder){

  $(‘[placeholder]’).focus(function() {
   var input = $(this);
   if (input.val() == input.attr(‘placeholder’)) {
       input.val(”);
       input.removeClass(‘placeholder’);
  }
  }).blur(function() {
     var input = $(this);
     if (input.val() == ” || input.val() == input.attr(‘placeholder’)) {
         input.addClass(‘placeholder’);
         input.val(input.attr(‘placeholder’));
     }
}).blur();
$(‘[placeholder]’).parents(‘form’).submit(function() {
    $(this).find(‘[placeholder]’).each(function() {
    var input = $(this);
    if (input.val() == input.attr(‘placeholder’)) {
       input.val(”);
    }
  })
});

Como puedes ver, el primer if , detecta mediante el objeto Modernizr la capacidad del navegador , y si no soporta placeholder (que es un atributo de input), entonces aplicamos el código jQuery que provee la misma funcionalidad del placeholder nativo HTML5.

image

En navegadores que aún no soportan este atributo, mediante la técnica de graceful degradation vamos a lograr similares experiencias de usuario en navegadores antiguos.

Saludos!, pronto subo más ejemplos.

@chalalo

Grabación WebCast, Nuevas características de Visual Studio 2011 para el Desarrollo Web.

Hola!, para empezar el año, les dejo un video de algunas de las nuevas características de Visual Studio 2011 para el desarrollo con ASP.NET. Bueno ya estamos en el 2012, quizás Visual Studio cambie de nombre a Visual Studio 2012, no lo sé. Sin más teorías, acá está el video:

Los puntos a tratados en este WebCast son:

  • Nuevas características en el Solution Explorer
  • Nuevas características de desacoplamiento de ventanas
  • Editor CSS (Regiones, Helpers, Autocompletación)
  • Editor JavaScript (Referencia de Definiciones, Referencia a librerías)
  • Nuevas posibilidades del editor de código (Asociar Eventos, agregar columnas en grillas)
  • Repeters Tipados, Bundling , Validaciones no Intrusivas
  • Instalación de Librerías mediante NuGet , ValidateRequestMode.

Espero que les sea de ayuda Sonrisa

Saludos!
@chalalo