Archive for November, 2007

Jquery UI: usando draggables y droppables

Tuesday, November 27th, 2007

En algún momento te haz preguntado; ¿Como obtengo el objeto, que estoy arrastrando con el ratón usando jquery.ui?; la pregunta es facil de responder y trataremos de explicar algunas cosas sobre draggables y dropables para entender mejor.

El concepto para comenzar a utilizar ui.draggables y ui.droppables es sencillo; simplemente creen un par de DIV (de ejemplo); cada uno con un nombre distinto (pueden, opcionalmente, agregarle el classname “draggable” o “droppable” para llegarle por selectores CSS como siempre se puede en jquery) y posicionenlos en cualquier area separada de pantalla (sea usando position: absolute o porque los han colocado dentro de tablas o celdas separadas).

Ahora viene la magia! detrás de jquery: para arrastrar simplemente declaren al DIV1 draggable:

$(”#dragged”).draggable();

Opcionalmente, pueden decirle al objeto draggable que genere un “clon”; esto es, que cuando se inicia el arrastre del objeto; no se arrastra al DIV1, sino a un “clon” del DIV1.

$(”#dragged”).draggable({
helper: ‘clone’
});

Posteriormente viene la declaración del DIV2, en este caso un contenedor de objetos “arrastrados” (droppable); igual que el anterior, podemos indicar que es droppable:

$(”#dropped”).droppable();

Claro, en este caso podemos contar con ciertas opciones para restringir o personalizar nuestro “droppable”:

accept: “.draggable”, : nos permite indicar que tipo de objeto (referencia a un id o selector) aceptará este droppable

activeClass: ‘droppable-active’, :cuando el droppable tenga dentro de si un “draggable”, cambiará su CSS a este estilo

hoverClass: ‘droppable-hover’, : cuando pasamos por encima (mouseover) el objeto draggable, esta será el estilo CSS aplicado

tolerance: ‘fit’ :tipo de tolerancia con los draggables, puede ser “fit”, si caen completo dentro del droppable, “intersect”, si los bordes del droppable y el draggable se intersectan.

Además, droppable posee una serie de “eventos” que pueden ser funciones callback que ocurren cuando un draggable los libera.

ejemplos:

drop: function(ev, ui) { //ocurre cuando el draggable cae dentro del droppable
},

activate: function(ev, ui) { //ocurre cuando el draggable se activa (comienza a ser arrastrado)
},

deactivate: function(ev, ui) { //ocurre cuando el draggable deja de ser arrastrado
},

como todo evento de droppable, posee 1 referencia implicita y dos parámetros; la referencia implicita es al objeto “this”; que se refiere al objeto droppable;

$(this).append(”");

o sin necesidad de jquery: var iddrop = this.id;

y ev, que se refiere al gestor de eventos (al DOM Event de la página actual).

con EV podemos obtener ejemplo, las coordenadas de donde ha estado el draggable:

ev.ClientX / evClientY

ahora, quien es ui?, con ese nombre tan críptico, uno no sabe lo que es.

Pues bueno, siguiendo la regla de John Resig (primeras opciones, parámetros, segundas, propiedades, ultimas, callbacks); ese ui debe ser un objeto o una propiedad de droppable; en este caso, UI retorna una referencia al objeto arrastrado (es decir al draggable).

ej.

var id = ui.draggable.element.id;

o

$(ui.draggable.element).

Con lo cual podemos extraer toda la información que necesitemos del elemento que fue arrastrado.

El bloque de código que usé para pruebas fue el siguiente:


$(document).ready(function(){
$(”#dragged”).draggable({
helper: ‘clone’
});
$(”#dropped”).droppable({
accept: “.draggable”,
activeClass: ‘droppable-active’,
hoverClass: ‘droppable-hover’,
drop: function(ev, ui) {
//alert(ev.clientX);
$(this).append(”<br>Dropped!”);
},
deactivate: function(ev, ui) {
alert(ui.draggable.element.id);
$(this).append($(document.createElement(’div’)).text(’deactivate’));
},
tolerance: ‘fit’
});
});

Experimentos con XPATH y PHP5 DOM

Wednesday, November 21st, 2007

Hola a todos; estoy en medio de un experimento (como los llama walter, medio criptico) de construcción de un XPATH parser para el DOM de tomates (basado en DOM de php5); en este caso, para resumir mucho más las largas estructuras DOM:XPATH (como lo hace jquery).

Por lo general yo nunca posteo preguntas (mas bien respuestas) en mi blog; pero estoy algo atrasado con esta idea y queria ver si alguien al leer este artículo se anima a participar.

