Una de esas preguntas recurrentes en los foros es cuanto cobrar por una web. Casualmente me llegó a las manos un presupuesto que le había hecho una compañía a mi cliente más reciente. Les dejo los datos que tiene el presupuesto para que se puedan enterar más sobre cuanto cobrar. Quiero dejar en claro que estos para nada son mis precios, los cuales en realidad yo calculo individualmente por proyecto. Tampoco pregunten si yo cobro más o menos por que eso está fuera del panorama. Lo único que si les puedo decir es que en un país como Mx, de donde viene el presupuesto, los precios me parecen razonables, aun que el servicio se me hace un poco precario. No revelo la identidad de la compañía que tiene estos paquetes por dos razones, 1) no hacerles promoción, 2) no creo que fuera correcto hacerlo.

Web Profesional.

Indicada para pequeñas empresas que simplemente desean tener su tarjeta de visita en internet.
Consiste en realizar de forma atractiva una presentación eficaz de su empresa, de modo que la
pagina sirva de toma de contacto para sus clientes y proveedores por internet. En ella se es la
opción mas usada por despachos de consultoria, que desean tener una presencia en internet junto
con sus direcciones de correo personalizada para reforzar su imagen ante sus clientes. Se puede
contratar desde $4,950 m.n. y su precio variara según la complejidad final de dicha pagina y de las
ampliaciones que tenga su estructura
incial.

Incluye registro de dominio y
hospedaje durante el primer año.

Desarrollo web html.

•   Pagina de información sobre
la empresa (historia, casos

de éxito, etc.)
•   Fotografías de productos.
• Conceptualizar atraves de

imágenes sus servicios.
•   Pagina para envio de correo
electrónico sin necesidad de

programas.
•   1 a 5 cuentas de correo
electrónico de alta

capacidad.
•   Pagina principal con
producto destacado, noticias

de la empresa y una breve
introducción a ella.

$4,950 + IVA

Mantenimiento de la pagina $100.00 c/mes a partir del segundo  año el

costo anual es de $1,200.00. nota: 40% para iniciar el trabajo, 30% al aceptar
la plantilla y 30% al terminar el trabajo.

Web PyMe.

Orientada a aquellas empresas que desean tener una presencia notoria y de calidad en internet.
Se trata de dar a sus clientes de forma practica y eficiente información sobre sus novedades,
productos, promociones, y referencias de modo que la pagina sirve de una toma de podríamos
decir que existen tres tipos principales de proyectos web; los basados en paginas HTML con
contenido estético ( impacto visual básico), los basados en paginas HTML donde:

Incluye registro de dominio y

hospedaje durante el primer año
desarrollo web HTML‐flash
Catalogo de productos.

Paginas para productos o

servicios.
Baner para promoción de

productos o servicios.
Pagina de información

sobre la empresa (historia,
casos de éxito, etc).
Fotografías de productos

Conceptualizar atraves de

imágenes sus servicios.
1 a 10 cuentas de correo de

alta capacidad.
Pagina principal con

producto destacado,
noticias de la empresa y
una breve introducción a

ella.
Sitio animado para

incrementar permanencia
de visitas.

$7,950.00 + IVA

Mantenimiento de la pagina $150.00 c/mes a partir del segundo  año
el costo anual es de $1,200.00. nota: 40% para iniciar el trabajo, 30%
al aceptar la plantilla y 30% al terminar el trabajo.

Web Corporativa.

Ideal para aquellas empresas con una gama amplia de productos y servicios. Empresas
orientadas 100% al cliente, que deseen aumentar sus ventas y la publicidad de sus productos. En
este tipo de paginas web se muestra principalmente el listado de productos o servicios que se
quieren ofrecer, ordenados por precios y marcas con búsqueda por palabras.
1. Mostrar o vender productos de su empresa con detalle en fotografía y características.
2. Actualizar los productos o servicios desde una parte privada de la web de una forma fácil y
sencilla desde cualquier lugar, negocios o casa (siempre que haya una conexión a
internet).
3. Se podrán realizar compras a través de la web, realizar presupuestos y consultar las
características de los productos existentes de forma rápida y sencilla.

Incluye registro de dominio durante
3 años y hospedaje durante el primer año.

Desarrollo web HTML‐Flash  y FLASH.

