logoApuntes agrupados: Programación Ajax


Programación Ajax (ajax): Se encontraron 8 apuntes:

  1. ¡Mitología!, ¡Fútbol!, ¡Web!...
  2. Ajax accesible
  3. Ajax, con X de XML
  4. Top 10 con Ajax (paginación)
  5. Formularios y Ajax
  6. SVG vs. Ajax
  7. Subir archivos con Ajax
  8. Ajax para copiar ficheros


Titulo: ¡Mitología!, ¡Fútbol!, ¡Web!...


emoticón de Caricatos Publicado el día 12 de marzo de 2011
id=19

¡Sí!, los que vieron el título y pensaron en Ajax, han acertado, pero voy a descartar las opciones de hacer apuntes sobre temas mitológicos o de fútbol (al menos en esta ocasión). La verdad es que aún siendo una técnica bastante antigua para obtener cierto dinamismo en las páginas, el uso del método javascript XMLHttpRequest ha sido una auténtica revolución. Simplemente tenemos que crear un objeto Ajax, yo lo hago así:

function objetoAjax()	{
	if (window.XMLHttpRequest)
		_ajax = new XMLHttpRequest();
	else
		if (window.ActiveXObject)
			_ajax = new ActiveXObject("Microsoft.XMLHTTP");
		else
			_ajax = false;
	return _ajax;
}

Pero no vayan a pensar que este apunte se debe a un especial interés en mostrar este pequeño código. En mi condición de moderador de Ajax en los foros del web, he encontrado una serie de malos hábitos, y por ello la intención es dar unos pocos consejos.

Usar Ajax debería ser una ayuda a la navegación, recogiendo pocos datos y actualizados; pero existe una tendencia preocupante de cargar páginas completas, posiblemente sin considerar algunas cosas básicas.

Algunos puntos será mejor matizarlos.

Algunos Matices

Empecemos por el primer punto de la lista:

Messi

Desactivando javascript se elimina todo tipo de posible navegación del sitio: Este punto se puede matizar, incluso con un ejemplo: Publicaciones (mlggb.com). En el enlace se puede apreciar que pinchando sobre las portadas se abre una ficha descriptiva de la publicación donde mediante Ajax se obtienen los datos de cada ficha, y se genera una ventana simulada con una capa para mostrarlos. Pero si se desactiva javascript (o sin hacerlo, pero abriendo el enlace), El enlace es hacia esa misma ficha.

Posible duplicidad de elementos que deberían ser únicos: No solo los elementos de la página que deben ser únicos como "html, head, body", sino cabeceras, títulos, etc.

Difícil posicionamiento en los buscadores: Tal vez este punto sea el que más nos haga reflexionar. Elementos como títulos y palabras clave, que tienen mucha relevancia para los buscadores, dejarían de ser fiables y tal vez penalizables, con la consecuencia de una mala indexación y por lo tanto una mala ubicación en los mismos.

Malabarismos innecesarios en el uso de scripts: No deberíamos olvidarnos de cambiar el título de la página, o cambiar de pestaña. O para evitar duplicados, cambiar el nombre de algunos identificadores únicos. Muchas veces inicializamos datos al cargarse la página, evento distinto es recibir datos con Ajax, así que si deben inicializarse datos, debemos tenerlo presente (Es una pregunta bastante frecuente en los foros). Además, si tenemos valores inicializados que luego reemplazamos (el típico uso de innerHTML), ese trabajo o gasto de recursos se desperdicia.

Horrores semánticos en Metadatos, titulos, etc.: También dificulta el posicionamiento en los buscadores. Supongamos que desde la página principal cargamos un formulario de contacto, el título que podemos pensar para esa página es justamente ese "formulario...", y podemos hacer visible ese nuevo título, incluso en el mismo navegador (document.title), pero la referencia que tienen los buscadores siempre será el primero que detecte; o sea el título original. Lo mismo pasa con todos los elementos descriptivos (metas: description, keywords, etc.)

... Y más...: Algo que ocurre cada vez que se carga toda una página con Ajax, es que el tráfico de datos va a ser el mismo que si simplemente enlazamos a otra página... Creo que es algo digno de reflexión.

Mis recomendaciones

Basado en mi experiencia planteo estos consejos: Antes de querer usar Ajax para recoger datos debemos comprobar que esos datos se obtienen con enlaces normales, como se aprecia en el enlace antes mencionado. Por ejemplo:

<a id="ejemplo" href="enlace.html" onclick="buscarConAjax(this.id); return false" >enlace</a>

En negro tenemos algo que debe funcionar sin lo que está en rojo, y luego podemos añadir justamente lo que mostramos en rojo (no desarrollaremos la petición ni discutiremos la razón y tipo de argumentos, ya que para entrar en este asunto, implica unos conocimientos básicos).

Otra recomendación es evitar el envío de datos con el objeto Ajax. Si se puede considerar Ajax enviar formularios a un iframe (tal vez oculto), es mucho mejor usar esa técnica. Un ejemplo sencillo es intentar enviar algunos caracteres especiales, un simple espacio en blanco debe codificarse de forma especial y se hace automáticamente con funciones especiales como escape, generando algo del estilo %20, pero en el servidor, si se trabaja con php el espacio se considera con el signo "+", o sea que tenemos que atinar bien en la forma de codificar esas cosas... y si el signo es "&" (ampersand), si no se codifica es un separador de variables. En resúmen, un lío.






Titulo: Ajax accesible


emoticón de Caricatos Publicado el día 11 de octubre de 2011
id=45

accesibilidad Cuando leo los problemas que plantean los usuarios de los foros, y sus códigos, encuentro que raras veces se preocupan que esos códigos sirvan aún con javascript desactivado en los navegadores. Tenemos en este diario un ejemplo de Ajax accesible en el sistema de valoración con estrellitas doradas: Este diario: Valorar contenido.

Empezando por el principio

Nos limitaremos a explicar el sistema en cuestión (nuestro sistema de valoración), donde en un recuadro tenemos un simple formulario con unas estrellitas, un control "select" y un botón con el texto "Valorar" escrito en él. Si urgamos en el código, encontramos también un campo oculto con el nombre de la página (en este caso pagina.45); el formulario tiene el método get, y va dirigido a una página externa cuyo nombre no viene al caso, pero sí su contenido que detallaremos más adelante.

No se encuentra ningún tratamiento de eventos, o sea que si no se dispone de la oportuna inicialización javascript, al presionar el botón de tipo submit "Valorar", se enviará el contenido al destino cuyo código (en realidad mostraremos algunas partes) vemos a continuación:

<?php
	session_start();
	$ajax = isset($_POST["ajax"]);
	$pagina = $_GET["pagina"];
	$soy = $_SESSION["soy"];
	$valor = $_GET["valor"];
	$hay_valor = (isset($_GET[valor]) && ($_GET["valor"] > "0"));
	$vale = ($hay_valor && ($pagina == $soy));
	$volver = $_SERVER[HTTP_REFERER];
//?>

Vemos en estas pocas líneas del principio de la página receptora de la valoración que hay una variable "$ajax" que se envía por el método "post", junto a las dos variables que están en el formulario original; en otra variable guardamos la página origen de la valoración, y una gestión de variables de sesión que comentaremos a continuación.

Intentando evitar mamarrachadas

Hemos visto que los valores se envían por el método "get" o línea de comandos, lo que significa que si desde otra página externa ponen la dirección de la página receptora con los valores que a cada uno les dé la gana, el sistema de seguridad sería vulnerado y eso no nos interesa. Podrían incluso usar enlaces o peticiones Ajax ocultas ajenas a esta página... ponemos un ejemplo de un enlace para dar valoracióon escasa al index: Dar valor 5 al index. Si activamos el enlace veremos un mensaje de valoración incorrecta, ya que no coinciden la variable de sesión con la página referenciada, pero si podríamos modificar la valoración de este mismo apunte con el siguiente enlace: Poner valoración "Sobresaliente".

Ya chequeada la validez de los parámetros (variable $vale), podemos consultar nuestra tabla en la base de datos previa obtención de la IP del ordenador remoto:

$ip = $_SERVER["REMOTE_ADDR"];
$sql = "select valor from $tabla_valores where pagina='$soy' and ip='$ip'";

Con esta consulta, las acciones que realizaremos dependerá de la respuesta para hacer una inserción, o una modificación o nada (junto a los respectivos mensajes).

Aún no hemos comentado nada sobre Ajax, simplemente porque antes de programar una petición Ajax, nuestra recomendación es que debemos controlar que todo funcione correctamente sin el uso de javascript.

Y ahora, ¡AJAX!

