<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>

<channel>
	<title>Maestros del Web &#187; Pepe Molina</title>
	<atom:link href="http://www.maestrosdelweb.com/author/pepe-molina/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.maestrosdelweb.com</link>
	<description>Un espacio para los entusiastas del web</description>
	<pubDate>Fri, 21 Nov 2008 02:02:21 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.3</generator>
	<language>en</language>
			<item>
		<title>Revisar las imágenes antes de subirlas</title>
		<link>http://www.maestrosdelweb.com/editorial/revisar-las-imagenes-antes-de-subirlas/</link>
		<comments>http://www.maestrosdelweb.com/editorial/revisar-las-imagenes-antes-de-subirlas/#comments</comments>
		<pubDate>Thu, 29 Mar 2007 07:00:21 +0000</pubDate>
		<dc:creator>Pepe Molina</dc:creator>
		
		<category><![CDATA[Desarrollo Web]]></category>

		<category><![CDATA[Editorial]]></category>

		<category><![CDATA[Javascript]]></category>

		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.maestrosdelweb.com/editorial/revisar-las-imagenes-antes-de-subirlas/</guid>
		<description><![CDATA[Cuando se quiere que una imagen seleccionada en un formulario pueda ser previsualizada antes del envío del mismo, y poder controlar cosas como tipo, tamaño o dimensiones; podemos encontrarnos con serios problemas. Con este tutorial acompañado de un sencillo ejemplo, podemos ver como conseguirlo.
Limpiando un campo file
Comprobar que un fichero tenga una extensión determinada no [...]]]></description>
			<content:encoded><![CDATA[<p><span class="intro">Cuando se quiere que una imagen seleccionada en un formulario pueda ser previsualizada antes del envío del mismo, y poder controlar cosas como tipo, tamaño o dimensiones; podemos encontrarnos con serios problemas. Con este tutorial acompañado de un sencillo ejemplo, podemos ver como conseguirlo.</span><span id="more-2405"></span></p>
<h3>Limpiando un campo file</h3>
<p>Comprobar que un fichero tenga una extensión determinada no es muy difícil con javascript, pero cuando lo tenemos seleccionado y no es correcto, podemos cometer el error de pulsar sobre el botón de envío.</p>
<p>Debido a ello vamos a proponer un script que permita previsualizar la imagen que seleccionemos, y en el caso de que el fichero seleccionado no tenga la extensión de imagen que nos interese, limpiar el campo file.</p>
<p>La estructura será así:</p>
<div class="codigo">
<pre>
function checkear_extension(fichero)	{
	// definimos antes los métodos prever() y limpiar()
	(/.(gif|jpg|png)$/i.test(fichero.value)) ? prever() : limpiar();
}</pre>
</div>
<p>La función limpiar():</p>
<div class="codigo">
<pre>
function limpiar()	{
	f = document.getElementById("archivo");
	nuevoFile = document.createElement("input");
	nuevoFile.id = f.id;
	nuevoFile.type = "file";
	nuevoFile.name = "archivo";
	nuevoFile.value = "";
	nuevoFile.onchange = f.onchange;
	nodoPadre = f.parentNode;
	nodoSiguiente = f.nextSibling;
	nodoPadre.removeChild(f);
	(nodoSiguiente == null) ? nodoPadre.appendChild(nuevoFile):
		nodoPadre.insertBefore(nuevoFile, nodoSiguiente);
}</pre>
</div>
<p>Como puede verse la forma de limpiar un campo file es algo rebuscada, pero después de hacer muchas pruebas, es la única manera funcional en los tres navegadores probados. De todos modos, simplemente se podría comprobar la extensión durante la validación del formulario:</p>
<div class="codigo">
<pre>-onsubmit=''return/.(gif|jpg|png)$/i.test(archivo.value)"</pre>
</div>
<h3>La visualización</h3>
<p>Mostrar una imagen seleccionada desde un campo file podría parecernos cosa fácil, pero por razones de seguridad no se pueden mostrar las imágenes a no ser que estén en la red (tal vez puedan encontrarse truquillos que funcionen en algún navegador, pero no sirven en todos).</p>
<p>Solo queda mostrar el método prever que definiremos dentro del método <code>checkear_extension()</code>, que definitivamente se quedaría de la siguiente manera:</p>
<div class="codigo">
<pre>
function checkear_extension(fichero)	{

	function prever() {
		var campos = new Array("maxpeso", "maxalto", "maxancho");
		for (i = 0, total = campos.length; i &lt; total; i ++)
			fichero.form[campos[i]].disabled = false;
		actionActual = fichero.form.action;
		targetActual = fichero.form.target;
		fichero.form.action = "previsor.php";
		fichero.form.target = "ver";
		fichero.form.submit();
		for (i = 0, total = campos.length; i &lt; total; i ++)
			fichero.form[campos[i]].disabled = true;
		fichero.form.action = actionActual;
		fichero.form.target = targetActual;
	}

	function no_prever() {
		alert("El fichero seleccionado no es válido...");
		limpiar();
	}

	(/.(gif|jpg|png)$/i.test(fichero.value)) ? prever() : no_prever();
}</pre>
</div>
<p>Como comentarios adicionales, solo quedaría matizar que la visualización no es otra cosa que el envío del formulario con la habilitación de los campos que servirán de control, hacia una ventana, que en este caso concreto es un iframe del mismo documento.</p>
<h3>El resto de javascript</h3>
<p>Lo que quedaría por definir es un sistema validador para evitar el envío del formulario en el caso de no haber seleccionado una imagen válida, y un método que reciba los valores sobre la imagen que se seleccione.</p>
<p>Para la primera definición supondremos que la etiqueta form tiene algo de esto: <code>&lt;form onsubmit="return validar(this)"&gt;</code></p>
<div class="codigo">
<pre>
function validar(f)	{
	enviar = /.(gif|jpg|png)$/i.test(f.archivo.value);
	if (!enviar)	alert("seleccione imagen");
	return enviar;
}</pre>
</div>
<p>Y los datos de la previsualización los recibirá un método que llamaremos <code>datosImagen()</code>, cuyos argumentos serán, el peso, anchura, altura y nº de error (si el error es &#8220;0&#8243; significa sin error).</p>
<div class="codigo">
<pre>
function datosImagen(peso, ancho, alto, error)	{
	function mostrar_error()	{
		enviar = false;
		mensaje = "Ha habido un error (error nº " + error + "):";
		if (error % 2 == 1) // tipo incorrecto
			mensaje += "nel fichero no es válido";
		error = parseInt(error / 2);
		if (error % 2 == 1) // excede en peso
			mensaje += "nla imagen pesa mogollón (" + peso + ").";
		error = parseInt(error / 2);
		if (error % 2 == 1) // excede en anchura
			mensaje += "nla imagen excede en anchura (" + ancho + ").";
		error = parseInt(error / 2);
		if (error % 2 == 1) // excede en altura
			mensaje += "nla imagen excede en altura (" + alto + ").";
		error = parseInt(error / 2);
		alert (mensaje);
		with (document.forms)	{
			formu.peso.value = 0;
			formu.ancho.value = 0;
			formu.alto.value = 0;
		}
		limpiar();
	}

	if (error == 0)	with (document.forms)	{
		formu.peso.value = peso;
		formu.ancho.value = ancho;
		formu.alto.value = alto;
	}
	else	mostrar_error();
}</pre>
</div>
<p>Sobre la forma de codificar los errores no voy a hacer comentarios para que este artículo no se haga demasiado extenso.</p>
<h3>Gestión desde el servidor</h3>
<p>La página destino del formulario durante este sistema de previsualización, debe ser una página web, con una imagen (que en este caso será el fondo de la página), y el contenido de esa imagen será el recibido por la imagen del formulario.</p>
<div class="codigo">
<pre>
&lt;?php
	session_start();
	$defecto = "webmaster.gif";
	$Ok = isset($_FILES["archivo"]);
	$url = ($Ok) ? $_FILES["archivo"]["tmp_name"] : $defecto;
	list($anchura, $altura, $tipoImagen, $atributos) = getimagesize($url);
	$error = (isset($atributos)) ? 0 : 1;
	$los_tipos = array("gif", "jpg", "png");
	$tipo = ($Ok) ? "image/".$los_tipos[$tipoImagen - 1] : "image/gif";
	$fichero = ($Ok &amp;&amp; ($error == 0)) ? $_FILES["archivo"]["name"] : $defecto;
	$tam = filesize($url);
	$OkTam = isset($_POST["maxpeso"]);
	$OkAncho = isset($_POST["maxancho"]);
	$OkAlto = isset($_POST["maxalto"]);
	$maxTam = ($OkTam) ? (int) $_POST["maxpeso"]: 100000;
	$maxAncho = ($OkAncho) ? (int) $_POST["maxancho"]: 640;
	$maxAlto = ($OkAlto) ? (int) $_POST["maxalto"]: 480;
	$error += ($tam &lt;= $maxTam) ? 0 : 2;
	$ancho = ($error == 1) ? 0 : $anchura;
	$alto = ($error == 1) ? 0 : $altura;
	$error += ($ancho &lt;= $maxAncho) ? 0 : 4;
	$error += ($alto &lt;= $maxAlto) ? 0 : 8;
	$datos = ($error == 0) ? $url : $defecto;
	$onload = ($Ok) ? "onload='parent.datosImagen($tam, $ancho, $alto, $error)'": '';
	$datos_imagen = fread(fopen($datos, "rb"), filesize($datos));
	$_SESSION["cont"] = $datos_imagen;
	$_SESSION["tipo"] = ($error == 0) ? $tipo : "image/gif";
?&gt;
&lt;html&gt;
&lt;head&gt;
&lt;style type="text/css" &gt;
html	{
	margin: 0;
	height: 100%;
}
body	{
	height: 100%;
	background-image: url(previendo.php?dato=&lt;?=$fichero;?&gt;);
	background-repeat: no-repeat;
	background-position: center center;
}
&lt;/style&gt;
&lt;/head&gt;
&lt;body &lt;?=$onload;?&gt;&gt;

&lt;/body&gt;
&lt;/html&gt;</pre>
</div>
<p>Resumiendo el código expuesto, diremos que se crea una sesión <a href="http://www.maestrosdelweb.com/editorial/phpintro/">php</a> y se guarda el código de la imagen y su tipo; además se pone como fondo de la página un fichero (previendo.php) que a pesar de tener parámetro, en la página no se consideran, la razón de esta &#8220;curiosidad&#8221; es evitar que la imagen sea mostrada por los navegadores desde la memoria caché.</p>
<p>Otra curiosidad es la definición en la etiqueta body (sus estilos se ven en la sección style de la cabecera del documento) del evento load (onload), donde se envían datos a la ventana &#8220;parent&#8221;, con información de la imagen y un código de error, que de ser distinto de 0 en la página &#8220;padre&#8221; mostrará una alerta con la descripción del mismo.</p>
<p>Para finalizar mostraremos el contenido del fichero previendo.php, que como se puede adivinar, tan solo envía el contenido de la imagen a la consola:</p>
<div class="codigo">
<pre>
&lt;?php
session_start();
$url = ($_SESSION["cont"] == "")
	? fread(fopen("webmaster.gif", "rb"), filesize("webmaster.gif"))
	: $_SESSION["cont"];
$tip = ($_SESSION["tipo"] == "")
	? "image/gif"
	: $_SESSION["tipo"];
header("Content-type: $tip");
echo $url;
session_destroy();
?&gt;</pre>
</div>
<p>Solo nos queda mostrar este código en funcionamiento; para ello podemos visualizar el <a href="http://www.caricatos.net/articulos/check_form.html">formulario ejemplo</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.maestrosdelweb.com/editorial/revisar-las-imagenes-antes-de-subirlas/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Destripador</title>
		<link>http://www.maestrosdelweb.com/editorial/destripador/</link>
		<comments>http://www.maestrosdelweb.com/editorial/destripador/#comments</comments>
		<pubDate>Tue, 02 May 2006 00:00:00 +0000</pubDate>
		<dc:creator>Pepe Molina</dc:creator>
		
		<category><![CDATA[Editorial]]></category>

		<category><![CDATA[Javascript]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[El término suena extraño, pero es posible destripar una página web de forma sencilla y obtener cada una de las tripas que se encuentran al abrir nuestro explorador.
Estructura de árbol
En la jerga informática  se suele usar mucho el término &#8220;estructura de árbol&#8221;, &#160;que significa una dependencia de unas cosas  con otras, &#160;en donde [...]]]></description>
			<content:encoded><![CDATA[<p><span class="intro">El término suena extraño, pero es posible destripar una página web de forma sencilla y obtener cada una de las tripas que se encuentran al abrir nuestro explorador.</span><span id="more-332"></span></p>
<h3>Estructura de árbol</h3>
<p>En la jerga informática  se suele usar mucho el término &#8220;estructura de árbol&#8221;, &nbsp;que significa una dependencia de unas cosas  con otras, &nbsp;en donde el objeto más  importante es la raíz; y en una página web, la raíz es la propia ventana (el  objeto window). </p>
<p>De dicho objeto window,  se desprenden unas cuantas ramas que a la vez, en algunos casos, son objetos y  en otros no, estos últimos se podrían considerar simples &#8220;hojas&#8221;,  pero en lenguaje informático creo que es mejor decir que se trata de atributos  o propiedades </p>
<p>El código que a  continuación se presenta, permite destripar el objeto window:</p>
<div class="codigo">
<pre>function destriparWindow()	{
	var tripas = "destripando el objeto &lt;u&gt;window&lt;/u&gt;";
	dato = window;
	for(esto in dato)  tripas += "&lt;br /&gt;" + esto + " = " + dato[esto];
	return tripas;
}</pre>
</div>
<p>Si se quisiera  mostrar las tripas de window en una capa podríamos crear esa capa vacía y con  un identificador. Ejemplo: &lt;div id=&#8221;despiece_de_window&#8221; &gt;, y el  botón para activar el script podría estar definido así: </p>
<div class="codigo">
<pre>&lt;button
 onclick="with
(document.getElementById('despiece_de_window')) innerHTML = destriparWindow()" &gt;
Destripar el objeto window
&lt;/button &gt;
</pre>
</div>
<p>El siguiente  espacio contiene el script y las definiciones de la capa y el botón para que  pueda ver los resultados: </p>
<p><script type="text/javascript">
<!--
function destriparWindow()	{
	var tripas = "destripando el objeto <u>window</u>&#8220;;
	dato = window;
	for(esto in dato)  tripas += &#8220;<br />&#8221; + esto + &#8221; = &#8221; + dato[esto];
	return tripas;
}
&#8211;></p>
<p></script><br />
<script type="text/javascript">
<!--
function destriparWindow()	{
	var tripas = "destripando el objeto <u>window</u>&#8220;;
	dato = window;
	for(esto in dato)  tripas += &#8220;<br />&#8221; + esto + &#8221; = &#8221; + dato[esto];
	return tripas;
}
&#8211;>
</script></p>
<hr style="margin: auto; width: 50%; text-align: center;">
<div id="despiece_de_window" style="border: 1px solid gray; margin: 0.2cm auto; overflow: auto; display: none; width: 80%; height: 150px; background-color: rgb(238, 238, 238);">
</div>
<p><button onclick="with (document.getElementById('despiece_de_window')) {style.display = 'block';innerHTML = destriparWindow();} this.disabled = 'disabled'" style="margin: auto; width: 60%; display: block;"><br />
Destripar el objeto window<br />
</button></p>
<hr style="margin: auto; width: 50%; text-align: center;">
<h3>Destripar el objeto window</h3>
<p>Según &nbsp;el resultado obtenido en el recuadro  informativo, después de activar el script, podemos ver que dependen del objeto  window una buena cantidad de objetos (o tal vez sea mejor decir sub-objetos).  Entre ellos podemos encontrar document, location, el propio objeto window, self,  etc. que nos permite deducir el próximo paso: qué tal si modificamos nuestro  destripador del objeto window, permitiendo un parámetro: un objeto para  destripar. </p>
<p>Bueno, como yo ya  lo hice, lo propongo como ejercicio, por ejemplo: en vez de llamarse:  &#8220;destriparWindow()&#8221; podría ser &#8220;destriparObjeto()&#8221; o  simplemente &#8220;destripar()&#8221;. El parámetro será el objeto a destripar,  así que la resolución del ejercicio pasaría por cambiar las coincidencias del  objeto window en el script por lo que se pasa como parámetro. En <a href="http://www.forosdelweb.com/">foros del web</a> pueden hacer las preguntas  que quieran para esta tarea. </p>
<h3>Otros objetos para destripar </h3>
<p>La lista de  objetos para destripar puede ser inmensa, incluso se pueden destripar nuevos  objetos creados dinámicamente. </p>
<h3>Objetos interesantes para destripar:</h3>
<ul>
<li>document </li>
<li>document.frames </li>
<li>location </li>
<li>document.body </li>
<li>document.body.childNodes </li>
<li>document.getElementById(&#8217;despiece_de_window&#8217;).parentNode </li>
</ul>
<h3>Conclusiones</h3>
<p>Antes de  terminar, me gustaría prevenir a aquellos osados lectores que se les haya pasado  por la cabeza hacer un destripador recursivo, que en el momento que encuentre  un objeto &#8220;destripable&#8221; lo destripe sin más. No sé si habrán notado  que el objeto window tiene como rama desprendiéndose de sí otro objeto window.  Y es que una de las características de esta estructura de árbol es que contiene  nodos que hacen referencia a sí mismos, de esta forma un sistema recursivo  generaría un &#8220;bucle infinito&#8221;, cosa que todo programador sabe que  debe evitarse. </p>
<p>Un buen ejemplo a  manera de conclusión es:  un destripador que hice con anterioridad y que sirvió de semilla para escribir  este artículo: <a href="http://www.pepemolina.com/DOM/destripador.html">Destripador  web</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.maestrosdelweb.com/editorial/destripador/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Colores intermedios RGB</title>
		<link>http://www.maestrosdelweb.com/editorial/coloresrgb/</link>
		<comments>http://www.maestrosdelweb.com/editorial/coloresrgb/#comments</comments>
		<pubDate>Fri, 17 Mar 2006 00:00:00 +0000</pubDate>
		<dc:creator>Pepe Molina</dc:creator>
		
		<category><![CDATA[Diseño Gráfico]]></category>

		<category><![CDATA[Editorial]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Si alguien nos pregunta ¿cuál es el color intermedio entre el blanco y el negro?, no tenemos ninguna duda y respondemos gris (y luego pensamos&#8230; ¡esta pregunta fue fácil!).
¿RGB?
Y si queremos los colores para alguna aplicación informática, tenemos que
concentrarnos en el concepto RGB que proviene de las iniciales de los tres colores básicos que se
necesitan: [...]]]></description>
			<content:encoded><![CDATA[<p><span class="intro">Si alguien nos pregunta ¿cuál es el color intermedio entre el blanco y el negro?, no tenemos ninguna duda y respondemos gris (y luego pensamos&#8230; ¡esta pregunta fue fácil!).</span><span id="more-321"></span></p>
<h3>¿RGB?</h3>
<p>Y si queremos los colores para alguna aplicación informática, tenemos que<br />
concentrarnos en el concepto RGB que proviene de las iniciales de los tres colores básicos que se<br />
necesitan: rojo, verde y azul (en inglés: Red Green Blue)</p>
<p>Ahora los colores dejan de serlo para convertirse en unos números que se corresponden con la cantidad o<br />
porcentaje de cada componente. En resúmen, contestando más técnicamente la pregunta inicial, el negro<br />
es ausencia de los tres componentes (rojo, verde y azul)&#8230; el blanco es la máxima cantidad de ellos&#8230;<br />
y el gris es la mitad de cada uno.</p>
<p>Para mostrar colores en las páginas web hay que usar su descripción en inglés, siempre que<br />
esté definido; por ejemplo existe el negro (black), el blanco (white), el gris (gray)&#8230;, pero para<br />
otras tonalidades podría no existir una descripción, así que tenemos que pensar en un sistema<br />
que indique la cantidad de cada componente del color que queremos.</p>
<p>Uno de esos sistemas es una especie de función &#8220;rgb()&#8221; que recibe 3 parámetros que pueden ser números entre<br />
0 y 255, donde el blanco sería rgb(255,255,255); también pueden usarse porcentajes: rgb(100%,100%,100%).<br />
Otra forma de representación consiste en una cadena de texto empezada por el carácter almohadilla (#)<br />
seguido de los valores hexadecimales de cada componente: #FFFFFF.</p>
<h3>Hexadecimal: conceptos básicos</h3>
<p>En el sistema hexadecimal cada dígito puede valer entre 0 y 15 (0..F), y para los colores necesitamos<br />
un rango entre 0 y 255 (00..FF). Seguidamente mostraremos la forma de convertir valores numéricos<br />
decimales/hexadecimales ayudándonos del lenguaje javascript.</p>
<div class="codigo">
<pre>
// conversión de un número entre 0 y 255 a su valor hexadecimal.
// Por ejemplo valorHex(255) = "FF"
function valorHex(n)    {
    return "0123456789ABCDEF".charAt(parseInt(n / 16))
	+ "0123456789ABCDEF".charAt(parseInt(n % 16));
} 

// conversión de un número hexadecimal "00" y "FF"
// a su valor numérico decimal (entero positivo: 0..255).
// Por ejemplo valorDecimal("FF") = 255
function valorDecimal(s) {
  return ("0123456789ABCDEF".indexOf(s.charAt(0)) * 16)
	+ "0123456789ABCDEF".indexOf(s.charAt(1));
}</pre>
</div>
<p>Con la ayuda de estos conversores que acabamos de definir podemos manipular mejor los colores de<br />
  nuestra página. Propongo a continuación la declaración de un objeto &#8220;Color&#8221;, donde la definición<br />
  se realiza introduciendo como parámetro sus tres componentes en forma numérica, o si se prefiere<br />
como una cadena de texto. </p>
<div class="codigo">
<pre>
// Objeto Color: a partir de sus 3 componentes
// Entero positivo: 0..255
function Color(Rojo, Verde, Azul)	{
	this.Rojo = Rojo;
	this.Verde = Verde;
	this.Azul = Azul;
	this.toString = function()	{
		return "#" + valorHex(this.Rojo) + valorHex(this.Verde) + valorHex(this.Azul);
	}
	this.toArray = function()	{
		return new Array(this.Rojo, this.Verde, this.Azul);
	}
	this.fromString = function(s)	{
		return new Color(valorDecimal(s.substr(1, 2)),
			valorDecimal(s.substr(3, 2)),
			valorDecimal(s.substr(5, 2)));
	}
}
</pre>
</div>
<p>Notese la definición de los métodos toString(), toArray() y fromString(s)&#8230; en realidad &#8220;toString()&#8221; es una<br />
re-definicaión ya que los objetos javascript implementan de forma inherente este método cuya<br />
finalidad es representarlos; toArray() devuele los componentes como un array. También puede formarse<br />
una cadena de este tipo: </p>
<div class="codigo">
<pre>
"rgb(" + negro.toArray() + ")"
</pre>
</div>
<p>&#8230; fromString() es un método que permite la construcción del color a partir de otro color representado<br />
por una cadena. He creído conveniente usar una representación que nos permita su uso directo.</p>
<p>O sea que con este código son válidas las siguientes definiciones:</p>
<div class="codigo">
<pre>
var negro = new Color(0, 0, 0);
var blanco = new Color().fromString("#FFFFFF");
// Para obtener el color como una cadena
// bastaría con poner el nombre de la variable:
alert(negro);
// Y si quisieramos obtener el color como un array de
// sus tres componentes habría que añadirle la coletilla
// toArray() al nombre de la variable:
alert(negro.toArray());
// Por último podemos obtener el valor de cada componente
// consultando el atributo correspondiente
alert(negro.Rojo);
</pre>
</div>
<h3>Los valores intermedios</h3>
<p>Teniendo las declaraciones necesarias para manipular colores nos centraremos en la obtención<br />
de los valores intermedios. Para ello debemos obtener un número que he denominado ratio,<br />
que sumándolo a cada componente nos permite obtener el siguiente.<br />
De más está decir que esos valores también pueden ser negativos.</p>
<div class="codigo">
<pre>
function coloresIntermedios(inicial, final, pasos)	{
	var resultado = new Array(pasos--);
	resultado[0] = inicial;
	resultado[pasos] = final;
	ratio = new Color(parseInt((final.Rojo - inicial.Rojo) / pasos),
		parseInt((final.Verde - inicial.Verde) / pasos),
		parseInt((final.Azul - inicial.Azul) / pasos));
	for (var i = 1; i < pasos; i ++)
		resultado[i] = new Color(inicial.Rojo + (ratio.Rojo * i),
			inicial.Verde + (ratio.Verde * i),
			inicial.Azul + (ratio.Azul * i));
	return resultado;
}
</pre>
</div>
<h3>Una sencilla aplicación</h3>
<p>Si quisieramos obtener esos datos intermedios introduciendo por teclado los colores<br />
inicial y final, además del número de valores intermedios, nos bastaría un pequeño formulario<br />
con 3 elementos para la entrada de datos, un botón para poner en funcionamiento nuestro script,<br />
y un elemento que muestre esos datos.</p>
<div class="codigo">
<pre>
&lt;form name="intermedios" action="" method="get" &gt;
color inicial:&lt;input type="text" name="ini" value="#000000" /&gt;
color final:&lt;input type="text" name="fin" value="#FFFFFF" /&gt;
pasos:&lt;input type="text" name="pasos" value="5" /&gt;
&lt;textarea name="resultado" style="width: 70%; height: 150px;"&gt;&lt;/textarea&gt;
&lt;br/&gt;

&lt;button
	onclick="resultado.value = coloresIntermedios(new Color().fromString(ini.value),
		new Color().fromString(fin.value), pasos.value)" >
obtener intermedios
&lt;/button&gt;
&lt;/form&gt;
</pre>
</div>
<h3>Algunos usos</h3>
<p>Se me ocurren dos posibles usos para este sistema: fondos degradados en botones, capas y páginas;<br />
y efecto fade en textos. Se puede apreciar estas dos funcionalidades en la siguiente página:<br />
<a href="http://www.caricatos.net/gradientes/index.html"><br />
Gradientes (php + librerías GD)</a></p>
<h3>Otros enlaces relacionados</h3>
<p>Para quien desee más información:</p>
<ul>
<li><a href="http://www.caricatos.net/gradientes/index.html">Gradientes (php + librerías GD) -mencionado anteriormente-</a></li>
<li><a href="http://www.forosdelweb.com/showthread.php?p=903567#post903567" >gradientes (FAQs javascript en Foros del web)</a></li>
<li><a href="http://www.forosdelweb.com/showthread.php?postid=377464#post377464" >Fondo degradado (FAQs javascript en Foros del web)</a></li>
<li><a href="http://www.maxxblade.co.uk/fade/index.htm" >Fade v1.1</a></li>
<li><a href="http://www.forosdelweb.com/showthread.php?t=159137" >FadeOut en un talbla</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.maestrosdelweb.com/editorial/coloresrgb/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Formularios y enlaces dirigidos a ventanas</title>
		<link>http://www.maestrosdelweb.com/editorial/formenlaces/</link>
		<comments>http://www.maestrosdelweb.com/editorial/formenlaces/#comments</comments>
		<pubDate>Thu, 23 Feb 2006 00:00:00 +0000</pubDate>
		<dc:creator>Pepe Molina</dc:creator>
		
		<category><![CDATA[Editorial]]></category>

		<category><![CDATA[Javascript]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[A través del presente artículo aprenderemos la correcta utilización de las ventanas popup, pues la forma que considerabamos correcta, según algunos artículos publicados no lo es del todo.
Incluso se afirma que son formas semánticamente correctas, no voy a juzgar si está bien o mal empleado el uso de esas palabras, tan solo voy a incluír [...]]]></description>
			<content:encoded><![CDATA[<p><span class="intro">A través del presente artículo aprenderemos la correcta utilización de las ventanas popup, pues la forma que considerabamos correcta, según algunos artículos publicados no lo es del todo.</span><span id="more-204"></span></p>
<p>Incluso se afirma que son formas semánticamente correctas, no voy a juzgar si está bien o mal empleado el uso de esas palabras, tan solo voy a incluír un enlace a un artículo de <a href="http://es.wikipedia.org/wiki/Portada">wikipedia</a>, sobre <a href="http://es.wikipedia.org/wiki/Sem%C3%A1ntica">&#8220;Semántica&#8221;</a>.</p>
<p>En principio podría decir simplemente que la forma correcta es la que se puede ver en un mensaje de los <a href="http://www.forosdelweb.com">foros del web</a> que yo mismo escribí:<a href="http://www.forosdelweb.com/showthread.php?postid=693040#post693040">. Abrir enlace en un popup</a> (me refiero a la primera de esas formas), pero he notado que siguen existiendo dudas, tal como se puede deducir de este otro mensaje: <a href="http://www.forosdelweb.com/showthread.php?t=238052">Hay que rectificar las FAQS</a></p>
<p>Existen varias páginas en donde se explica esa forma de enlazar:</p>
<ul>
<li><a href="http://www.nosolousabilidad.com/articulos/popups_javascript.htm">http://www.nosolousabilidad.com/articulos/popups_javascript.htm</a></li>
<li><a href="http://www.sitepoint.com/article/perfect-pop-up">http://www.sitepoint.com/article/perfect-pop-up</a></li>
<li><a href="http://www.accesibilidad.info/2005/02/28/popup_de_javascript_accesible/">http://www.accesibilidad.info/2005/02/28/popup_de_javascript_accesible/</a></li>
<li><a href="http://www.alistapart.com/articles/popuplinks/">http://www.alistapart.com/articles/popuplinks/</a></li>
<li><a href="http://www.jlvelazquez.net/accesibilidad/popups.asp">http://www.jlvelazquez.net/accesibilidad/popups.asp</a></li>
</ul>
<p>Y&#8230; ¿Por qué afirmo que no es correcto?</p>
<p>Para iniciar daré una explicación sencilla  basada justamente en la semántica. Si usamos un enlace o vínculo a otra página, es evidente que pensamos que ese vínculo se puede realizar, pero el usar la sentencia return false (asociado al evento click de ese enlace) estamos dando la orden de cancelar el enlace o vínculo. En resumen, usando un enlace queremos expresar &#8220;enlace a&#8221;, y usando return false estamos expresando &#8220;no enlace&#8221;.</p>
<p>Podríamos pensar entonces que no debería existir ese tipo de cancelación, pero la verdadera razón de existencia es para confirmación o validación, tal como explicaré más adelante.</p>
<p>Describiré ahora la forma correcta, ayudándome de la similitud entre enlaces y formularios. La verdad es que son muy pocas las veces que se plantea el envío de un formulario hacia un popup,  pero es posible, y está registrado en las FAQs javascript del mismo foro: <a href="http://www.forosdelweb.com/showthread.php?postid=624635#post624635">Submit a una ventana emergente (popup)</a>, que también escribí. Además he encontrado un mensaje precedente: <a href="http://www.forosdelweb.com/showthread.php?t=73648">Un consejo, una idea, por favor</a>.</p>
<h3>Forma correcta</h3>
<p>El enlace a un popup se debe hacer como cualquier enlace, usando el atributo href&#8230;, y para enviar formularios se utiliza el atributo action (en el primer caso se usa la etiqueta &#8220;a&#8221; y en el segundo &#8220;form&#8221;).</p>
<p>Para que el soporte destino (tanto de los enlaces como de los formularios) sea otra ventana, debe definirse el atributo target. Existen nombres estándar de algunas ventanas como _self, _blank, _top, _parent. Pero también se puede dar un nombre arbitrario, y esos es lo que debemos hacer.</p>
<h4> Y ahora viene lo más importante&#8230; &#8220;el popup&#8221;&#8230; </h4>
<p>Tanto formularios como enlaces, ofrecen un sistema para confirmar/cancelar la ejecución y que son muy parecidos. Usando un valor lógico con el evento asociado: submit para formularios y click para enlaces, de manera que se puede confirmar la acción asignando el valor lógico true, y cancelarla con false.</p>
<p>Dicho esto, voy a mostrar 2 formas correctas de formulario y enlace (aún sin usar ventanas):</p>
<div class="codigo">
<pre>Enlace:
&lt;a
	href="destino.html"
	onclick="return confirm('Desea enlazar con:\n' + this.href)"&gt;
	...
&lt;/a&gt;
Formulario:
&lt;form
	action="destino.html"
	onsubmit="return confirm('Desea enviar formulario a:\n' + this.action)"&gt;
	...
&lt;/form&gt;
</pre>
</div>
<p>Nótese la similitud de los dos ejemplos&#8230; y si a ambos le añadimos un atributo target arbitrario: target=&#8221;popup&#8221;,  seguirá teniendo la misma similitud: un enlace que se confirma (también podría validarse) con una función asociada al manejador de evento onclick, y un formulario que igualmente se confirma con su evento asociado (submit).</p>
<p>La verdad es que la confirmación la podemos omitir y en su lugar, ¿qué pasaría si abriésemos una ventana<br />
en blanco, de nombre popup&#8230;? Recuérdese que hemos puesto un atributo target=&#8221;popup&#8221;&#8230;
</p>
<div class="codigo">
<pre>
Enlace:
&lt;a
	href="destino.html"
	target="popup"
	onclick="window.open('', 'popup', 'width = 200, height = 100')"&gt;
	...
&lt;/a&gt;

Formulario:
&lt;form
	action="destino.html"
	target="popup"
	onsubmit="window.open('', 'popup', 'width = 200, height = 100')"&gt;
	...
&lt;/form&gt;</pre>
</div>
<p>Cuando se activa el enlace (click), antes de enlazar se chequea el evento asociado por si hubiese que validar/confirmar, pero en vez de eso está la orden de abrir la ventana popup&#8230; sin URL. Entonces se abre esa ventana y luego se enlaza, pero al tener definido el atributo target, ese enlace se hace a una ventana que debe llamarse popup, y como es parte del juego de ventanas activas, allí se realiza. Con el formulario el razonamiento es el mismo. </p>
<h3>Una última observación </h3>
<p>Otra cosa que no hemos considerado es el bloqueo de ventanas emergentes desde la configuración de los navegadores. Si bien en estos casos algunos navegadores abren una ventana nueva, la verdad es que no debería ser así&#8230;</p>
<p>Con los siguientes códigos para enlazar: </p>
<div class="codigo">
<pre>&lt;a
	href="index.php"
	target="v"
	onclick="window.open('', 'v', 'width=300,height=200');" &gt;
	...
&lt;/a&gt;

&lt;a
	href="index.php"
	target="v"
	onclick="window.open(this.href, this.target, 'width=300,height=200'); return false" &gt;
	...
&lt;/a&gt;</pre>
</div>
<p>probados en los navegadores: &#8220;explorer&#8221;, &#8220;mozilla&#8221; y &#8220;opera&#8221;, se han abierto correctamente las ventanas en los dos primeros, pero en el tercero la ventana fue bloqueada con ambos códigos, pero solo a enlazado en la ventana activa el código sin cancelación (primero). Supongo que este último comportamiento es el correcto cuando se bloquean los popups (lamento no disponer de todos los navegadores para hacer pruebas). </p>
<p>Y teniendo javascript desactivado (otra de las posibilidades que ofrecen los navegadores), ambos códigos<br />
también funcionan correctamente.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.maestrosdelweb.com/editorial/formenlaces/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
