Archive for May, 2009

Hagalo usted mismo: Efecto marquesina con Javascript

May 30th, 2009

Recientemente m313n45 me pidio ayuda para hacer un efecto de marquesina con unas imágenes y al dar click sobre alguna de ellas se viera la versión completa, todo esto sin usar flash.

Lo realice obviamente con Javascript + JQuery y a continuacion veremos paso a paso como lograrlo.

Tambien pueden ver el ejemplo completo aquí

Las imágenes para las marquesina son 6, iniciamos con el markup de las imágenes.

1
2
3
4
5
6
7
8
9
10
<div id="container">
	<img src="01.png" alt="1"/>
	<img src="02.png" alt="2"/>
	<img src="03.png" alt="3"/>
	<img src="04.png" alt="4"/>
	<img src="05.png" alt="5"/>
	<img src="06.png" alt="6"/>
</div>
<div id="viewport">
</div>

Además ocupamos darle estilo:

1
2
3
4
5
6
7
8
9
10
11
12
13
#container
{
	overflow: hidden;
	width: 400px;
	height: 64px;
	border-style: solid;
}
#container img
{
	position: relative;
	width: 60px;
	height: 64px;	
}

overflow: hidden; hace que las imágenes que no quepan en el contenedor esten ocultas en ves de causar scrolling o un efecto similar, además hacemos las imágenes mas pequeñas y asignamos su posicion como relativa, lo cual sera útil a realizar la animación.

Hasta el momento esto se ve así:

123456

Notece que una de las imágenes se encuentra oculta de momento, debido a que no se alcanza a mostrar en el contenedor.

Después iniciamos con la animacion, requerimos a JQuery para facilitarnos las cosas, tendrán que agregar la referencia a la libreria en su header además de agregar el código de animación:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var deltaX = 5;
var deltaT = 42;	
 
$(document).ready (function ()
{
	setTimeout("animate()", deltaT); //start animation
});
 
function animate ()
{
	var left = parseInt ($("#container img").css("left"));
	left -= deltaX;
 
	$("#container img").css("left", left + "px");
 
	setTimeout ("animate()", deltaT); //continue animation
}

Donde deltaT define cada cuantos milisegundos ocurrira la animacion y deltaX indica el desplazamiento cada intervalo de deltaT milisegundos. La animación la realizamos modificando la propiedad left del css. Ahora esto se ve así:

123456

Pero para el momento en que ustedes lleguen a leerlo todas las imágenes habrán desaparecido hacia la izquierda, así que recarguen la pagina por favor y bajen rápidamente hasta este punto para ver la animación.

Eso ocurre por que ocupamos hacer que la marquesina sea giratoria, para lograr el efecto debemos de quitar la primer imagen cuando esta ya no sea visible y ponerla después de la ultima imagen. La primer imagen no es visible cuando su atributo css left tenga un valor de -LongitudImagen, en este caso, -60px.

Como quitaremos la imagen, ocupamos volver a ajustar el desplazamiento a la izquierda aumentando el atributo css left con la longitud de la imagen que quitamos, es decir 60px. El script queda entonces:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
var deltaX = 5;
var deltaT = 42;	
var imageWidth = 60;
 
$(document).ready (function ()
{
	setTimeout("animate()", deltaT); //start animation
});
 
function animate ()
{
	var left = parseInt ($("#container img").css("left"));
	left -= deltaX;
 
	if (left <= -imageWidth) //if first image is no longer visible
	{
		left += imageWidth;
		$("#container img:first")
                	.remove ()
                	.insertAfter("#container img:last");
	}
 
	$("#container img").css("left", left + "px");
 
	setTimeout ("animate()", deltaT); //continue animation
}

Y ya podemos ver la animación circular:

123456

Por ultimo requerimos que al dar click en una imagen la mostremos en su tamaño original, para dar el efecto de vinculo debemos de cambiar el css de las imágenes para que aparezca la “manita” cuando pongamos el puntero sobre la imagen, el css queda entonces:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#container
{
	overflow: hidden;
	width: 400px;
	height: 64px;
	border-style: solid;
}
#container img
{
	position: relative;
	width: 60px;
	height: 64px;	
	cursor: pointer;
}

Solo nos falta el script, pero debemos de tener cuidado, por que cuando quitamos la imagen para ponerla al final de la lista perdemos la asociación del evento y tenemos que volverla agregar,por lo que el script final queda:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
var deltaX = 5;
var deltaT = 42;	
var imageWidth = 60;
 
$(document).ready (function ()
{
	$("#container img").click (changeViewportImage);
	setTimeout("animate()", deltaT); //start animation
});
 
function changeViewportImage ()
{
	$("#viewport img").remove ();
	$("#viewport").append ($(this).clone ());
}
 