•   Catalogo de productos.

• Paginas para productos o
servicios.
• Baner de información sobre la
empresa (historia, casos de éxito,
etc).
• Fotografía de productos y/o
tienda.
• Conceptualizar a través de
imágenes sus servicios.
• Pagina para envio de correo
directo sin necesidad de
programas.
• Configuración de tienda virtual
para procesar pedidos (no pagos
electrónicos).
• Alta de productos o servicios de
la empresa en la tienda.
• 1 a 20 cuentas de correo
$9,950.00 + IVA
electrónico de alta capacidad.
• Pagina principal con producto
Mantenimiento de la pagina
destacado, noticias de la
$200.00 c/mes a partir del segundo
empresa y una breve
año el costo anual es de $1,700.00.
introducción a ella.
nota: 40% para iniciar el trabajo,
• Sitio animado para incrementar
30% al aceptar la plantilla y 30% al
permanencia de visitas.
terminar el trabajo.

Notas sobre z-index

January 8, 2010

Estoy escribiendo una galería y he descubierto algo interesante. El cliente requiere que la galería sea una especie de light box por lo que tengo que trabajar con elementos transparentes. Si alguna vez has trabajado con elementos transparentes sabrás que un div con transparencia del 70% forzará a todos los elementos que contiene a tener dicha transparencia aun cuando tu especifiques que esos elementos deben ser completamente opacos. Esto trae un problema: no se pueden poner más elementos dentro del elementos transparente, por lo que este sirve solo como una pantalla. Para poder posicionar elementos sobre él y que estos no sean transparentes es necesario que se coloquen en otro contenedor y que este contenedor se posicione sobre el elemento transparente. Esto realmente no representa un problema, pero me llevó a descubrir una curiosidad sobre z-index de la que no había oído antes.

Intentando diversas opciones, llegué a considerar poner el elemento transparente con posición fixed para evitar que se mueva cuando se hace scroll y así asegurar que la pantalla esta cubierta en todo tiempo. Después quise poner el elemento que quería mostrar sobre la pantalla con su posición por defecto para poder aprovechar algunas ventajas de esta posición. Pensé que con usar un z-index de 1000 sería suficiente pero no fue así. Resulta que un elemento cuya posición no ha sido modificada (usando position en CSS)  no puede posicionarse sobre un elemento cuya posición es fixed o absolute sin importar el z-index que se le asigne al elemento cuya posición no ha sido modificada. Esto puede resultar poco interesante para muchos, sin embargo, a mi me ha tomado por sorpresa por que son de las cosas que no te enseñan en los libros y que solo aprendes con la experiencia. Lo bueno de esto es que te ayuda a conocer más la forma de funcionar del lenguaje y esto te ayuda en desarrollos futuros. Saber como funciona el lenguaje y la web en general es muy importante como lo comprueba este post:

http://www.forosdelweb.com/f13/como-obtener-dinamicamente-siguiente-nivel-con-js-765613/

Estos días he tenido muy poco tiempo libre, o mejor dicho nada de tiempo libre, pero me las he arreglado para desarrollar este objeto. Espero que les guste. Primero por que no ves un ejemplo en funcionamiento (No soporte para IE)

Como todos los objetos que hago, este tampoco soporta IE, pero soporte se implementará en siguientes versiones. El objeto depende en domCore, otro objeto que no les había presentado por que está  muy precario por ahora.

El uso de este objeto es muy simple, pero primero veamos que es lo que hay dentro:

//draggMe 0.1
//By Buzu
//Depends on domCore by Buzu.

