[Tutorial]–Facebook List, un AutoCompletar Cool para JQuery y su integración con ASP.NET
Hola que tal? Hoy voy ha escribir una especie de tutorial para mostrar como integrar (no es la única forma) el excelente Plugin para jQuery Facebook List, puedes ver el demo de como funciona acá:
http://devthought.com/wp-content/articles/autocompletelist/test.html

También puedes ver un comportamiento similar en Hotmail, cuando elijes a los destinatarios de tu correo

FaceBook List
Este PlugIn, obtiene los datos desde una fuente que le retorne un objeto en notación JSON con los campos:caption y value.
Además puedes agregar a la lista ítems ya previamente seleccionados y agregar nuevos elementos la lista de búsqueda mediantes LI.
Revisa para mayor información:
http://devthought.com/blog/projects-news/2008/01/textboxlist-meets-autocompletion/
Nuestro Ejemplo
Nuestra base es simple, tenemos la siguiente Modelo y su contexto con Linq2Sql asociado.
| MER | Contexto |
 |  |
Como ves, es un listado géneros y sus películas asociadas, de manera de poder consultar por los géneros y obtener un listado de películas.
Ahora hay que crear el código para devolver en notación JSON el listado de géneros para que funcione el autocomplete. Para esto podríamos utilizar Servicios WCF que nos pueden retornar el conjunto de resultados con dicha notación. Pero en este caso , podrías no querer desarrollar un webservice, por lo que vamos a generar la respuesta con JSON desde un WebForm, para esto , creamos el webform getDatos.aspx:
Public Class getDatos
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim datos As String = GetGeneros()
Response.ContentType = "application/json"
Response.Write(datos)
Response.End()
End Sub
Public Function GetGeneros() As String
Dim Items As New List(Of GeneroItem)
Dim modelo As New ModeloDataContext
Dim lista = From p In modelo.Generos Order By p.Genero
For Each g As Genero In lista
Items.Add(New GeneroItem With {.caption = g.Genero, .value = p.Id})
Next
Dim jsonSerializer As New _
System.Web.Script.Serialization.JavaScriptSerializer()
Return jsonSerializer.Serialize(Items)
End Function
Public Class GeneroItem
Public caption As String
Public value As Integer
End Class
End Class
Contamos con una funcion getGeneros que se encarga de obtener mediante linqtoSql una lista de GeneroItem serializada a JSON. Como ves. se obtiene una lista de géneros y luego se pasa a una lista de generoItem y se retorna el resultado “JSONEADO”. La clase GeneroItem tiene los campos necesarios que requiere Facebook-list para crear los ítems al momento de seleccionar el autocompletado.
Luego en la Page_Load obtenemos la respuesta de GetGeneros y escribimos en la página mediante Response.Write esta respuesta, cambiando el ContentType de la página para que se escriba con la notación que necesitamos.
Ahora al momento de ejecutar la página GetDatos.aspx tenemos la respuesta:
[{"caption":"Accion","value":3},
{"caption":"Comedia","value":5},
{"caption":"Drama","value":2},
{"caption":"Suspenso","value":4},
{"caption":"Terror","value":1}]
Que es justamente lo que buscamos
.
Formulario Principal
Para crear esto, me baso en el ejemplo que viene con el plugin, pero vamos a crear más código javascript para que se adapte para trabajar con WebForms. En el tema de diseño, vamos tener lo siguiente:

Veamos el código declarativo
Primero que nada, debemos hacer las referencias necesarias:
<script src="jquery.js" type="text/javascript" charset="utf-8"></script> <script src="fcbkcomplete.min.js" type="text/javascript" charset="utf-8"></script>
Luego seguimos con el código propio del del Plugin:
<ol>
<li id="facebook-list" class="input-text">
<label>
Demo FacebookList - Busca los nombres de los Generos
</label>
<asp:TextBox ID="TxBusca" runat="server"></asp:TextBox>
<ul id="preadded" style="display: none">
<asp:Literal ID="Agregados" runat="server">
</asp:Literal>
</ul>
<div id="facebook-auto">
<div class="default">
Escribe los géneros de las películas a buscar</div>
<ul id="feed">
</ul>
</div>
</li>
</ol>
Según el esquema del plugin, la estructura debe ser la que antes se muestra, el UL con Id preadded sirve para agregar selecciones al cargar el plugin, esto nos va a servir para mantener el estado del plugin, es decir que no se pierda la selección entre PostBack, para esto agregamos un control Literal “Agregados” para que mediante código programático mantengamos las selecciones anteriores, esto se ve apoyado mediante código JavaScript.
<script language="JavaScript">
$(document).ready(function () {
$.facebooklist('#TxBusca', '#preadded', '#facebook-auto',
{ url: 'getDatos.aspx', cache: 1 }, 10,
{ userfilter: 1, casesensetive: 0 });
});
function getList() {
var lista = document.getElementById("facebook-list").children[1];
var i = 0;
var generos = "";
for (i = 0; i < lista.children.length - 1; i++) {
generos = generos + ";" + lista.children[i].outerText;
}
document.getElementById("hf_generos").value = generos;
return true;
}
</script>
El primer código que vemos es propio del plugin, que indica, cual es el input-text, cual es la sección del preadded , el cual tiene que ver con la sección en donde se agregan las selecciones, la URL que retorna la lista en JSON, la cantidad de sugerencias entre otros( para una info detallada, ve a la página del plugin).
Lo que no indica la documentación del plugin es como capturar los valores seleccionados, por lo que vamos a crear una función getList que obtiene cada uno de los valores seleccionados y luego genera una lista separa por ; y se los asignamos a al HiddenField hf_generos. Esta función la llamamos desde la propiedad onClientClick del botón.
<asp:Button ID="Button2"
runat="server"
Text="Buscar"
OnClientClick="getList()" />
De esta manera, al presionar el botón llamamos a la función JavasScript y al método en el código programático:
Protected Sub Button2_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button2.Click
Dim listaGeneros() As String = hf_generos.Value.ToString.Split(";")
Dim modelo As New ModeloDataContext
Dim listaPeliculas = From p In modelo.Peliculas _
Where listaGeneros.Contains(p.Genero.Genero) _
Select p.Nombre, p.Genero.Genero
GrillaPeliculas.DataSource = listaPeliculas
GrillaPeliculas.DataBind()
'volvemos a Poner en la lista lo que había antes
Dim listaAgregados As String = String.Empty
Dim i As Integer
For i = 0 To listaGeneros.Length – 1
If Not String.IsNullOrEmpty(listaGeneros(i)) Then
listaAgregados = listaAgregados + _
String.Format("<li value=""{0}"">{1}</li>", i,
listaGeneros(i))
End If
Next
Agregados.Text = listaAgregados
End Sub
Lo primero tenemos que hacer es obtener desde el HiddenField la lista de seleccione y las pasamos a un arreglo, luego hacemos la consulta con LinQ, para mostrar todos las películas que pertenecen a los géneros seleccionados. Luego ponemos en la lista la selección anterior , para mantener el estado, apoyándonos en el Literal e imprimiendo li con las selecciones previas.
Veamos el Video del funcionamiento:
Baja el ejemplo desde acá:
http://cid-053a660afa3473b3.office.live.com/self.aspx/P%c3%bablico/Autocomplete2.rar
PD:Recuerda que el onClientClick no funciona de manera adecuada en FireFox.
Este es un control que esta es sus primeros pasos, por lo que pueden existir algunos bugs por el momento, pero como vez, es totalmente funcional.
Espero que te sirva!
Gonzalo