function animate ()
{
	var left = parseInt ($("#container img").css("left"));
	left -= deltaX;
 
	if (left <= -imageWidth) //if first image is no longer visible
	{
		left += imageWidth;
		$("#container img:first")
		    .remove ()
		    .insertAfter("#container img:last")
		    .click (changeViewportImage);
	}
 
	$("#container img").css("left", left + "px");
 
	setTimeout ("animate()", deltaT); //continue animation
}

Y queda finalmente así (recuerden dar click sobre alguna imagen):

123456

Tambien pueden ver el ejemplo completo aquí

Evaluando expresiones aritméticas con C# (Shunting-yard)

May 26th, 2009

Fire_Tony tenia que escribir un programa que parseara una expresión aritmética infija (3*1/(2-6)), la convirtiera en un arbol binario, para después mostrar la expresión en notación polaca inversa (sufija) y evaluara el resultado.

El pobre no pudo terminar el problema a tiempo, y como me llamo la atención y no tenia mucho que hacer me ofrecí a resolver el problema para que revisara el código y no se viera en ese dilema la próxima ocacion.

El programa por sencillez solo evalúa numeros de 0 al 9 y reconoce los operadores *,+,- y / pero puede ser expandido fácilmente para mas casos.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
class SixPackJoy
{
    public static void Main(string[] args)
    {
        Console.WriteLine ("Expression: ");
        var expression = Console.ReadLine().Replace(" ", "");
        var output = new Stack<BinaryNode> ();
        var stack = new Stack<Operator> ();
        var index = -1;
 
        foreach (var token in expression)
        {
            index++;
            if ("0123456789".Contains(token)) //numeric token
            {
                output.Push(new BinaryNode (token));
            }
            else if ("*/+-".Contains(token)) //operator token
            {
                var op = new Operator (token);
 
                var lastOperator = stack.Count > 0 ? stack.Peek() : null;
                if (lastOperator != null && 
                    !lastOperator.IsParenthesis && 
                    op.ComparePrecedence(stack.Peek()) <= 0)
                {
                    var node = new BinaryNode(stack.Pop().Value);
                    if (output.Count < 2)
                    {
                        Console.WriteLine("Insuficcient operator argumets, process halted");
                        return;
                    }
                    node.RightChild = output.Pop();
                    node.LeftChild = output.Pop();
                    output.Push(node);
                }
                stack.Push(op);
            }
            else if (token == '(')
            {
                stack.Push(new Operator(token));
            }
            else if (token == ')')
            {
                while (true)
                {
                    if (stack.Count == 0)
                    {
                        Console.WriteLine("Parenthesis missmatch at {0}, process halted", index);
                        return;
                    }
                    var op = stack.Pop();
                    if (op.IsParenthesis)
                        break;
 
                    if (output.Count < 2)
                    {
                        Console.WriteLine ("Insuficcient operator argumets, process halted");
                        return;
                    }
                    var node = new BinaryNode (op.Value);
                    node.RightChild = output.Pop ();
                    node.LeftChild = output.Pop ();
                    output.Push (node);
                }
            }
            else
            {
                Console.WriteLine("Invalid token '{0}' at {1}, process halted", token, index);
                return;
            }
        }
 
        while (stack.Count != 0)
        {
            var op = stack.Pop();
            if (op.IsParenthesis)
            {
                Console.WriteLine ("Parenthesis missmatch, process halted");
                return;
            }
            if (output.Count < 2)
            {
                Console.WriteLine("Insuficcient operator argumets, process halted");
                return;
            }
            var node = new BinaryNode(op.Value);
            node.RightChild = output.Pop();
            node.LeftChild = output.Pop();
            output.Push(node);
        }
 
 
        if (output.Count != 1)
        {
            Console.WriteLine("Invalid expression, process halted");
            return;
        }
 
        var ast = output.Pop();
        Console.WriteLine("{0} = {1}", ast.GetSufixNotation (), ast.Evaluate());
 
    }
}
 
class BinaryNode
{
    public BinaryNode LeftChild;
    public BinaryNode RightChild;
 
    public BinaryNode(char value)
    {
        Value = value;
    }
 
    public char Value;
 
    public double Evaluate()
    {
        if (LeftChild == null)
            return double.Parse(Value.ToString ());
 
        var operations = new Dictionary<char, Func<double, double, double>> ()
          {
             {'*', (x, y) => x * y},
             {'/', (x, y) => x / y},
             {'+', (x, y) => x + y},
             {'-', (x, y) => x - y},
          };
 
        return operations[Value](LeftChild.Evaluate(), RightChild.Evaluate());
    }
 