Habíamos dejado en el aire el sentido de la variable que encontramos con el método "post"; pues justamente en este caso se usa para la discriminación de la petición ajax, o sea usando javascript.

Sabiendo como crear un objeto Ajax (véase el apunte "¡Mitología!, ¡Fútbol!, ¡Web!..."), debemos realizar esa llamada programando el evento submit del formulario, y luego cancelar ese evento:

function tag(id)	{return document.getElementById(id);}
function poner_evento(elemento, evento, f)	{
	if (document.addEventListener)
		elemento.addEventListener(evento, f, true);
	else
		if (document.attachEvent)
			elemento.attachEvent("on" + evento, f);
		else
			elemento["on" + evento] = f;
}

window.onload = function()	{
	// inicializamos otros eventos en otros elementos...
	poner_evento(tag("evaluar"), "submit", evaluar_con_Ajax);
}

function evaluar_con_Ajax(e)	{
	f = this;
	if (f.valor.value == "0")	{
		respuesta = "No ha hecho ninguna valoración...";
		tag("mensaje_respuesta_valorador").innerHTML = respuesta;
	}
	else	{
		url = f.action + "?pagina=" + f.pagina.value + "&valor=" + f.valor.value;
		Ajax = objetoAjax();
		params = "ajax=si";
		Ajax.open("POST", url, true);
		Ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
		Ajax.onreadystatechange = function()	{
			if(Ajax.readyState == 4 && Ajax.status == 200) {
				nueva_imagen = "diario.estrellas.php?pagina=" + f.pagina.value + "&fantasma=" + Math.random();
				tag("valorada").src = nueva_imagen;
				respuesta = Ajax.responseXML.getElementsByTagName("error")[0].firstChild.data;
				tag("mensaje_respuesta_valorador").innerHTML = respuesta;
			}
		}
		Ajax.send(params);
	}
	cancelar_evento(e);
}

function cancelar_evento(e) {
	if (!e) e = window.event;
	if (e.preventDefault)	{
		e.preventDefault();
	}
	else	{
		e.returnValue = false;
	}
}

En el código hemos omitido lo referente a la modificación de las estrella, pero siempre se puede ver el código fuente de la página.

Resumiendo lo visto, la petición Ajax se hace por el método "post", pero los datos de la valoración siguen enviándose por "get", así entre otras cosas evitamos complicar el código con dos gestiones distintas según el método... y ahora solo nos queda mostrar el uso de la variable discriminante:

if ($ajax)	{
	header("Content-type: text/xml");
	echo <<< xml
	// aquí el código xml (con Ajax)
xml;
}
else	{
	header("Content-type: text/html");
	echo <<< html
	// aquí el código html (sin Ajax)
html;
}

Solo nos queda comentar que aquella variable "$volver" que omitimos comentar, simplemente se aprovecha para volver (vaya la redundancia) a la página valorada en el código que no usa AJAX.






Titulo: Ajax, con X de XML


emoticón de Caricatos Publicado el día 08 de mayo de 2012
id=85

Mundo Hace algunos días me preguntaron en los foros del web si tenía un ejemplo simple de lectura de datos estructurados XML con Ajax...

... después de revisar mis códigos, he encontrado muchas rutinas con esa tecnología, pero de una complejidad que no creí correcto referenciar, así que se me ocurrió hacer algo nuevo que pueda usar en esta página. La conclusión ha sido crear un sistema que despliegue la lista de apuntes del sector "Archivos", a la derecha de este diario.

Preliminares

Viendo el código fuente de la página, descubrimos que se trata de una lista desordenada "ul" (unordered list) y en cada item "li" (list item) el enlace del tipo "?archivos=mayo+2012", y al pinchar nos lleva a la lista correspondiente, pero podríamos simplemente mostrar otra lista de los títulos asociados desplegándola debajo.

Para que sea XML hemos pensado que podría tener una estructura como los ficheros RSS y de esa manera conseguir que sea visible fácilmente usando la hoja XSL que ya teníamos hecha para nuestro sistema de sindicación.

Vamos a dejar de lado tantas siglas y enlazamos al fichero resultante de este mes. Aunque todos nuestros códigos están accesibles en nuestros listados, a continuación mostramos el que hemos usado para nuestro propósito:

$aaaa = $_GET["a"];
$mm = $_GET["m"];
header("Content-type: text/xml");
	ob_start();
	echo <<< cabecera
