Links 27-02-2007

0 COMENTARIOS -  Publicado hace 37 meses -  Clasificado en: , ,

 

  • MiniAjax.com es una ventana desde la que se nos muestran algunos de los mejores y sencillos scripts de AJAX y DHTML.

 

 

  • Guías Prácticas para Profesionales Web: Buenas Prácticas en Web Móvil. Traducción del documento de la W3c "Mobile Web Best Practices 1.0" que intenta sentar las bases de un desarrollo web eficaz sobre dispositivos móviles. Son una serie de consejos que tratan de ofrecer pautas y directrices que ayuden a los desarrolladores Web a proporcionar una mejor experiencia a los usuarios de dispositivos móviles.

 

  • Clutter Free es un plugin para WordPress que permite ocultar completamente algunos de los paneles de administración que nunca utilizamos, mejorando el espacio visual de nuestro entorno de administración.

Algunas entradas relacionadas:

 

Cross-domain Ajax con Flash

0 COMENTARIOS -  Publicado hace 39 meses -  Clasificado en: , ,

Interesante tutorial sobre como hacer cross-domain con AJAX mediante flash. La anotación está en inglés pero aborda una de las posibilidades para hacer peticiones Ajax entre dominios sin tener que utilizar JSON.

 

Crear una navegación por pestañas con AJAX y CSS. Segunda Parte

3 COMENTARIOS -  Publicado hace 40 meses -  Clasificado en: , ,

Continuación del tutorial de ayer. En esta parte vamos a ver la parte AJAX del mismo. Lo primero es crear una nueva istancia del objeto XMLHttpRequest:

var peticion = false; 
if (window.XMLHttpRequest) {
peticion = new XMLHttpRequest();
} else if (window.ActiveXObject) {
peticion = new ActiveXObject("Microsoft.XMLHTTP");
}

Luego necesitamos una función que cargue los datos en el div que le indiquemos.

function ObtenerDatos(datos,divID) { 
if(peticion) {
     var obj = document.getElementById(divID); 
     peticion.open("GET", datos); 
     peticion.onreadystatechange = function()  { 
          if (peticion.readyState == 4) { 
               obj.innerHTML = peticion.responseText; 
          } 
     } 
peticion.send(null); 
}
}

A la función la llamamos desde cada una de las pestañas para que cargue el contenido correspondiente. Le pasamos dos parámetros, los datos que queremos abrir y dónde los queremos abrir. Esta es una función genérica que nos puede servir en muchos casos para cargar datos con AJAX.Así la lista, variaría respecto a como nos quedamos en el tutorial anterior y quedaría del siguiente modo:

<li class="activo" id="bt1"><a href="javascript:ObtenerDatos('1.html','ContTabul');CambiarEstilo('bt1');">Apartado 1</a></li>
<li class="inactivo" id="bt2"><a href="javascript:ObtenerDatos('2.html','ContTabul');CambiarEstilo('bt2');">Apartado 2</a></li>
<li class="inactivo" id="bt3"><a href="javascript:ObtenerDatos('3.html','ContTabul');CambiarEstilo('bt3');">Apartado 3</a></li>
<li class="inactivo" id="bt4"><a href="javascript:ObtenerDatos('4.html','ContTabul');CambiarEstilo('bt4');">Apartado 4</a></li>

En este punto, la navegación ya funciona. Pero si os fijais en el código precedente, vereis que le he asignado un id a cada botón (bt1,b2,bt3,bt4) y a al primero una clase "activo" y al resto "inactivo"

#tabnav .activo {
      border-bottom: 1px solid #fff;
      color: #000000;
      background-color: #FFFFFF;
}
#tabnav .inactivo {}

Esto lo hago para, de un modo similar a un ejemplo anterior, cambiar la clase de los elementos y así siempre marcar el apartado activo. En este caso me apoyo también en una función creada por Jonathan Snook para obtener el elementos que tenga la clase "activo" y pasarlo a "inactivo".

function CambiarEstilo(id) {
var elementosMenu = getElementsByClassName(document, "li", "activo");
for (k = 0; k< elementosMenu.length; k++) {
elementosMenu[k].className = "inactivo";
}
var identity=document.getElementById(id);
identity.className="activo";
}
/*
function getElementsByClassName
Written by Jonathan Snook, http://www.snook.ca/jonathan
Add-ons by Robert Nyman, http://www.robertnyman.com
*/
function getElementsByClassName(oElm, strTagName, strClassName){
var arrElements = (strTagName == "*" && document.all)? document.all : oElm.getElementsByTagName(strTagName);
var arrReturnElements = new Array();
strClassName = strClassName.replace(/\-/g, "\\-");
var oRegExp = new RegExp("(^|\\s)" + strClassName + "(\\s|$)");
var oElement;
for(var i=0; i oElement = arrElements[i];
if(oRegExp.test(oElement.className)){
arrReturnElements.push(oElement);
}
}
return (arrReturnElements)
}