var dragMe = {
	version : '0.1',
	working : false,
	catchers : new Array(),
	overCatcher : false,
	lastOver : null,
	startDrag : function(e,cual,dejarClon){
		e.preventDefault();
		var dC = dejarClon || false;
		var elem = cual.cloneNode(true);
		elem.difX = e.clientX - cual.offsetLeft;
		elem.difY = e.clientY - cual.offsetTop;
		elem.style.zIndex = 900;
		domCore.esIE()? elem.style.filter = 'alpha(opacity = 70)' : elem.style.opacity = 0.7 ;
		dragMe.crearProxyCatcher();
		//uso window.onmousemove y onmouseup para poder eliminar luego
		//el evento. De otra manera habria que usar removeEventListener
		//y su equivalente en IE.
		window.onmousemove = function(e){
			dragMe.working = true;
			domCore.getByName('body')[0].appendChild(elem);
			elem.style.position = 'absolute';
			elem.style.top = (e.clientY - elem.difY) + 'px';
			elem.style.left = (e.clientX - elem.difX) + 'px';
			dragMe.onDragging(parseInt(elem.style.top), parseInt(elem.style.left));
		}
		window.onmouseup =  function(){
			if(!dC){domCore.getByName('body')[0].removeChild(elem)}
			window.onmousemove = '';
			//llamar solo si se ha hecho drag para evitar que se llame cada
			//que se hace click en el elemento sin arrastrarlo
			if(dragMe.working){
				dragMe.onDrop(dragMe.overCatcher, parseInt(elem.style.top), parseInt(elem.style.left));
			}
			//evitar que se repita la llamada a la funcion si se hace click
			//nuevamente.
			window.onmouseup = '';
			if(dragMe.overCatcher){
				//pasamos referencia al elemento original para saber cual
				//fue soltado y poder hacer algo con el...
				dragMe.lastOver.originalElem.func(dragMe.lastOver.originalElem);
				dragMe.overCatcher = false;
			}
			dragMe.removeProxyCatcher();
			dragMe.working = false;
		}
	},
	registerCatcher : function(catcher, func){
		catcher.func = func || function(){};
		dragMe.catchers[dragMe.catchers.length] = catcher;
	},
	crearProxyCatcher : function(){
		for(i=0; dragMe.catchers[i]; i++){
			var catcher = dragMe.catchers[i];
			var proxy = catcher.cloneNode(true);
			//guardamos referencia a proxy para poder eliminarla luego.
			catcher.proxy = proxy;
			proxy.originalElem = catcher;
			proxy.style.position = 'absolute';
			proxy.style.opacity = 0;
			proxy.style.filter = 'alpha(opacity=0)';
			proxy.style.top = catcher.offsetTop + 'px';
			proxy.style.left = catcher.offsetLeft + 'px';
			proxy.style.backgroundColor = '#F00';
			proxy.style.zIndex = 1000;
			domCore.getByName('body')[0].appendChild(proxy);
			proxy.onmouseover = function(){
				dragMe.overCatcher = true;
				dragMe.lastOver = this;
			}
			proxy.onmouseout = function(){
				dragMe.overCatcher = false;
			}
		}
	},
	removeProxyCatcher : function(){
		var b = domCore.getByName('body')[0];
		for(i=0; dragMe.catchers[i]; i++){
			b.removeChild(dragMe.catchers[i].proxy);
		}
	},
	onDrop : function(){},
	onDragging : function(){}
}

No voy a explicar lo que está pasando ahí dentro por que me tomaría mucho tiempo, pero si te interesa saber algo sobre el code, solo pregunta en los comentarios.

Una vez que has agregado el objeto, solo tienes que iniciar los elementos que serán arrastrables.

<meta name="keywords" content=""/>
<meta name="description" content=""/>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<meta http-equiv="content-type" content="application/xhtml+xml; charset=UTF-8"/>
<meta http-equiv="content-style-type" content="text/css"/>
<meta http-equiv="expires" content="0"/>
<script type="text/javascript" src="B_libs/domCore.js" ></script>
<script type="text/javascript" src="B_libs/dragMe.js"></script>
<script type="text/javascript">
	domCore.addEvent(window, 'load', function(){
		dragMe.registerCatcher(domCore.getById('catcher'));
		dragMe.registerCatcher(domCore.getById('catcher2'), function(){
			alert('dropped2');
		});
		domCore.addEvent(domCore.getById('drag'), 'mousedown', function(e){
			dragMe.startDrag(e, this);
			dragMe.onDrop = function(i,t,l){
				if(i){
					alert('in');
				}else{
					alert('out');
				}
			}
		});
		domCore.addEvent(domCore.getById('drag2'), 'mousedown', function(e){
			dragMe.startDrag(e, this);
			dragMe.onDrop = function(i,t,l){
				if(i){
					alert('adentro');
				}else{
					alert('afuera');
				}
			}
		});
	});