<?xml version="1.0" encoding="ISO-8859-1" ?>
<?xml-stylesheet type="text/xsl" href="diario.rss.xsl" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<atom:link href="$diario_ruta/diario.rss.xml" rel="self" type="application/rss+xml" />
<title>$diario_titulo: extras</title>
<link>{$_SERVER[PHP_SELF]}?extra=extras_xml</link>
<description>$diario_titulo</description>

cabecera;
$cabeza = ob_get_clean();

$sql = "select titulo, apunte from $tabla_apuntes where activo > 0 and fecha like '$aaaa-$mm%' order by fecha desc";
$listado = array();
$res = @mysql_query($sql);
$cuenta = mysql_num_rows($res);
while ($dato = mysql_fetch_array($res))	{
	$titulo = $dato["titulo"];
	$link = $diario."?titulo=".urlencode($titulo);
	preg_match('/\[rss\](.*?)\[\/rss\]/is', $dato["apunte"], $des);
	array_push($listado, "\n<item>\n<title>$titulo</title>\n<link>$link</link>\n<description>{$des[1]}</description>\n</item>\n");
}
$lista = implode("\n", $listado);

echo $cabeza.$lista."\n</channel>\n</rss>";

Para que sea más fácil nuestro propósito con el lenguaje javascript hemos modificado los enlaces añadiendo un atributo "id" del tipo "archivos_aaaa_mm", como por ejemplo: id="archivos_2012_05" para el enlace del mes de mayo de este año 2012.

Código no intrusivo

Para que sea inapreciable el arreglo hemos añadido el código después de cargarse la página. No obstante los enlaces seguirán siendo funcionales, así que mientras no se hayan cargado todos los elementos de la página serán los de siempre, y cuando se cargue el código, los enlaces desplegarán una lista con las referencias asociadas.

var lista_archivos = new Object();
function enlace_archivo_ajax(e)	{
	archivos = this;
	archivos_id = archivos.id;
	desglose_id = archivos.id.split("_");
	mes = desglose_id.pop();
	año = desglose_id.pop();
	id_archivos = "desglose_" + mes + "_" + año;
	if (lista_archivos[id_archivos] == undefined)	{
		lista_archivos[id_archivos] = [];
		lista_archivos[id_archivos]["visible"] = true;
		nueva_espera = document.createElement("img");
		nueva_espera.src = "diario/dibujos/espera.gif";
		tag(archivos_id).parentNode.appendChild(nueva_espera);
		url = "diario.jocker.php?extra=archivos&a=" + año + "&m=" + mes;
		Ajax = objetoAjax();
		Ajax.open("get", url, true);
		Ajax.onreadystatechange = function()	{
			if	(Ajax.readyState == 4 && Ajax.status == 200) {
				nueva_capa = document.createElement("ul");
				nueva_capa.id = id_archivos;
				nueva_capa.className = "enlaces";
				tag(archivos_id).parentNode.appendChild(nueva_capa);
				respuesta = Ajax.responseXML.documentElement;
				items = respuesta.getElementsByTagName("item");
				for (i = 0, total = items.length; i < total; i++)	{
					el_enlace = items[i].getElementsByTagName("link")[0].firstChild.nodeValue;
					el_titulo = items[i].getElementsByTagName("title")[0].firstChild.nodeValue;
					la_desc = (items[i].getElementsByTagName("description")[0].hasChildNodes()) ?
						items[i].getElementsByTagName("description")[0].firstChild.nodeValue: "sin descripción";
					nuevo_li = document.createElement("li");
					nuevo_enlace = document.createElement("a");
					nuevo_enlace.href = el_enlace;
					nuevo_enlace.setAttribute("title", la_desc);
					nuevo_enlace.appendChild(document.createTextNode(el_titulo));
					nuevo_li.appendChild(nuevo_enlace);
					nueva_capa.appendChild(nuevo_li);
				};
				tag(archivos_id).parentNode.removeChild(nueva_espera);
			}
		}
		Ajax.send();
	}
	else	{
		tag(id_archivos).style.display = (lista_archivos[id_archivos]["visible"]) ? "none":"block";
		lista_archivos[id_archivos]["visible"] = !lista_archivos[id_archivos]["visible"];
	}
	cancelar_evento(e);
}