Descargar ejemplo completo »»

Algunas entradas relacionadas:

 

Crear una navegación por pestañas con AJAX y CSS. Primera Parte

0 COMENTARIOS -  Publicado hace 40 meses -  Clasificado en: ,

En esta primera parte se va a crear la arquitectura en CSS y HTML que permitirá cargar los distintos contenidos en una navegación por pestañas o tabs. Para crear una barra de navegación, se puede usar una lista a la que se quitan las viñetas y se cuyos elementos se disponen de modo horizontal gracias a "display:inline". Para dar el aspecto de botones se les asigna un borde y un fondo que cambian cuando se pasa el raton sobre ellos (:hover). También he dispuesto de un contenedor "ContTabul" que será donde se irán cargando los distintos contenidos.Creo que el CSS es bastante claro y, en el caso de que no lo sea, uno siempre puede recurrir a múltiples tutoriales en internet que se enseñan como crear estas pestañas con CSS.

Quizá la unica peculiaridad es la creación de dos clases ("inactivo" y "activo"), que utilizaré y permutaré entre ellas con Ajax para mostrar en cada momento cuál es la pestaña activa. Pero eso lo veremos en la segunda parte del tutorial.

El código para crear una simple navegación por pestañas sería:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>AJAX TABS</title>
<style type="text/css">
body {
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 10px;
background-color: #FFFFFF;
margin-left: 100px;
margin-right: 100px;
}
#ContTabul {
border-left: 1px solid #CCC;
border-right: 1px solid #CCC;
border-bottom: 1px solid #CCC;
padding: 10px 5px 6px 5px;
}
ul#tabnav {
list-style-type: none;
margin: 0;
padding-left: 40px;
padding-bottom: 24px;
border-bottom: 1px solid #CCC;
font: 11px verdana, arial, sans-serif;
}
ul#tabnav li {
float: left;
height: 21px;
background-color: #E4E4E4;
color: #666;
margin: 2px 10px 0 2px;
border: 1px solid #CCC;
}
ul#tabnav a:link, ul#tabnav a:visited {
display: block;
color: #666;
text-decoration: none;
padding: 4px;
}
ul#tabnav a:hover {
background-color: #CCC;
color: #666;
}
#tabnav .activo {
border-bottom: 1px solid #fff;
color: #000000;
background-color: #FFFFFF;
}
#tabnav .inactivo {}
</style>
</head>
<body>
<ul id="tabnav">
<li class="activo"><a href="#">Apartado 1</a></li>
<li class="inactivo"><a href="#">Apartado 2</a></li>
<li class="inactivo"><a href="#">Apartado 3</a></li>
<li class="inactivo"><a href="#">Apartado 4</a></li>
</ul>
<div id="ContTabul">
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Vivamus mollis. Etiam aliquet. Ut ultrices justo ut arcu. Proin a purus. Fusce pharetra ultrices nibh. Nam erat lectus, dapibus id, congue vel, cursus a, tellus. Sed turpis ante, condimentum at, accumsan eget, pulvinar vitae, nibh. </p>
</div>
</body>
</html>

Ver ejemplo en funcionamiento » »

Algunas entradas relacionadas:

 

Comprobar si existe un usuario con AJAX

3 COMENTARIOS -  Publicado hace 41 meses -  Clasificado en: ,

Esta anotación relata un problema, una tentativa de solución y una solución -aunque seguro que no será la única posible-. El post puede ser bastante complejo para aquellos no muy puestos en temas de programación pero creo que puede ser de gran ayuda para aquellos que se hayan encontrado en una situación similar.

PROBLEMA: Quería realizar la comprobación instantanea, a medida que el usuario fuese tecleando su ID, para que éste no estuviera ya tomado por otro usuario.

TENTATIVA 1: Cree dos funciones javascript ObtDatos y compUsuario. Al evento onkeyup lanzamos la función compUsuario que a su vez llama a ObtDatos para cargar un php externo que comprueba la existencia del usuario. La comprobación lógica del usuario sería a partir de una consulta en la base de datos a la tabla oportuna. En el ejemplo esta parte se obvia puesto que la consulta dependería del diseño de la tabla en cuestión.