</script>
<style type="text/css">
	#catcher, #catcher2{
		width: 150px;
		height: 150px;
		border: 1px dashed #CCC;
	}
</style>
</head>
<body>
	<p id="drag">Hola, arrastrame!</p>
	<p id="drag2">Hola, arrastrame!</p>
	<div id="catcher"></div>
	<div id="catcher2"></div>
</body>

El objeto tiene tres métodos principales:

registerCatcher() Este método sirve para registrar las canastas donde queremos que se suelten los elementos. Acepta dos parámetros: El primero es una referencia al elemento que queremos que sea la canasta, el segundo es una función la cual queremos que se ejecute cuando soltemos algo dentro de la canasta. El primer parámetro es obligatorio, el segundo es opcional.

Ejemplo:

dragMe.registerCatcher(domCore.getById('catcher'));

startDrag() Este es el método que inicia el arrastre del elemento. Recibe dos parámetros, el primero es e o el evento en si. Solo ponle una e y es todo. Este parámetro es completamente necesario. El segundo parámetro es el elemento que se quiere arrastrar. Lo más logico es que sea una referencia al elemento sobre el que se hizo click, por lo que lo más seguro es que siempre le tengas que pasar this . Este también es necesario. startDrag() por fuerza tiene que ser ejecutado onmousedown, no lo agregues a otro evento por que dará problemas. Esto no es un error de programación o de planeación. Lo mas lógico es que arrastres un objeto con el mouse, por lo que esta es la forma más lógica de hacerlo.

Ejemplo:

domCore.addEvent(domCore.getById('drag'), 'mousedown', function(e){
	dragMe.startDrag(e, this);
	dragMe.onDrop = function(i,t,l){
		if(i){
			alert('in');
		}else{
			alert('out');
		}
	}
});

El tercer método es onDrop() este se ejecuta cuando el elemento siendo arrastrado es soltado. Este pequeño te regresa tres valores los cuales puedes capturar con la llamada al evento. El primero es un boleano (true o false) que indica si el elemento fue soltado dentro de una canasta o no. El segundo es el valor para top y el tercero el valor para left. Es decir que con el segundo y tercer valor puedes saber exactamente las coordenadas en las que el elemento fue soltado.

Ejemplo:

dragMe.onDrop = function(i,t,l){
	if(i){
		alert('in');
	}else{
		alert('out');
	}
}

onDrop y la función pasada como segundo parámetro a registerCatcher parecen hacer lo mismo, por lo que te preguntarás, que caso tiene tener ambas? la respuesta es simple, onDrop te permite ver si el elemento fue soltado en una canasta, mientras que la función en registerCatcher te permite saber si algo se solto en esa canasta. En otras palabras, con onDrop, el elemento te dice “me has soltado en una canasta”, mientras que la función en registerCatcher te dice “has soltado algo dentro de mi.” Es como ver el drop desde dos perspectivas, la del objeto arrastrable y la de la canasta.

Si estudias el code encontrarás más sorpresas, por ejemplo, un método onDragging() que se ejecuta durante el tiempo de arrastre y otras curiosidades.

Espero que les sirva este objeto, esperen soporte para IE en la siguiente versión. Como siempre, comentarios y sugerencias son bienvenidos.

Creando circulos con CSS.

December 11, 2009

Esto es solo una curiosidad que se me ocurrió ayer antes de dormir. Posiblemente ya se haya hecho antes, pero yo nunca he escuchado de ello. Se trata simplemente de crear círculos con CSS. No es nada del otro mundo, simplemente aprovechar un poco las características de CSS3, o en este caso mejor dicho, el ‘moz-border-radius que imita una característica de CSS3.

Creando un simple circulo:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title></title>
<meta name="author" content="Buzu">
<meta name="date" content="2009-12-11T11:04:26-0800">
<meta name="copyright" content="">
<meta name="keywords" content="">
<meta name="description" content="">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta http-equiv="content-type" content="application/xhtml+xml; charset=UTF-8">
<meta http-equiv="content-style-type" content="text/css">
<meta http-equiv="expires" content="0">
<style type="text/css">
 .circulo{
 border: 50px solid #ccc;
 -moz-border-radius: 60px;
 width: 15px;
 background-color: #CCC;
 height: 12px;
 }