Aunque pueda parecer mucho código, la parte "Ajax" es bastante sencilla: se lee el fichero XML/RSS correspondiente al enlace pinchado y se genera la lista desordenada con sus enlaces asociados. Los mismos quedan resumimos en la siguiente lista:

Por cada item de la lista se obtienen los datos: "title", "link" y "description" que usaremos al desplegar la lista (title es el texto que se muestra, link el enlace y description el atributo title).

Evitando redundancias

Otra parte fundamental del código y tal vez la razón de su extensión, es la que evita realizar más de una vez una misma consulta. Cuando se despliega una lista, se puede plegar pinchando sobre el mismo enlace, pero si volvemos a querer desplegarla simplemente se muestra lo que anteriormente se había ocultado; considerando que es casi imposible que se realizaran cambios en los enlaces de cada lista, no tienen ningún sentido volver a leer los datos ya leídos en la misma sesión (un vicio bastante común).






Titulo: Top 10 con Ajax (paginación)


emoticón de Caricatos Publicado el día 27 de mayo de 2012
id=86

Últimamente hemos modificado la página para mostrar los apuntes creados cada mes en la sección archivos, por lo que la sección "Últimos apuntes" tiene ahora poco sentido mantenerla. Por otro lado, en otro apunte hemos mostrado los 10 apuntes más leídos del diario, y hemos pensado que es lo que podría sustituir la sección antes mencionada.

Nos basaremos en la misma instrucción sql:

$sql = "select a.titulo as tit, a.id as idd, b.cuenta as cuen from $tabla_apuntes as a inner join $tabla_contadores as b on concat('apunte.', a.id)=b.pagina order by b.cuenta desc limit 0, 10";

Donde recibimos los diez apuntes más leídos junto a su id (identificador) y el número de veces leído.

Después de "cortar y pegar"...

Evidentemente tal como hemos hecho para mostrar la instrucción sql (copiar y pegar... seguro que lo habían adivinado), reutilizaremos esa instrucción, pero con pequeñas modificaciones.

Al tratarse de una paginación, esa instrucción solo tendría sentido para la primera página, pero tendrá que haber más, y las páginas deberán ser del tipo pag=n. Entonces la línea sql deberá estar limitada por una variable: "limit $inicio, 10"... o mejor "limit $inicio, $cuantas"; y para recibir los parámetros se nos ocurre que deberá ser así:

$ini = (isset($_GET["pag"])) ? $_GET["pag"] - 1 : 0;
$cuantas = (isset($_GET["cuantos"])) ? $_GET["cuantos"] : 10;
$inicio = $ini * $cuantas;
if ($inicio < 0)	$inicio = 0;

Otra modificación que hemos realizado es obtener el resumen al igual que hemos hecho con el apunte anterior. Tan solo falta saber cuántas páginas habrá, o aún mejor, cuántos apuntes... ¡Ya tenemos dos motivos para realizar consultas "Ajax"!

A continuación reservamos el espacio para nuestro propósito: una capa para el listado y abajo un pequeño menú de navegación con las páginas disponibles.

Listado de los apuntes más leídos. Página: 0 de ... (... apuntes)

La primera consulta, al cargarse la página, es averiguar cuantos apuntes tenemos y la instrucción sería:

	$sql = "select count(*) as total from $tabla_apuntes where activo='1'";
	$res = @mysql_query($sql);
	$total = mysql_result($res, 0, "total");
	echo $total;

Después de obtener ese dato (el número de apuntes) obtenemos la primera de las páginas y concluímos con los ajustes finales.

Últimos ajustes

Tan solo nos queda revisar detalles secundarios pero no menos importantes como las actualizaciones en los elementos que indican dónde estamos, ya sea enfatizando el vínculo actual (en nuestro caso hemos incrementado el tamaño de la letra/número), o actualizando ese valor en la zona informativa.






Titulo: Formularios y Ajax


emoticón de Caricatos Publicado el día 01 de agosto de 2012
id=92

Después de integrar un sistema para editar y borrar mensajes en nuestro libro de visitas nos encontramos en la necesidad de evitar cambiar de página por cada nueva modificación.

Inicialmente teníamos una advertencia antes de enviar las modificaciones, pero no hacíamos nada más que cancelar el envío según la respuesta:

function modificar(que)	{
	acto = (acto_form == 0) ? "borrar":"modificar";
	sitio = que.id.substr(2);
	return confirm("seguro que quiere " + acto + " el mensaje " + sitio);
}
var acto_form;