    public string GetSufixNotation()
    {
        if (LeftChild == null)
            return Value.ToString ();
 
        return string.Format("{0} {1} {2}",
            LeftChild.GetSufixNotation(),
            RightChild.GetSufixNotation(),
            Value);
    }
}
 
 
class Operator
{
 
    public char Value;
 
    public Operator(char value)
    {
        Value = value;
    }
 
    public bool IsParenthesis
    {
        get
        {
            return Value == '(';
        }
    }
 
    public int ComparePrecedence(Operator o)
    {
        if ("+-".Contains(Value))
        {
            if ("+-".Contains(o.Value))
                return 0;
            else
                return -1;
        }
        else if ("+-".Contains(o.Value))
            return 1;
        else
            return 0;
    }
}

#twitterfail #fixreplies

May 13th, 2009

Recientemente las gentes de Twitter hicieron un pequeño cambio al que ellos llaman “Small Settings Update”, y del cual se puede saber un poco mas en su blog

Ese cambio a molestado a muchas personas (incluyéndome), dejando a varios inconformes mandando retwitts una y otra ves para tratar llamar la atención (hacer bola pues) a los admins de Twitter.

¿Pero de que se trata ese cambio?
Imaginemonos que tenemos a Alice, Bob y Carol, Alice es amiga de Bob, y Bob es amiga de Carol, por lo tanto Alice “sigue” (follow) a Bob y a su vez Bob sigue a Carol.

Si Carol escribe un reply a Bob, Alice no lo ve, lo cual es natural ya que Alice no esta siguiendo a Carol, pero cuando Bob responde a Carol es donde encontramos el dilema.

Anteriormente si Alice seguia a Bob, el reply de Bob hacia Carol era leído por Alice también, lo que parece poco natural pero tenia un efecto útil al que muchas personas se acostumbraron, permitía conocer nuevas personas, si un reply te llamaba la atención podías buscar la fuente de la informacion, y de esa manera Alice podía conocer a Carol.

Con el nuevo setting, Alice no vera la respuesta de Bob a Carol por no seguir a Carol, por lo que Alice jamas podrá conocer a Carol, la que pudo muy bien haber sido su mejor amiga de toda la vida.

Espero que estés contento Twitter, acabas de destruir la vida de Alice y Carol.

¿Por que twitter no dejo eso como una setting ya sea opt-in o bien opt-out?

Pandemia – II

May 12th, 2009

Ayer fui a el cine, hace poco fueron reabiertos después de que la psicosis haya terminado en el transcurso de la semana pasada y el espectáculo que presencie fue por lo menos curioso.

Al llegar a la plaza Forum (Centro comercial de la localidad) por una de las entradas había una pequeña hoja pegada en la puerta de cristal informando que había gel antivacterial para disposición de todos, y efectivamente, en unas de las mesitas unos pasos después se encontraba un frasco de gel esperando a ser usado.

Al entrar al cine la cosa se fue volviendo mas bizarra, todos los empleados tenían cubre boca (pero no todos lo portaban correctamente), incluso la tipa que vende los boletos detrás de una placa de cristal (WTF?!). Aparte de eso se encontraban pequeñas botellas amarillas con una cara sonriente (mas gel por supuesto) en distintos lugares, la taquilla, cafetería y dulcería, ninguna se salvaba. Además, se podían ver unas placas que mencionaban que por disposición oficial, era OBLIGATORIO desinfectarse las manos antes de entrar a la sala, junto con la ya clásica información sanitaria, lo curioso es que a nadie le importaba y no había nadie asegurándose que la “DISPOSICIÓN” fuera honrada, tan secillo que hubiera sido “forzar” el uso del gel al momento de entregar el boleto.

En fin, veremos como sigue la cosa.

Chiste – I

May 12th, 2009

No acostumbro a hacer esto, pero me vale madre, chiste robado de Sonny_Taz en Twitter

Se juntan un sádico, un masoquista, un asesino, un necrófilo, un zoófilo y un piromaníaco en el jardín de un hospital neuropsiquiátrico


Y el zoófilo dice:- Y si nos cogemos un gato?


Entonces el sádico dice:- Eso, vamos a cogernos a un gato y después lo torturamos


Dice el asesino:- Vamos a cogernos un gato, torturarlo y después matarlo!!


Dice el necrófilo:- Vamos a cogernos un gato torturarlo, matarlo y después lo cogemos otra vez!!!


Dice el piromaníaco: amos a coger un gato, torturarlo, matarlo, volver a cogerlo y prenderle fuego !!!!


Se hace un repentino silencio, todos miran al masoquista y le preguntan:- Y tu no dices nada ???


Y el masoquista dice:- Miauuu !!!!

Pendejo de Metachat