</style>
</head>
<body>
 <p class="circulo"></p>
</body>

Como puedes ver, simplemente estamos aprovechando CSS y obtenemos un círculo. Naturalmente, esto solo funciona en firefox, pero puede ser adaptado de modo que funcione en la mayoría de los navegadores más populares. Ahora veamos si podemos hacer algo más con esos círculos:

Un mono de nieve:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title></title>
<meta name="author" content="Buzu">
<meta name="date" content="2009-12-11T11:29:47-0800">
<meta name="copyright" content="">
<meta name="keywords" content="">
<meta name="description" content="">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta http-equiv="content-type" content="application/xhtml+xml; charset=UTF-8">
<meta http-equiv="content-style-type" content="text/css">
<meta http-equiv="expires" content="0">
<style type="text/css">
 .cabeza{
 border: 50px solid #ccc;
 position: absolute;
 -moz-border-radius: 60px;
 top: 20px;
 left: 300px;
 background-color: #CCC;
 }
 .cuerpo{
 border: 70px solid #ccc;
 position: absolute;
 top: 110px;
 left: 280px;
 -moz-border-radius: 80px;
 background-color: #CCC;
 }
 .ojo{
 border: 5px solid #000;
 position: absolute;
 top: 50px;
 background-color: #000;
 -moz-border-radius: 6px;
 }
 .izquierdo{
 left: 330px;
 }
 .derecho{
 left: 360px;
 }
 .voca{
 border-bottom: 10px solid #F00;
 position: absolute;
 top: 80px;
 -moz-border-radius: 20px;
 width: 10px;
 left: 345px;
 }
</style>
</head>
<body>
 <p class="cabeza"></p>
 <p class="cuerpo"></p>
 <p class="ojo derecho"></p>
 <p class="ojo izquierdo"></p>
 <p class="voca"></p>
</body>
</html>

Podríamos incluso agregar un poco de javascript y hacer transiciones de cuadro a circulo o a otras formas, las posibilidades son muchas. A ti que se te ocurre?

Hace algunos días google anunció el lanzamiento de su servicio public DNS. Para aquellos que no sabe, DNS es el sistema que se encarga de traducir las URL a ip. Por ejemplo, cuando en tu navegador introduces la dirección www.google.com, esta es traducida a una dirección ip, en este caso:  74.125.19.105 Para comprobarlo, introduce los numero anteriores en la barra de direcciones de tu navegador y presiona enter. Esto debería llevarte directamente a la pagina de google.

Por que querría alguien cambiar la configuración de sus DNS?

Las respuestas pueden ser muchas, puedo mencionar por ejemplo, por velocidad. Es posible que un servicio sea más lento que otro ya sea por que aplica muchos filtros o simplemente por que el servicio es lento. En mi caso, decidí cambiar los DNS por que mi ISP aplicaba filtros de modo que si yo me equivocaba y ponía una dirección incorrecta, el navegador se iba al buscador y la publicidad de mi ISP. Además, estoy acostumbrado a simplemente poner la dirección, por ejemplo google y presionar enter, sin poner el .com, pero mi ISP me mandaba a su buscador en lugar de auto completar el dominio (google.com) (No estoy seguro, pero se supone que el navegador por si solo debería se capaz de completar el dominio). La situación era muy molesta, y por esa razón decidí hacer el cambio.

Como hacer el cambio de DNS en ubuntu?

En la verción 9.10 de ubuntu, solo tienes que hacer una modificación al archivo de configuración del cliente DHCP.

Primero abre el terminal y escribe:

ls /etc/dhcp3/

y presiona enter.

Fíjate que tengas un archivo llamado dhclient.conf

si está ahí, escribe:

gksudo gedit /etc/dhcp3/dhclient.conf

Esto te abrirá dhclient.conf en gedit. Ve hasta el final y agrega la siguiente linea:

prepend domain-name-servers 8.8.8.8, 8.8.4.4;

guarda los cambios y cierra gedit.

y listo, ahora ya puedes conectarte a internet usando google public DNS.

Que hace esto?

Lo único que hace el cambio que hemos hecho en dhclient.conf es agregar la IP de los DNS a usar antes de las de los de tu ISP. Lo más seguro es que estés usando las que tu proveedor de Internet te ha provisto como era mi caso.