Fieles a nuestras recomendaciones, debemos poder navegar perfectamente sin javascript (descativándolo), y así sucede, porque para lo único que lo usábamos era para mostrar una advertencia. Es el momento de añadirle a nuestro sistema inicial las modificaciones necesarias para nuestro objetivo... ¡que tal si españolizamos nuestra alerta!:

return confirmar(que);

Nos queda el tratamiento con Ajax...

Confirmación y ejecución

La misma confirmación ahora debemos condicionarla, y en todo caso cancelar el evento de envío (submit). Ahora las pocas líneas de nuestro sistema de confirmación con la modificación mencionada las moveremos a la nueva función:

function confirmar(que)	{
	acto = (acto_form == 0) ? "borrar":"modificar";
	sitio = que.id.substr(2);
	if (confirm("seguro que quiere " + acto + " el mensaje " + sitio))	{
		params = ["acto=" + acto];
		params.push("sitio=" + sitio);
		if (acto == "modificar")	{
			activo = (que.activo.checked) ? "on":"off";
			params.push("activo=" + activo);
			params.push("nombre=" + escape(que.nombre.value));
			params.push("desde=" + escape(que.desde.value));
			params.push("Email=" + escape(que.Email.value));
			params.push("URL=" + escape(que.URL.value));
			params.push("comentario=" + escape(que.comentario.value));
		}
		Ajax = objetoAjax();
		url = que.action;
		Ajax.open("post", url, true);
		Ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
		Ajax.onreadystatechange = function()	{
			if	(Ajax.readyState == 4 && Ajax.status == 200) {
				// Aquí procesamos la respuesta Ajax
			}
		}
		Ajax.send(params.join("&"));
	}
	return false;
}

Antes de explicar la "respuesta Ajax" podemos ver que pasamos siempre el sitio (equivale al id[entificador]) y el botón que se ha pulsado; y si se tratase del botón "modificar" pasamos el resto de los datos (innecesarios en el caso de pulsar el botón "borrar").

De la respuesta solo nos interesa que se han recibido los datos, así que simplemente obtenemos el código de color, y según ese valor actualizamos el mensaje. Con el rojo eliminamos el mensaje (en nuestro caso cambiamos su color), y en el servidor generamos una transacción "delete" en la base de datos. El código negro significa que lo hemos desactivado, y mostramos el mensaje con opacidad; y ya sea negro o azul, modificamos el mensaje con los cambios realizados.

Aunque aquí no mostremos el código de la respuesta, siempre será posible consultarlo desde la propia página.

Algunas conclusiones

Podríamos echar en falta un sistema para procesar varios mensajes a la vez, por ejemplo cuando simplemente queremos borrarlos o desactivarlos, pero para esos casos con el sistema actual solamente debemos hacer unas pocas pulsaciones, así que por el momento es innecesario.

Es de destacar que el fichero que procesa cada formulario en el servidor es el mismo que tenemos para ese cometido sin usar Ajax.






Titulo: SVG vs. Ajax


emoticón de Caricatos Publicado el día 01 de junio de 2014
id=136

Después de añadir a nuestro Mapa de España las ciudades autónomas de Ceuta y Melilla hemos hecho algunas reflexiones:

A pesar de que nos ha sido de mucha utilidad el mapa usado, tuvimos que añadir Ceuta y Melilla de manera "muy artesanal", cuando existen otros mapas con sus coordenadas mucho más precisas. También notamos la ausencia del resto del continente europeo, aparentando ser una gran isla, y no un país integrado en su continente.

Intentaremos saber si nuestro navegador permite el formato svg simplemente cargando la imagen que vamos a usar, y que se encuentra en la wikipedia: Provincias de España.svg. Si se carga correctamente podemos crear una imagen nueva basándones en las características de la recientemente cargada

Pinchando sobre el botón que acompaña este párrafo (si todo va bien) realizaremos una petición Ajax para obtener los datos básicos de la etiqueta svg, junto a las distintas etiquetas "path" y "polygon" para dibujar sus siluetas. No olvidemos que los ficheros SVG son también XML (responseXML).

Antes de analizar los resultados, vemos el código que hemos usado:

svgns = "http://www.w3.org/2000/svg";
_colores_ = ["red", "lime", "blue", "green", "aqua"];
_color_ = 0;
function _obtener_tags_svg_(url, donde) {
	ajax = objetoAjax();
	ajax.open("get", url, true);
	ajax.onreadystatechange = function()	{
		if (ajax.readyState == 4) {
			resultado = ajax.responseXML;

			// elemento raíz

			_svg_ = resultado.getElementsByTagName("svg")[0];
			xmlns = _svg_.getAttribute("xmlns");
			ancho = _svg_.getAttribute("width");
			alto = _svg_.getAttribute("height");
			box = _svg_.getAttribute("viewBox");

			_imagen_ = document.createElementNS(svgns, "svg");
			_imagen_.setAttribute("xmlns", xmlns);
			_imagen_.setAttribute("width", ancho);
			_imagen_.setAttribute("height", alto);
			_imagen_.setAttribute("viewBox", box);
			_imagen_.style.border = "1px solid black";
			tag(donde).appendChild(_imagen_);

			// buscando formas (polygon, path)

			_tags_ = resultado.getElementsByTagName("*");
			for (i = 0, total = _tags_.length; i < total; i++)	{
				switch(_tags_[i].tagName.toLowerCase())	{
					case "polygon":
						_puntos_ = _tags_[i].getAttributeNS(null, "points");
						_figura_ = document.createElementNS(svgns, "polygon");
						_figura_.setAttributeNS(null, "points", _puntos_);
						_figura_.setAttributeNS(null, "stroke", _colores_[(_color_++ % _colores_.length)]);
						_figura_.setAttributeNS(null, "stroke-width", "1");
						_figura_.setAttributeNS(null, "fill", "none");
						_imagen_.appendChild(_figura_);
					break;

					case "path":
						_path_ = _tags_[i].getAttributeNS(null, "d");
						_figura_ = document.createElementNS(svgns, "path");
						_figura_.setAttributeNS(null, "d", _path_);
						_figura_.setAttributeNS(null, "stroke", _colores_[(_color_++ % _colores_.length)]);
						_figura_.setAttributeNS(null, "stroke-width", "1");
						_figura_.setAttributeNS(null, "fill", "none");
						_imagen_.appendChild(_figura_);
					break;
				}// switch
			}// for
		}
	}
	ajax.send(null);
}

A partir del resultado que vemos, sabiendo que solo hemos añadido siluetas, nos resulta raro encontrarnos con textos. Evidentemente se han insertado con polígonos o recorridos (path). Podríamos reconocerlos y eliminarlos, pero al ver el resto de las siluetas, encontramos algunas líneas incorrectas, así que buscaremos otros mapas que nos puedan interesar más.

Otros Mapas

Haciendo una búsqueda en la Wikipedia, hemos encontrado otros mapas que mostramos a continuación; Pulsando sobre cada uno de ellos se mostrarán las siluetas de sus formas en el "Espacio para mostrar otro mapa":

http://upload.wikimedia.org/wikipedia/commons/6/61/Provincias_de_Espa%C3%B1a_centrado.svg http://upload.wikimedia.org/wikipedia/commons/e/e8/Provincias_de_Espa%C3%B1a_%28an%29.svg http://upload.wikimedia.org/wikipedia/commons/3/35/Prov%C3%ADncies_d%27Espanya.svg

Espacio para mostrar otro mapa

Si todo ha ido bien y podemos ver las diferencias en las siluetas, nos decantaremos por el tercero de los mapas, que en un futuro apunte trataremos de estudiar más a fondo.






Titulo: Subir archivos con Ajax


emoticón de Caricatos Publicado el día 01 de julio de 2014
id=137

Hasta hace poco, la forma de subir archivos era a través del envío de un formulario, y se podía "simular" el uso de la tecnología "Ajax" dirigiendo el resultado a un iframe (oculto o no), como hacíamos en este artículo: Revisar las imágenes antes de subirlas.

Con el nivel 2 del objeto XMLHttpRequest y los objetos FormData se puede lograr subir ficheros sin tener que pulsar el botón destinado al envío de un formulario.

Usando el evento de cambio de estado de un control file vamos a subir el fichero que elijamos. Por el asunto de la accesibilidad usaremos un formulario con su botón de envío, pero "maquillado" en etiquetas "noscript":

<form action="recibir.php" method="post" enctype="multipart/form-data" id="formulario">
	<label for="fichero">
		Fichero que se enviará:
	</label>
	<input type="file" name="fichero" id="fichero"/>
	<noscript>
		<button type="submit">
			Enviar Archivo
		</button>
	</noscript>