Para los que aun no conocen XPATH, este es un lenguaje de localización y recepción de nodos dentro de un arbol DOM XML (o sea un archivo XML cualquiera); estas recepciones se crean mediante expresiones, tanto sencillas como complejas, para ubicar nodos dentro de un documento.
el ejemplo más sencillo es un documento XHTML, de la forma:

<html>
  <head>
    <title>Titulo de la pagina web</title>
  </head>
  <body><div id=“capa1″ style=“font-family: verdana; color: #000cab; “>Prueba de DIV<span class=“estilo1″ style=“font-family: arial; “>span anidado dentro de un div de id capa1</span><div>
</html>

Llegarle a BODY significa un path (eje o axis) es: /html/body … es util porque en muchos casos getElementById o getElementsByTagName no funcionan ya que requieren un DTD (Doctype Document Definition) y a veces el XML es propio (y no un XHTML).
sin embargo, llegarle al SPAN que está dentro del DIV es más dificil; para ello deberiamos llegarle al DIV y luego de todos sus hijos, seleccionar el SPAN que cumpla las reglas; algo como:

body -> div:id=capa1 -> span:class=estilo1

eso, en XPATH se escribe de la siguiente manera:

id(”capa1″)/child::span[@class=”estilo1″]

/child representa todos los hijos de id(); (::) representa el scope (alcance) actual (en este caso, todos los childs), span representa evidentemente el nombre de la etiqueta SPAN y dentro de los corchetes se coloca [] lo que se conoce como predicado, o expresión filtro; en este caso @ representa los atributos que la etiqueta span pudiera tener; @class se refiere al atributo class que es igual a estilo1.
Bueno, al caso; voy a mostrar algunos ejemplos de para que puede servir XPATH en experimentos realmente particulares con XHTML; fijense:

Ejemplos:
id(”capa1″)/parent::node()
//trae el padre del id capa1

id(”capa1″)/child::span[@class=”estilo1″]
//trae de id:capa1 todos los span que tengan como className:estilo1

/html/body/ul[1]/li[position()=last()]
//del primer UL, trae el li que tiene la ultima posicion

Tambien se puede escribir como //ul[1]/li[last()]

id(”tb1″)/child::tbody/child::tr[position() mod 2 = 1]
//del objeto id:tb1, revisa todos los childs tbody::tr que su posicion sea impar.

//ul/li[position()> 2 and position()< 8]
//trae todos los li, que su posicion ordinal sea mayor que dos y menor que 8

id(”lista_estados”)/li[starts-with(., “M”)]
//para la lista de id:lista_estados, traer todos los li que empiezan con M

//*[.=”item 1″]
//para todos los elementos que tienen como texto la palabra “item 1″

id(”tb1″)/child::tbody/child::tr/child::td[@id[starts-with(., “fecha_nacimiento”)]]
//de la tabla id:tb1; traer todas las celdas que su id comience con fecha_nacimiento.

id(”tb1″)/child::tbody/child::tr/child::td[@id[starts-with(., “fecha_nacimiento”)] and substring(., 1, 4)=”1970″]
//El mismo de arriba, pero ademas, que el valor de esa celda, pasado por la funcion substring, sea igual a 1970