Notas:

1)Se puede usar vi (sudo vi) en lugar de gedit (gksudo gedit), pero personalmente me siento más comodo con gedit que con vi.

2)Si tienes acceso al panel administrativo de tu router (conecciones inalámbricas) probablemente puedas hacer configuraciones más avanzadas. En mi caso, por ejemplo, podría introducir directamente los DNS desde ahí y hacer algunos otros cambios, pero prefiero no hacerlo y recomiendo no hacerlo a menos que sepas exactamente lo que estás haciendo.

Generalmente paso la mayor parte del tiempo en internet. Durante ese tiempo visito sitios, uso recursos, leo artículos, noticias, tutoriales, consumo ancho de banda y sobre todo obtengo beneficios. La mayor parte del tiempo navego la web yendo de enlace en enlace, pero hasta hace un tiempo había simplemente ignorado todos esos molestos ads. De un tiempo a la fecha, he decidido ser más agradecido con esas personas que han tomado el tiempo para desarrollar todo el contenido que estoy usando, y para poner tantos recursos a mi alcance sin tener que pagar.  Lo que hago es simple, si encuentro un sitio cuyo contenido me ha sido de utilidad, hago click en alguno de sus enlaces (generalmente solo los de texto, sigo sin soportar esos enlaces animados, con música o cualquier fanfarria de esas). Escribo esta  mini entrada en mi blog para ivitarte a que seas agradecido con las personas que han puesto el contenido al alcance de un click. No te cuesta nada y ni siquiera tienes que ver la pagina que se abre. Solo abrela en una pestaña nueva y dejala ahi sentada por un rato, despues cierrala y listo. Has contribuido con un poquito a que la persona(s) que está(n) detras del sitio sigan motivados en brindarnos ese contenido que tanto nos ha servido.

Se un poco más agradecido.

fadeObj.js actualizado.

November 19, 2009

Pues siguiendo las recomendaciones de mi gran amigo jseros, he actualizado fadeObj.js para implementar la simulación de los eventos onFadeStart y onFadeStep que se activan al iniciar el efecto y en cada una de las vueltas del loop respectivamente.

El código lo puedes obtener en:

http://www.p-freeweb.com/outside/javascript/fadev1.1/fadeObj1.1.js

También puedes ver un ejemplo demostrando el uso de onFadeStart y onFadeStep en:

http://www.p-freeweb.com/outside/javascript/fadev1.1/fade.html

Espero les gusten los cambios.

Espero más criticas y sugerencias.

PD. La implementación del método toggle para no tener que escoger el modo (entrada o salida) requiere un poco más de trabajo y por el momento no tengo el tiempo para implementarlo.Aun falta hacerlo cross browser.

Gracias Jseros y Panino por sus sugerencias y comentarios.

fadeObj.js –Nuevo script.

November 17, 2009

Hoy les traigo un script que estuve desarrollando durante mi tiempo libre estos dos últimos días. Aun me falta cosas por hacerle, como por ejemplo hacerlo cross browser, pero por ahora creo que es un buen ejercicio para quien lo quiera checar e incluso usar. Agradezco a mi gran amigo Panino5001 quien me ayudo a aclarar una duda que me surgió mientras codigueaba.

Checa un ejemplo de fadeObj.js

fadeObj.js

//ObjectName: fade
//Author:     Buzu.
//Varsion:    1.0
//todo:       evitar que se cancele el efecto una vez terminado.
//Bugs?:      Please report any bug to @imbuzu on twitter. use #fade1.0 #Bug