</form>

La función Ajax para subir el fichero y que asociaremos al evento de cambio del control "fichero" llevará estas líneas:

function tag(id) {return document.getElementById(id);};
function subir_con_Ajax()	{
	fd = new FormData(tag("formulario"));
	Ajax = new XMLHttpRequest();
	Ajax.open("POST", tag("formulario").action, true);
	Ajax.onreadystatechange = function() {
		if	(Ajax.readyState == 4 && Ajax.status == 200) {
			alert(Ajax.responseText);
		}
	}
	Ajax.send(fd);
}

Con este sencillo código en nuestra página y unas pocas líneas de código en el fichero que procese el formulario en el servidor, ya podemos subir nuestros ficheros seleccionados.






Titulo: Ajax para copiar ficheros


emoticón de Caricatos Publicado el día 12 de julio de 2014
id=138

Hemos visto como subir archivos con Ajax, donde contábamos de un formulario y un control para seleccionar ficheros, pero cómo lo haríamos sin esa selección...

No se me ocurre otra razón para este cometido que las funciones administrativas de una web, pero si existiesen otras, con este apunte veremos cómo lograrlo.

Supongamos que nuestra intención es copiar nuestro logo (logo.png) que se encuentra en la raiz del dominio, a la carpeta "/ficheros". Tenemos que tener el mismo formulario y el mismo control "file" indicados en el anteriormente citado apunte, pero podemos tenerlo oculto, así que nos valdremos de la ruta de la imagen.

El código que hemos asociado a un elemento de la página para nuestro objetivo es el siguiente:

var logo;
function copiar()	{
	Ajax_1 = new XMLHttpRequest();
	Ajax_1.open('GET', tag("imagen").src, true);
	Ajax_1.responseType = "blob";
	Ajax_1.onload = function() {
		if (Ajax_1.status == 200) {
			logo = this.response;
			blob = new Blob([logo]);
			fd = new FormData(tag("prueba"));
			fd.append("fichero", blob, tag("imagen").src.substr(tag("imagen").src.lastIndexOf("/") + 1));
			Ajax_2 = new XMLHttpRequest();
			Ajax_2.open("POST", tag("prueba").action, true);
			Ajax_2.onreadystatechange = function()	{
				if	(Ajax_2.readyState == 4 && Ajax_2.status == 200) {
					tag("respuesta").innerHTML = Ajax_2.responseText;
				}
			}
			Ajax_2.send(fd);
		};
	};
	Ajax_1.send();
}

Encontramos algunas cosas nuevas que comentaremos a continuación.

Novedades

Esperar una respuesta Ajax de un fichero sin parámetros es normal, pero habitualmente esperamos texto plano o con formato xml, pero en este caso esperamos una imagen, así que hemos tenido que definir un nuevo atributo para nosostros: Ajax.responseType, indicando el tipo de datos "blob". Tampoco nos serviría las respuestas más habituales: "responseText" y "responseXML", pero sí nos sirve "response" (a secas).

Teniendo la respuesta en la variable "logo", tenemos que crear un objeto del tipo "Blob" con los datos recogidos, y asignarlo al control del formulario con la instrucción append.

Suponiendo que la respuesta del fichero que procesa el envío mediante Ajax tan solo muestre la variable $_FILES

print_r($_FILES);

la respuesta obtenida es:

Array
(
    [fichero] => Array
        (
            [name] => logo.png
            [type] => application/octet-stream
            [tmp_name] => http://www.pepemolina.com/XXXXXXX.tmp
            [error] => 0
            [size] => 3500
        )
)

El código que nos falta es una comprobación de la existencia del fichero y la correspondiente copia:

move_uploaded_file($_FILES["fichero"]["tmp_name"], "ficheros/".$_FILES["fichero"]["name"]);

Esperamos que sea de utilidad.



Zona de comentarios

Esto grupo aún no tiene comentarios.

Evaluación

Valoración de esta página: (grupo.ajax) valor

Valoración evaluar evaluar evaluar evaluar evaluar evaluar evaluar evaluar evaluar evaluar

Respuesta: Zona de mensajes (proceso de evaluación)

Copyright © 2002-2024 www.pepemolina.com
RSS rss | Ver Mapa del sitio