Lo que ven empezando es una expresion XPATH, lo segundo (luego del //) es la explicacion de lo que hace la expresion XPATH; alguna vez se han preguntado, sobre todo trabajando con DOM; como hago para contar (sin tener que pegarme a la DB) desde una tabla cuantas personas femeninas nacieron posterior a 1970 y su nombre empieza con A?.
XPATH, en muchos casos es la respuesta.

Bueno, en el caso actual, deseo simplificar este proceso; haciendolo tal cual como lo hace jquery, pero en PHP; algo como:

$(’ul li:first’)
es igual a:
/html/body/ul/li[position()=1]

ven a lo que me refiero?, ambas dicen: traeme todos los LI que su posicion sea 1, en todos los UL del documento HTML actual.

para hacer esto en PHP requiero dos cosas:

separar la expresion de arriba (el ‘ul li:first’) en “tokens” (ej: ul, li:first) y esos tokens analizarlos segun expresiones regulares (es lo más optimo que veo ahi) y hacer las transformaciones segun el siguiente mapa:

Algunas reglas robadas de jquery:

Reglas:                se traduce a:

#identificadores:
#name <- es id                 id(’name’)
.class <- posee clase x     [@class=”class”]
div <- es un elemento        /div

#indicadores de posicion:
:first                                [position()=1]
:last                                [position()=last()]
:n (number)                      [position()=n]
:odd <- impares                [position() mod 2 = 1]
:even                               [position() mod 2 = 0]
:>2                                  [position() > 2]

#descendencia y ascendencia:
:child                child::*
:child::span            child::span
:parent                parent::node()
:self                self::node()

Lo que ven de primero, es como se “escribiria” y lo de la derecha, como es la expresion “traducida” en XPATH; entienden a lo que me refiero?, un parser de expresiones a XPATH; el problema por el que atravieso ahora es el poco tiempo disponible para obtener las expresiones regulares que separen en “tokens” y las que interpretan esos tokens; quien se anima a ayudar?.

Si se logra esto (crear el parser XPATH), esta expresion:
id(”tb1″)/child::tbody/child::tr/child::td[@id[starts-with(., “fecha_nacimiento”)] and substring(., 1, 4)=”1970″]
quedaria parecida como en jquery:
(”#tb1 tbody tr td:id=(starts-with(., ‘fecha_nacimiento’) and substring(., 1, 4)=1970)”)

Y para que podría ser util XPATH en PHP?, bueno, fijense este codigo:

$filas = $dom->query(’id(”tb1″)/child::tbody/child::tr[position() mod 2 = 1]’);
foreach($filas as $fila) {
$fila->className(’odd’);
}

Dice, “toma todas las filas impares del tbody de la tabla llamada tb1″; de esas filas (que es un DOMNodelist) itero sobre ellas y les aplico un estilo “odd” lo que hace que nuestra tabla sea una “zebra”; claro, esto ya lo hace jquery; pero es un ejemplo interesante de iteración sobre tablas estáticas ya existentes.

Alguno se ha preguntado como hacer un Total de la columna sub-total de una tabla? …
$subtotal = 0;
$celdas = $dom->query(’id(”tb1″)/child::tbody/child::tr/child::td[@class=”subtotal”]’);
foreach($celdas as $celda) {
$subtotal+= $celda->nodeValue;
}

en la variable $subtotal tendremos el total general de todas las columnas que tengan como class “subtotal” (existen otras formas de identificarlas, pero es para plantear la idea).

y esperen a que llegue XPATH 2.0; podremos hacer cosas como:

sum(for $x in id(’tb1′)/child::tbody/child::tr/child::td return $x/@cantidad * $x/@precio)

La expresion id(’tb1′)/child::tbody/child::tr/child::td return $x/@cantidad * $x/@precio) retorna el subtotal de multiplicar las TD:class=cantidad * TD:class=precio; si ese subtotal, lo iteramos entre TODAS las filas (eso hace el for) y sumamos eso (eso hace el sum) obtendremos el total general.

Mientras, seguiré haciendo busquedas con XPATH normalito y básico; pero es un proyecto interesante que tengo por ahi …

El que quiera colaborar, un reply a este post…

I encuentro de Emprendedores del Software Libre

Saturday, November 17th, 2007

El miércoles y jueves he tenido el grato placer de participar en el I encuentro Nacional de Emprendedores del Software Libre; realizado por el CNTI y RINDE; en colaboración con FUNDACITE Lara, la UNEXPO y que tuvo como sede la Torre David de la ciudad de Barquisimeto.

Contamos con la presencia de Octavio Rossell y Eduardo D’Atellis que en conjunto presentaron una ponencia sobre Glove; Hector Colina presentandonos una amena presentación sobre servidores web en debian y Hector Rivero de CNTI una sobre RINDE (como una costumbre mia; le volví a recordar; ¿Cuando volverán a levantar FINDE? ;) ).

En mi caso, asistí para dar una ponencia sobre Bases de datos Libres (hablé y dí ejercicios sobre postgresql y mysql; pero hablamos de firebird, berkeley db, ingres y otras); la cual estrené en ese evento y tuvo una buena aceptación; espero mejorar el material y los ejemplos con el tiempo.

Me parece un interesante modelo que aplicaré de ahora en adelante en todas mis ponencias:

Historia (como buena doña, no faltan anecdotas) -> teoría básica -> explicación extendida -> ejemplos básicos -> cierre y conclusiones -> ejemplos complejos (si queda tiempo y personas despiertas ;) ).

proximanente me crearé un repositorio para todas mis ponencias; espero tenerlo pronto.

Gracias a CNTI, a Ezequiel (chekex), la gente de FUNDACITE Lara y todos los demás que hicieron posible este gran evento, como siempre la gente de Lara muy organizada y dispuesta!; felicidades a todos ….

PD: y Galeno, por favor!, pareces naufrago!; donde depositamos la colecta para que vayas al barbero??… ;)