fade = {
 el : null,
 intervalo : null,
 mod : null,
 inAlph : null,
 seg : null,
 fadeF : function(e, m, s){
 //fadeF sig. fadeFunction
 //aceleramos el acceso a fade con una variable local.
 var f = fade;
 f.seg = s || 3;
 !e ? alert('No Elem') : (f.el = e);
 f.mod = m || 's';
 f.mod == 's' ? f.fadeout() : f.mod == 'e' ? f.fadein() : alert('no valid mode');
 },
 fadein : function(){
 var f = fade;
 //si se vuleve a activar el fade sobre el mismo objeto
 //no queremos que el objeto vuelva a alpha 0
 //sino que el efecto comienze con el alpha que el
 //elemento ya tiene.
 f.inAlph = f.inAlph || 0;
 f.intervalo = setInterval(
 function(){
 f.inAlph += 1/(f.seg*10);
 f.el.style.opacity = f.inAlph;
 if(f.inAlph >= 1){clearInterval(f.intervalo); f.onFadeEnd(f.el)};
 }, 100
 );
 },
 fadeout : function(){
 var f = fade;
 f.inAlph = f.inAlph || 1;
 f.intervalo = setInterval(
 function(){
 f.inAlph -= 1/(f.seg*10);
 f.el.style.opacity = f.inAlph;
 if(f.inAlph <= 0){clearInterval(f.intervalo); f.onFadeEnd(f.el);};
 },100
 );
 },
 onFadeEnd : function(){}
}

Ejemplo de uso:

window.onload = function(){
   document.getElementById('fade').onclick = function(){
      fade.onFadeEnd = function(e){
         document.getElementsByTagName('body')[0].removeChild(e);
      }
      fade.fadeF(this, 's', 2)
   }
}   

Para usar el objeto basta con llamar su método fadeF:

fade.fadeF()

Este método recibe tres parametros, el primero es el elemento al cual se le aplicará el fade, el segundo es el modo ’s’ para salida y ‘e’ para entrada y el tercero es el tiempo que durará el efecto (en segundos).

fade.fadeF(elem, 's', 5);

Solo el primer parámetro es obligatorio. Los otros son opcionales y toman como default  s y 3 respectivamente.

Al terminar el efecto, se llama al método onFadeEnd() para simular eventos:

fade.onFadeEnd = function(){
//codigo de la funcion
}

a onFadeEnd se le puede pasar un parametro el cual regresa el nodo al cual se le aplico el fade:

fade.onFadeEnd = function(e){
alert(e);
}

Para entender más el uso de fade, te invito a que revises el código fuente del ejemplo.

Espero que encuentren útil este objeto. En unos días terminare los detalles. Como siempre, estoy abierto a criticas y sugerencias.

NOTA: Este contenido es por motivos educativos e informativos solamente.

Hace un par de días se me ocurrió que posiblemente se puede acceder a las cookies de un sitio web mediante greasemonkey. Al principio pensé que un agujero de seguridad tan grande no debió pasar por enfrente de los ojos de los desarrolladores del plugin sin ser notado, así que hice una pequeña prueba la cual consiste en crear un nuevo script que sea ejecutable en todos los sitios el cual contiene solo la siguiente instrucción:

alert(document.cookie);

Es super sencillo e inofensivo. Sin embargo, al correr un sitio web te das cuenta que en efecto greasemonkey puede acceder a las cookies de cualquier sitio web. Lo que puedes hacer con esas cookies depende mucho de tu creatividad, conocimiento y por supuesto, de la cookie en sí. Por ejemplo una cosa sencilla que hice fue simplemente redireccionar el navegador a una pagina donde la cookie se manda por correo a mi bandeja de entrada. Al probar ese script pude enviarme las cookies de twitter que mi navegador almacena. Un script bien configurado y dirigido para atacar una app especifica podría causar mucho daño, o por lo menos un buen susto. Lo mas obvio que puedes hacer con esto es robar información y ganar acceso a algunas cuentas de sitios web que usan cookies de forma irresponsable.

Redireccionar no es la forma más inteligente de robarte las cookies. Pero recordemos que greasemonkey no está sujeto a las mismas normas de seguridad que javascript corriendo directamente desde un sitio web. Digo esto por que hay que recordar que ajax no está sujeto a un solo dominio, sino que puede interactuar con documentos de distintos dominios al mismo tiempo, por lo que podemos usar el mismo script que yo hice para enviar el correo, pero en lugar de redireccionar y hacer el robo de datos demasiado obvio, podemos usar ajax y hacer la transferencia totalmente transparente al usuario.

Que se puede hacer al respecto?

La verdad es muy poco probable que te pase eso, a menos que alguien esté intencionalmente haciéndolo y ahí es donde está el problema. Por ejemplo alguien puede esconder el script malicioso dentro de algún otro script. Supongamos que quiero robar las cookies de facebook de alguna persona. Solo tendría que escribir un script que fuera útil para los usuarios de facebook y distribuirlo. El script ya tiene dentro la parte que hace el truco. Puedo disfrazarla de alguna u otra manera e incluso ofuscarla. Puedo incluso hacer que el script malicioso se active solo cuando esa persona en particular lo usa y así evitarme un montón de correos en mi bandeja que en realidad no quiero. Entonces que podemos hacer?

