Comunidad de diseño web y desarrollo en internet online

AJAX y Javascript no intrusivo y accesible

Atención: Este tutorial hace uso intensivo del código visto en el tutorial de AJAX publicado en Cristalab. No olvides revisarlo antes de ver este.

Ahora todo el mundo habla de usabilidad web y accesibilidad web, pero pocos entienden los conceptos. Se puede entender por accesibilidad el acceso a la información contenida en los sitios web sin limitación alguna por razón de deficiencia, minusvalía o tecnología utilizada sin que interfieran. Esto que quiere decir, que no importa si la persona es ciega, debe poder navegar el sitio sin problema alguno, y para hacerlo no utiliza una computadora, utiliza un dispositivo especial que es totalmente diferente a una computadora. (

Usabilidad es brindar al sitio algo para que sea mas fácil su navegación.

Si nos remitimos a las Pautas de Accesibilidad del Contenido en la Web en la sección 6.3 se puede leer lo siguiente

“Asegure que las paginas sigan siendo utilizables cuando se desconectan o no se soporten los scripts, applets u otros objetos de programación. Si esto no es posible, proporcione información equivalente en una pagina alternativa accesible [Prioridad 1]”

Y el ejemplo que proveen es NO usar en los tag atributos del tipo “atributo=javascript:Algo()". Una practica común en Javascript.

Como podrán haber visto en este tutorial de AJAX (Que seguiremos durante este tutorial de accesibilidad) es muy normal que los tags sean algo así

<a href="javascript:funcion('parametro.html','contenedor')";>link</a>

Y como verán, estamos haciendo algo prohibido según las pautas de accesibilidad web. Investigando por aquí y por alla encontre varias guías para hacer algo más acorde a la pauta. Iré comentando el código a medida que lo expongo.

function addLoadEvent(func){
    var oldonload = window.onload;
    if (typeof window.onload != 'function')
    {
        window.onload = func;
    }else{
        window.onload = function(){
            if (oldonload)
            {
                oldonload();
            }
            func();
        }
    }
}

Esta función lo que hace es agregarle una función (la que se recibe por parametro) a la pagina HTML, es algo similar a poner en el tag body "onload=javascript:algo()"

addLoadEvent(function(){
    var links = document.getElementsByTagName( 'a' );
    var divs = document.getElementsByTagName( 'div' );
    var total = links.length;
    for( var i=0; i < total; i++ )
    {
        links[i].onclick = function()
        {
            var total2 = divs.length;
            for( var j=0; j < total2; j++ ){
                if(this.id == divs[j].id){
                    cargar_pagina(this.href, divs[j]);
                    return false;
                }
            }
        }
    }
});

Aquí hemos invocado a la función anterior y le hemos pasado otra función por parametro. Esta función se cargara en la pagina y se ejecutara cuando se haga click en los links, la explicación viene luego para que se comprenda mejor.

function NuevoAjax(){
    var xmlhttp=false;
    try{
        xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
    }catch(e){
        try{
            xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
        }catch(E){
            xmlhttp = false;
        }
    }

    if(!xmlhttp && typeof XMLHttpRequest!='undefined'){
        xmlhttp = new XMLHttpRequest();
    }
    return xmlhttp;
}

function cargar_pagina (url, contenedor){
    ajax=NuevoAjax(); 
    ajax.open("GET", url,true); 
    ajax.onreadystatechange=function(){
        if(ajax.readyState==1){
            //Sucede cuando se esta cargando la pagina
            contenedor.innerHTML = "cargando()";//<-- Aca puede ir una precarga
        }else if(ajax.readyState==4){
            //Sucede cuando la pagina se cargó
            if(ajax.status==200){
                //Todo OK
                contenedor.innerHTML = ajax.responseText;
                agregar_accion();

            }else if(ajax.status==404){
                //La pagina no existe
                contenedor.innerHTML = "La página no existe";
            }else{
                //Mostramos el posible error
                contenedor.innerHTML = "Error:".ajax.status; 
            }
        }
    }
    ajax.send(null);
}

La primer función ya la deben conocer del tutorial de AJAX, lo que hace es crear nuestro objeto AJAX para usar. La segunda función recibe 2 parametros, un string con la url que queremos abrir y un objeto que sera el encargado de recibir esa pagina nueva. Es bastante similar al tutorial de AJAX y como esta comentado el código no voy a explicar mucho.

Todo esto va en un bonito archivo javascript que va a usar nuestra pagina web. Ahora, el HTML

<a href="link1.html" title="uno" id="uno">link</a><br />
<a href="link2.html" title="dos" id="dos">link</a><br />
<a href="link3.html" title="tres" id="tres">link</a><br />
<a href="link4.html" title="cuatro" id="cuatro">link</a><br />
<br />
<div id="uno">este es el uno</div>
<br />
<div id="dos">este es el dos</div>
<br />
<div id="tres">este es el tres</div>
<br />
<div id="cuatro">este es el cuatro</div>

Obviamente esto va dentro del body ^^

A simple vista, parece código HTML normal, nadie nos creía si le dijésemos que ahí se va a ejecutar AJAX. A esto nos referimos con usabilidad web, el HTML no debe ser mas que... HTML puro.

Nota: La única aclaración que voy a hacer es que el tag <a> necesita el atributo "id" y el valor de ese atributo se debe repetir en el tag <div> como se ve en el ejemplo.

Cuando hagamos click en un link, se ejecutara la función del javascript que vimos hoy. Y ahora la explicación.

Con la línea 1 vamos a pasarle a un array todos los tags <a> y en la segunda línea vamos a pasarle a otro array todos los <div>

En el ciclo for que le sigue, la idea es agregar el evento a cada l ink correspondiente.
Como no podemos usar el id para identificar al objeto para cargar el AJAX (porque hay 2 objetos con el mismo id) vamos a usar un for para identificarlo. Como estamos "dentro" del tag <a> si hacemos "this.href" obtendremos el valor del atributo href del link al que le hicimos click, así que podemos comparar sin ningún problema los id del link (this.id) con el id del div (divs[j].id) de la siguiente manera:

if(this.id == divs[i].id)

Cuando esta bifurcación sea true llamaremos a la función que hace el milagro del AJAX pasándole "this.href" como url, y "divs[j].id" como objeto destino, luego el "return false;" para que nos anule el click que se hace cuando una hace click en un link.

Y listo, ya con esto tendremos un bonito AJAX no intrusivo que cumple con las pautas de accesibilidad web. Pero como estoy bueno les voy a dar un regalo.

Cuando uno usa Gmail y esta viendo unos de esos correos que tienen "RE: " como principio de enunciado, lo que ven es un pedacito del mail, cuando uno le hace click puede ver el mail, y luego cuando le vuelve a hacer click el mail se cierra. Aca les dejo el ejemplo para que vean de lo que hablo.

Vamos a modificar el addLoadEvent para hacer algo parecido, aquí abajo tiene el código, la explicación luego.

addLoadEvent(function(){
    var links = document.getElementsByTagName( 'a' );
    var divs = document.getElementsByTagName( 'div' );
    var total = links.length;
    for( var i=0; i < total; i++ )
    {

        links[i].onclick = function()
        {
            var total2 = divs.length;
            for( var j=0; j < total2; j++ ){
                if(this.id == divs[j].id){
                    if (document.getElementById('flecha') != null){//Solo para el cambio de imagenes
                        var img = this.getElementsByTagName( 'img' );
                        if (img[0].title == "Expandir"){
                            img[0].title = "Contraer";
                            img[0].alt = "Contraer";
                            img[0].src = "images/general/farriba.gif";
                        } else{
                            divs[j].innerHTML = "";
                            img[0].title = "Expandir";
                            img[0].alt = "Expandir";
                            img[0].src = "images/general/fabajo.gif";
                            return false;
                        }
                    }
                    cargar_pagina(this.href, divs[j]);
                    return false;
                }
            }
        }
    }
});

Y en el HTML lo siguiente

<a href="pagina.html" title="Publicidad" id="publicidad">Publicidad <img src="images/general/fabajo.gif" id="flecha" alt="Expandir" title="Expandir" width="11" height="8" /></a>
<div id="publicidad"></div>

Agregamos una imagen dentro del tag <a> y en cualquier parte de la pagina un <div> vacío así como esta aquí. En la imagen el atributo alt y title debe ser igual y debe ser "Expandir".

Cuando hagamos click, se va a ejecutar el código igual que hoy, pero verán que hay una bifurcación nueva, lo que hacemos es preguntar si hay alguna tag con id igual a "flecha", nuestras imagenes de flechitas se llama así, "flecha".

var img = this.getElementsByTagName( 'img' )

Por esto decía que la imagen debe ir dentro del tag <a> para localizarla correctamente y poder tener varias flechas sin problemas.

Luego preguntamos por el title de ese tag, si es igual a "expandir" cambiamos su alt, title y la imagen, al salir de la bifurcación se cargara la pagina, si no llega a ser igual entonces la pagina ya estara cargada, por lo que con

divs[j].innerHTML = "";

Estaremos limpiando el <div>, luego nos queda cambiar el alt, title e imagen y como no tenemos que cargar agregamos el return false; con esto saldremos abruptamente de la función.

Limitación de esta técnica.

Hasta el día de la fecha no pude resolver un problema, que es el siguiente:
Tenemos una pagina A, y cargamos una pagina B dentro de ella. Con esta técnica. no podremos usar AJAX dentro de B, por lo que se pierde gran parte de lo bonito de AJAX :( pero sigo tratando de resolverlo. Pasense por el foro de AJAX para más información.

¿Sabes SQL? ¿No-SQL? Aprende MySQL, PostgreSQL, MongoDB, Redis y más con el Curso Profesional de Bases de Datos que empieza el martes, en vivo.

Publica tu comentario

El autor de este artículo ha cerrado los comentarios. Si tienes preguntas o comentarios, puedes hacerlos en el foro

Entra al foro y participa en la discusión

o puedes...

¿Estás registrado en Cristalab y quieres
publicar tu URL y avatar?

¿No estás registrado aún pero quieres hacerlo antes de publicar tu comentario?

Registrate