May 8th, 2009

Hace tiempo que no entraba a Metachat (una red de IRC de Culiacá), hoy entre y recordé por que en ocasiones resultaba tan patético andar por esos rumbos:

<MANUEL->    k onda wey te cambio msn de morras
===    MANUEL- <adolfo@DAA1911D.BB30026F.5D8CB3A7.IP> “MANUEL-”
===    MANUEL-: member of #Sinaloa
===    MANUEL-: attached to Tecate.MetaChat.Net “TeCaTe SabOr Con Caracter.!! =)”
—    End of WHOIS information for MANUEL-.
<AlbertEin>    simon
<MANUEL->    ok
<AlbertEin>    arre
<MANUEL->    kien empieza
<AlbertEin>    tu
<MANUEL->    pero k esten conectadas y de unos 19 a 25
<MANUEL->    wey
<MANUEL->    k si tiens
<AlbertEin>    simon
<MANUEL->    ok
<MANUEL->    de k edad des tieens?
<AlbertEin>    son morras w, no les puedo preguntar la edad o se indignan, pero estan en edad de merecer
<MANUEL->    ok
<MANUEL->    y estan conectadas
<AlbertEin>    si ome
<MANUEL->    ok
<MANUEL->   [CORREO SENSURADO DE UNA TAL ANYTA CON MUCHO AMOR]
<AlbertEin>    shemale69@hotmail.com
<MANUEL->    ok
<MANUEL->    esta conectada
<AlbertEin>    simon
<MANUEL->    ok
<MANUEL->   [CORREO SENSURADO DE UNA TAL CECY]
<AlbertEin>    sofy_love23@hotmail.com
<MANUEL->    e wey no seas mamon la primera no esta conectada
<AlbertEin>    a lo mejor no te quiere aceptar w
<AlbertEin>    si tu correo es manuel_elviolador@hotmail.com no creo que te acepten
<MANUEL->    jajaj
<MANUEL->    ewey la neta eres bien mamon+
<MANUEL->    ninguna esta conectada
<MANUEL->    wey
<MANUEL->    te pasas
<MANUEL->    wey}
<AlbertEin>    jajajaja
<AlbertEin>    quien te dice que te van a aceptar asi nomas por guapo?
<MANUEL->    no wey esk no es eso sino k no estan CONECTADAS
<AlbertEin>    las tuyas tampoco me aceptan, a lo mejor nomas agregan a jotitos
<MANUEL->    VALES VERGA
<AlbertEin>    uuuyy que delicada
<MANUEL->    PUES ESK LA NETA LA COSA NO ERA ASI WEY
<AlbertEin>    ?
<MANUEL->    Y K NO TIENES PALABRA DE HOMBRE O K VERGA
<MANUEL->    PUES
<AlbertEin>    pues que?
<MANUEL->    LO K KIERAS
<MANUEL->    VERGA
<MANUEL->    DIME DE DONDE ERES
<MANUEL->    A CHINGAR TU MADRE
<MANUEL->    PUES}
<AlbertEin>    preguntale a tu mama w
<MANUEL->    A LA TUYA
<MANUEL->    VERGA
<MANUEL->    K YA TE RAJASTE
<MANUEL->    PUÑAKL
<AlbertEin>    si conoces a mi ama entonces por que me preguntas de donde soy?

<AlbertEin>    ?
<MANUEL->    K POCO
<AlbertEin>    poco que?
<MANUEL->    nada wey
<MANUEL->    vales verga asi nomas
<AlbertEin>    yo no soy el morro pendejo patetico que tiene que hablarle a desconocidos para que le de el msn de morras con la tonta esperanza de que lo pelen, quieres msn de morras? sal de tu casa pendejo y conocelas

<MANUEL->    ajajajajaja
<MANUEL->    k palabritas de nena wey
<MANUEL->    olle cuantos años tienes
<MANUEL->    ?
<AlbertEin>    jaja, no puedes conseguir morras y quieres conquistarme a mi ?
<MANUEL->    no bato lodo podrido we
<MANUEL->    y menos puñales
<MANUEL->    como tu
<AlbertEin>    jajajajajaja
<AlbertEin>    que machote, que barbaro
<AlbertEin>    siendo asi no se como no se te hechan encima las viejas, no mames, como se pueden resistir?
<MANUEL->    kierees un machetobn
<MANUEL->    o0
<AlbertEin>    pffff
<MANUEL->    ya wey bno estes chingando
<AlbertEin>    jajaja, si tuvieras una pisca de cerebro me dieras ignore y a, o simplemente no peles la ventana, yo solamente te estoy contestando
<AlbertEin>    tu eres el que dice palabras de “machos” esperando que salga corriendo llorando