Una de las cosas más obvias es simplemente revisar los scripts que usas, aun que claro, eso puede ser un dolor de cabeza. Puedes por ejemplo usar un editor de textos que tenga capacidad para buscar y haces una búsqueda de ‘document.cookie’ para saber cuando un script esté accediendo a las cookies de tu navegador y ver que es lo que está haciendo con ellas. Otra cosa también es usar script confiables y como siempre investigar un poco antes de instalar un script. Pero aun así, recuerda revisarlo aun si nadie reporta nada raro. Esto por que por ejemplo, yo podría descargar un script muy popular, modificarlo y redistribuirlo asegurando que mucha más gente lo va a usar que un script que yo simplemente haya creado ayer por la tarde.

PD. Probablemnte muchos quieran ver los scripts que hice para enviarme cookies a mi correo. No lo comparto por que se que ahí afuera hay muchos script kiddies que probarán todo lo que encuentren para ‘hackear’.  Además, los scripts son tan básicos que cualquiera que tenga conocimientos mínimos los puede desarrollar por si solo.

Hace un par de días comencé a notar una cosa. Primero fue con twitter y su nueva funcionalidad (que al parecer por el momento la han deshabilitado) de actualizar el sitio cada vez que hay twitts nuevos. Me encantaba por que solo dejaba la ventana abierta y en cualquier momento el titulo de la pestaña cambiaba para indicar cuantos twitts nuevos había. Es mucho más fácil estar al tanto de twitter (y esclavizase a él) de esa manera sin tener que tener otra app abierta. Después comencé a notarlo con otros sitios. Por ejemplo, http://scobleizer.com/ actualiza su barra lateral cada cierto tiempo. Llegó el momento que me dije a mi mismo, Gush! este sitio está vivo!. No es la primera vez que veo que un sitio se mueve por si solo. He visto cientos de rolling menus, y sitios que de una u otra forma “se mueven”, pero eso no me impresiona. Después de todo, todo eso que se mueve no es más que un loop, algo que alguien programó antes y que no cambia-un .gif programado. Sin embargo, estos sitios están no solo moviéndose, sino auto actualizándose para mostrarte el nuevo contenido y es eso precisamente lo que causa la sensación de WOW!

Como programador que soy, se que todo lo que hay detrás no es más que ajax, pero la verdad aun así me impresionó. Probablemente sea por que es una de las primeras veces que veo ajax empleado de forma usable, amigable y responsable, o quizá solo me agarró desprevenido y me sorprendió. Cualquiera que sea la razón, la verdad que por un momento me hizo sentir que estaba viendo algo vivo, algo que se movía, y me produjo la sensación que te produce ver cuando un recién nacido mueve una mano-simplemente increíble. Posiblemente esté exagerando, después de todo ajax ya está creciendo barba. Sin embargo, es agradable ver que finalmente los desarrolladores están aprendiendo a usarlo de forma benéfica y no solo para impresionar damiselas. Seguro que la web nos depara muchas sorpresas todavía. Apps como wave se abren paso y cada vez la web deja de ser ese papel lleno de formularios que proveen la única forma de interacción. En lo personal no me emociona las animaciones ni los drag and drop.  Eso lo veo más bien como simples trucos de feria. Los verdaderos avances en la materia son aquellos que no se notan, que han sido tan bien calculados, planeados y desarrollados que se introducen de forma natural de modo que el usuario nunca se da cuenta que lo está usando y por lo tanto nunca tiene que aprender algo nuevo ni adaptarse aun nuevo método de interacción. Way to go, pero la web es cada vez más excitante y nos exige a notros, lo programadores que de cierta manera somos participes en esa evolución web, cada vez mejores y más responsables metodologías para el uso y la aplicación de las nuevas tecnologías. Ahora solo tenemos dos caminos, sentarnos a esperar más avances en la materia, o se nosotros mismos quienes impulsemos eso avances. Tu cual escoges?