Así pues tendríamos dos ficheros que podrían tener la siguiente estructura.

validar.html

<script language = "javascript">
var peticion = false;
try{
// Mozilla/Safari
if (window.XMLHttpRequest)
peticion = new XMLHttpRequest();
// IE
else if (window.ActiveXObject)
peticion = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e) {
alert(e);
}
// Error
if(!peticion)
alert("no se pudo crear");
function ObtDatos(url) {
if(peticion) {
peticion.open("GET", url);
peticion.onreadystatechange = function(){
if (peticion.readyState == 4 ) {
if(peticion.responseText == "NO"){
var DivDestino = document.getElementById("DivDestino");
DivDestino.innerHTML = "<div id='error'>El nombre de usuario no está disponible.</div>";
}
}
}
peticion.send(null);
}
}
function compUsuario(Tecla) {
Tecla = (Tecla) ? Tecla: window.event;
input = (Tecla.target) ? Tecla.target :
Tecla.srcElement;
if (Tecla.type == "keyup") {
var DivDestino = document.getElementById("DivDestino");
DivDestino.innerHTML = "<div></div>";
if (input.value) {
ObtDatos("login.php?q=" + input.value);
}
}
}
</script>
Teclea tu Id de usuario:
<input id = "textField" type = "text" name = "IdUsuarui" onkeyup = "compUsuario(event)">
<div id = "DivDestino"><div></div></div>
</body>

login.php

<?php 
// En el caso probable de trabajar
//con una base de datos se haria una consulta
//para averiguar si el nombre esta libre o no
if ($_GET["q"] == "juan"){
echo "NO";
}
else {
echo "OK";
}
?>

Si probamos con este código. Funciona bien en Internet Explorer pero en Firefox 1.5 da un error similar a:

Error: [Exception… “Component returned failure code: 0×80040111 (NS_ERROR_NOT_AVAILABLE) [nsIXMLHttpRequest.status]” nsresult: “0×80040111 (NS_ERROR_NOT_AVAILABLE)” location: “JS frame ...

Parece ser que se trata de un problema que surge al llamar a la función send() en un objeto XMLHttpRequest que todavía se encuentra procesando una petición anterior. Así pues se podría solucionar aumentando el tiempo de envio de las peticiones. De hecho si se escribe lentamente el ID en Firefox no aparece el problema. Pero claro no es cuestión de pedir al usuario que teclee despacio.

TENTATIVA 2: Para evitar el problema. La única solución eficaz ha sido crear una array para crear tantas peticiones como necesitemos, para así evitar utilizar una ya ocupada.

validar.html

<script language = "javascript">
function createRequestObject(){
var peticion;
var browser = navigator.appName;
if(browser == "Microsoft Internet Explorer"){
peticion = new ActiveXObject("Microsoft.XMLHTTP");
}else{
peticion = new XMLHttpRequest();
}
return peticion;
}
var http = new Array();
function ObtDatos(url){
var act = new Date();
http[act] = createRequestObject();
http[act].open('get', url);
http[act].onreadystatechange = function() {
if (http[act].readyState == 4) {
if (http[act].status == 200 || http[act].status == 304) {
var texto
texto = http[act].responseText
var DivDestino = document.getElementById("DivDestino");
DivDestino.innerHTML = "<div id='error'>"+texto+"</div>";
}
}
}
http[act].send(null);
}
function compUsuario(Tecla) {
Tecla = (Tecla) ? Tecla: window.event;
input = (Tecla.target) ? Tecla.target :
Tecla.srcElement;
if (Tecla.type == "keyup") {
var DivDestino = document.getElementById("DivDestino");
DivDestino.innerHTML = "<div></div>";
if (input.value) {
ObtDatos("login.php?q=" + input.value);
}
}
}
</script>
<p>Teclea tu Id de usuario:
<input id = "textField" type = "text" name = "IdUsuarui" onkeyup = "compUsuario(event)">
</p>
<div id = "DivDestino"></div>

login.php

<?php 
// En el caso probable de trabajar
//con una base de datos se haria una consulta
//para averiguar si el nombre esta libre o no
if ($_GET["q"] == "juan"){
echo "El ID se encuentra ocupado";
}
else {
echo "Puedes utilizarlo";
}
?>

Ver ejemplo en funcionamiento » »

Algunas entradas relacionadas:

 

Ejemplo de comprobación de enlaces internos con Ajax

0 COMENTARIOS -  Publicado hace 42 meses -  Clasificado en: , ,

Este ejemplo sirve para comprobar los enlaces internos del propio sitio. El ejemplo hace uso de AJAX y del objeto XMLHttpRequest, que tiene ciertas limitaciones como es la imposibilidad de hacer llamadas a otros dominios. He estado leyendo algún que otro artículo sobre cómo saltarse esta limitación pero lo cierto es que no he sacado nada en claro. Sería muy interesante poder saltarse la limitación para poder crear una aplicación en AJAX que testease todos los links, tanto internos como externos, de un sitio. De momento, como ya he dicho, éste ejemplo testea los links internos.

El ejemplo se sustenta en tutoriales anteriores de Ajax y en algunos ejemplos ya expuestos de Javascript.

Ver ejemplo en funcionamiento » »

<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
<script type="text/javascript">
var i=0;
function getreq()
{
    if(window.XMLHttpRequest)
        return new XMLHttpRequest();
    else if(window.ActiveXObject)
        return new ActiveXObject("Microsoft.XMLHTTP");
}
function cargarEnlace() {
	var links=document.getElementsByTagName("a");
	peticion = getreq();
	if(peticion.readyState == 4 || peticion.readyState == 0) {
		if (i< links.length){
			var url = document.links[i].href;
			peticion.onreadystatechange = imagexists;
    			peticion.open("get", url, true);
    			peticion.send(null);
			
	}
	}
}
function imagexists(){
	if(peticion.readyState == 4) {
		if(peticion.status == 200)
		{
			document.links[i].style.color = "#438811";
			i++;
			cargarEnlace();
		}
		else
		{
			document.links[i].style.color = "#F5601E";
			i++;
			cargarEnlace();
		}
	}
}
window.onload=cargarEnlace;
</script>
<style type="text/css">
<!--
body  { font: 11px Verdana, Arial, Helvetica, sans-serif; color: #333;}
a { font: 12px Verdana, Arial, Helvetica, sans-serif; color: #CCC; text-decoration:none}
ul { list-style: none;}
-->
</style>
</head>
<body>
<p>Comprobación de los enlaces de las secciones del blog:</p>
 <ul>
	<li>
	<a href="http://www.webintenta.com/category/ajax/">
	AJAX</a>
	</li><li>
	<a href="http://www.webintenta.com/category/ASP/">
	ASP</a>
	</li><li>
	<a href="http://www.webintenta.com/category/PHP/">
	PHP</a>
	</li><li>
	<a href="http://www.webintenta.com/category/CSS/">
	CSS</a>
	</li><li>
	<a href="http://www.webintenta.com/category/diseno/">
	Diseño</a>
	</li><li>
	<a href="http://www.webintenta.com/noexiste/">
	No existe</a>
	</li><li>
	<a href="http://www.webintenta.com/category/javascript/">
	Javascript</a>
	</li><li>
	<a href="http://www.webintenta.com/category/fotografia/">
	Fotografia</a>
	</li>
</ul>
</body>
</html>

Algunas entradas relacionadas:

 

Combos dependientes II

4 COMENTARIOS -  Publicado hace 44 meses -  Clasificado en: , ,

Continuando con el tema de combos dependientes veamos ahora un ejemplo con Ajax y PHP. El anterior ejemplo nos puede ser útil siempre y cuando no tengamos mucha información, pero supongamos ahora que tenemos dos tablas relacionadas; una de actividades con 17 registros; y otra de subactividades -relacionada con la anterior por un mismo id de actividad- de más de 100 subactividades. En este caso deberemos recurrir a leer desde una base de datos. Si queremos, además, que no se recargue la página para agilizar el uso de nuestro formulario, deberemos usar AJAX.

Tenemos dos tablas:

  • "t_actividades" con los campos "Id" y "Actividad"
  • "t_subactividades" con los campos "IdActividad", "IdSubactividad", "SubActividad". (Los campos en negrita relacionan ambas tablas)

Ahora necesitamos crear un php que sería en el que tendríamos todo nuestro formulario, incluyendo los desplegables de Actividad y Subactividad. Lo vamos a denominar "combos2.php" y en un primer momento tendríamos:

<p><label for="actividad">Actividad:</label>
<select name="Actividades" id="Actividades">
<?
$servidor = 'servidor.dominio.com';
$usuario = 'usuario';
$contrasena = 'password';
$datos = 'basededatos';
mysql_connect($servidor,$usuario,$contrasena);
@mysql_select_db($datos) or die( "Unable to select database");
$query = "SELECT * FROM t_actividades";
$result=mysql_query($query);
$num=mysql_numrows($result);
mysql_close();
$i=0;
while ($i < $num) {
$Id = mysql_result($result,$i,"Id");
$Actividad = mysql_result($result,$i,"Actividad");
?>
<option value=<? echo $Id; ?>>
<? echo $Actividad ?>
</option>
<?
$i++;
}
?>
</select>
</p>
<p>
<div id="Div_Subactividades">
<label for="SubActividad">SubActividad:</label>
<select name="SubActividades" id="SubActividades" class="select">
</select>
</div>
</p>

Lo que se ha hecho es crear el primer combo a partir de los datos extraidos en la tabla de actividades "t_actividades" y dejar el combo correspondiente a las subactividades vacío, pero dentro de un div llamado Div_Subactividades que será donde se cargue el contenido obtenido tras hacer una petición mediante AJAX.

<div id="Div_Subactividades">
<label for="SubActividad">SubActividad:</label>
<select name="SubActividades" id="SubActividades" class="select">
</select>
</div>

Lo siguiente sería crear una instancia del objeto XMLHttpRequest() y una función que nos permita cargar el contenido del segundo combo en función del primero.

<script type="text/javascript">
var peticion = false;
var testPasado = false;
try {
peticion = new XMLHttpRequest();
} catch (trymicrosoft) {
try {
peticion = new ActiveXObject("Msxml2.XMLHTTP");
} catch (othermicrosoft) {
try {
peticion = new ActiveXObject("Microsoft.XMLHTTP");
} catch (failed) {
peticion = false;
}
}
}
if (!peticion)
alert("ERROR AL INICIALIZAR!");
function cargarCombo (url, comboAnterior, element_id) {
//Obtenemos el contenido del div
//donde se cargaran los resultados
var element = document.getElementById(element_id);
//Obtenemos el valor seleccionado del combo anterior
var valordepende = document.getElementById(comboAnterior)
var x = valordepende.value
//construimos la url definitiva
//pasando como parametro el valor seleccionado
var fragment_url = url+'?Id='+x;
element.innerHTML = '<img src="Imagenes/loading.gif" />';
//abrimos la url
peticion.open("GET", fragment_url);
peticion.onreadystatechange = function() {
if (peticion.readyState == 4) {
//escribimos la respuesta
element.innerHTML = peticion.responseText;
}
}
peticion.send(null);
}
</script>

La función "cargarCombo" quizá sea la más interesante. Se le pasan tres parámetros: la url a la que llamamos, el combo del que depende el que vamos a cargar, y el id del div donde se cargará el resultado. El código javascript lo podemos insertar en el mismo "combos2.php" o hacer un include. El valor del segundo combo variará siempre que cambie el contenido del primer combo con lo que deberemos llamar a la función "cargarCombo" al evento onchange del select 'Actividades'. Por lo que finalmente quedaría:

<select name="Actividades"  onchange="javascript:cargarCombo('Subactividades.php', 'Actividades', 'Div_Subactividades')" id="Actividades">

Por último nos queda crear un fichero "Subactividades.php", que en función de la actividad seleccionada, cargará en el desplegable las subactividades correspondientes.

<?
$IdActividad = $_REQUEST['Id'];
?>
<label for="SubActividad">SubActividad:</label>
<select name="SubActividades" id="SubActividades" class="select">
<?
$servidor = 'servidor.dominio.com';
$usuario = 'usuario';
$contrasena = 'password';
$datos = 'basededatos';
mysql_connect($servidor,$usuario,$contrasena);
@mysql_select_db($datos) or die( "Unable to select database");
$query = "SELECT * FROM t_subactividades WHERE IdActividad=$IdActividad";
$result=mysql_query($query);
$num=mysql_numrows($result);
mysql_close();
$i=0;
while ($i < $num) {
$IdSubactividad = mysql_result($result,$i,"IdSubactividad");
$SubActividad = mysql_result($result,$i,"SubActividad");
?>
<option value=<? echo $IdSubactividad; ?>>
<? echo htmlentities($SubActividad) ?>
</option>
<?
$i++;
}
?>
</select>
 
Páginas: < Anterior 1 2 3 4 5 Siguiente >