Últimos mensajes - Powered by IBM
- Orientación de página
- error al intentar unirse al dominio
- Botones de acceso rapido en un teclado
- PROBLEMAS PARA CONFIGURAR IMPRESORA
- Crear mensaje de inicio en bacth
- Problema con cartel "Suspender Apagar Reiniciar"
- Error al encender laptop Pantalla Azul
- sesion lenta entre xp y winServer2008
- mensaje antes de responder un correo por xchange ...
- problemas con Z:
Palabras claves
Javascript no obstructivo, Manual de buenas maneras
17/10/2006 - 21:59 por Chea | Informe spam
Esto pretende ser una traducción (de las mias) de un fabuloso artículo de
Christian Heilmann.
Javascript es una herramienta maravillosa para mejorar la usabilidad de las
aplicaciones web. Es una capa extra entre la estructura (HTML) y el
diseño(CSS). Javascript nos permite alterar el comportamiento de un
elemento.
Uno de los problemas con los que nos encontramos a la hora de desarrollar
aplicaciones web con javascript son problemas de accesibilidad derivados al
no contemplar la posibilidad de que un usuario nos visite con un navegador
que no interprete este lenguaje. Una técnica para corregir este problema
sería el separar el javascript de las otras 2 capas del desarrollo web
(estructura y diseño), esto recibe el nombre de Javascript no obstructivo o
Javascript Accesible.
La frase, "¡¡Divide y vencerás!!" se adapta perféctamente a esta idea, en
la cual separaremos cada capa en su respectivo fichero, de forma que en
cuanto a mantenimiento (la etapa más costosa y larga del desarrollo de una
aplicación) e incluso la comprensión de la aplicación se verán afectadas
positivamente en cualquier aplicación.
Operación limpieza
El desarrollo web ha cambiado en los últimos años, estamos dejando de
mezclar la presentación de la estructura, lo que nos está facilitando el
trabajo de mantenimiento, modificación y mejora de nuestras aplicaciones.
El código que hace años usabamos esta dando lugar a otro más complejo y
fácil de mantener.
HTML:
<table border="0? cellpadding="0? width="100%" cellspacing="5?>
<tr>
<td><font face="Arial" size="-2?>Lorem Ipsum</font></td>
</tr>
</table>
Este código con todos los atributos referentes a la presentación en el
código nos obliga a recorrer toda la aplicación para modificar cualquier
aspecto que deseemos modificar. Por este motivo, nuestro código empieza a
coger un poco de sensatez y nos permite separar las 2 capas, diseño y
estructura.
CSS:
td.content {font-family:Arial,sans-serif;font-size:12px;}
HTML:
<table cellpadding="0?
style="width:100%;border:none" cellspacing="5?>
<tr>
<td class="content">Lorem Ipsum</td>
</tr>
</table>
Y aún podemos ir más allá.
CSS:
body {font-family:Arial,sans-serif;font-size:12px;}
p {padding:5px;}
HTML:
<p>Lorem Ipsum</p>
La misma evolución ha sufrido el desarrollo con Javascript.
Reglas del Javascript no obstructivo
1. Nunca, bajo ninguna circunstancia incluyas javascript directamente en el
documento.
Una de las mayores ventajas del Javascript es que al igual que CSS permite
la ejecución en ficheros externos. Esto nos permite incluir los ficheros
que necesitemos para cada páginas, ajustando al máximo el peso de la
aplicación. Además si has de cambiar alguna funcionalidad de la aplicación
únicamente has de modificar el fichero JS en cuestión.
Pero para poder disfrutar de esta propiedad siempre tendremos que hacer
referencia a nuestro/s javascript desde el fichero HTML, añadiendo entre
los tags <head></head> la siguiente línea haciendo alusión al fichero que
deseamos adherir a nuestro proyecto.
<script type="text/javascript" src="scripts.js"></script>
2. Javascript es una mejora, no un sistema de seguridad.
Nosotros solo podemos usar Javascript como una mejora, debemos de pensar
que no siempre podremos disponer de él y que agentes externos pueden
deshabilitarlo sin darnos opción a activarlo, asi que hemos de programar
pensando en que cualquier persona en este problema tambien debe poder usar
nuestra aplicación.
Para ello podemos ver un ejemplo de javascript en el que vemos como valida
un formulario.
HTML:
<form action="index.php" onsubmit="return checkform(this)">
<p><label for="login">Login:</label>
<input type="text" name="login" id="login" /></p>
<p><label for="pw">Password:</label>
<input type="password" name="pw" id="pw" /></p>
<p><input type="submit" value="send" /></p>
</form>
Javascript:
function checkform(f)
{
var error='';
error+=f.login.value==''?'nlogin':'';
error+=f.pw.value==''?'npassword':'';
if (error!='')
{
alert('Please enter the following:'+error);
}
return error=='';
}
Esto es perfectamente válido, nos permite controlar el formulario sin
perjudicar a los usuarios que no tiene Javascript. De modo que en caso de
no tenerlo activado únicamente tendremos que tener en cuenta que en la
página de recepción de datos tendremos que validarlos directamente en el
servidor, devolviendo al usuario a la página anterior en caso de que no
sean válidos.
Otra forma de afrontar el problema sería la siguiente.
HTML:
<form action="index.php">
<p><label for="login">Login:</label>
<input type="text" name="login" id="login" /></p>
<p><label for="pw">Password:</label>
<input type="password" name="pw" id="pw" /></p>
<p><input type="button" onclick="checkform()" value="send" /></p>
</form>
Javascript:
function checkform()
{
var f=document.forms[0];
var error='';
error+=f.login.value==''?'nlogin':'';
error+=f.pw.value==''?'npassword':'';
if (error!='')
{
alert('Please enter the following:'+error);
} else {
f.submit();
}
}
De esta forma estamos condenando al fracaso nuestra aplicación ya que si el
navegador de nuestro usuario no soporta la llamada onclick, no podrá
realizar un submit ya que nuestro boton es del tipo button.
3. Checkea la disponibilidad de un objeto antes de acceder a él.
Muchos de los errores en Javascript se deben a que se intenta acceder a
elementos o métodos que no existen en un determinado momento del periodo de
ejecución. Para solucionar esto basta con realizar un pequeña comprobación
antes de utilizar dicho elemento o método.
Javascript:
function color(o,col)
{
if(o)
{
o.style.background=col;
}
}
Antes de usar el elemento o, comprobamos que exista, así conseguimos una
robustez en nuestra aplicación que el usuario agradecerá. Esta técnica es
muy usada para el famoso cross-browsing.
4. Crea un Javascript no especifico para un navegador
Quizas la regla más complicada de todas, pero la más importante. Al igual
que tenemos que tener en cuenta navegadores sin Javascript hemos de tener
en cuenta todos los navegadores, para ello usaremos la regla anterior como
la mejor baza a nuestro favor.
Javascript:
function doDOMstuff()
{
if(document.getElementById && document.createTextNode)
{
[.]
}
}
Comprobamos la existencia del método getElementById y createTextNode del
objeto document antes de usarlo, así nos aseguramos una victoria al lanzar
esta función.
5. No uses variables de otros scripts.
Cuando creemos una función o funcionalidad debemos estar seguros de usar
variables locales para dicha función o funcionalidad. De esta forma nos
prevenimos de que otras funciones o funcionalidades modifiquen nuestras
variables.
Javascript:
var iB; // global variable
function dothings()
{
for (i=0;i<200;i++) // i gets changed
{
// some code
}
}
function dothingsright()
{
var i; // define i locally
for (i=0;i<200;i++)
{
// some code
}
}
alert(i); // = 42
dothingsright()
alert(i) // = 42 (due to local definition)
dothings()
alert(i) // = 200, oops!
6. Mantén los efectos de ratón de forma independiente
Tener en cuenta que el javascript esté activo o no no es suficiente. Hemos
de tener en cuenta que hay usuarios que no pueden utilizar el ratón para
navegar como normalmente se hace, esto obliga a usar el teclado para
realizar todas las tareas que requiera nuestra aplicación. Un problema
típico es el onchange o onblur en los elementos de un formulario ya que el
teclado ejecuta estos eventos de forma distinta que el ratón.
HTML:
<form>
<p>
<label for="go2?>Go to:</label>
<select name="go2? id="go2? onchange="send(this)">
<option value="index.html">Home</option>
<option value="chapter1.html">Operation Cleanout</option>
<option value="chapter2.html">Reaching things</option>
</select>
</p>
</form>
Javascript:
function send(f)
{
var chosen;
chosen=f.options[f.selectedIndex].value;
self.location=chosen;
}
El problema que tenemos aqui es que cada vez que hacemos nos desplazamos
hacia abajo desde nuestro teclado, estamos realizando la función send(), no
siendo el resultado deseado (en FF parece no pasar). Los usuarios con
experiencia sabrán que usan alt+abajo podrán omitir este evento.
La forma de solucionar esto es delegando la obtención del valor al evento
onsubmit, de forma que podremos realizar cuantos cambios deseemos sobre
nuestro formulario y únicamente lanzará la función al realizar el submit.
HTML:
<form action="send.php" method="post" onsubmit="return send(this)">
<p>
<label for="go2?>Go to:</label>
<select name="go2? id="go2?>
<option value="index.html">Home</option>
<option value="chapter1.html">Operation Cleanout</option>
<option value="chapter2.html">Reaching things</option>
</select>
<input type="submit" value="go" />
</p>
</form>
Javascript:
function send(f)
{
var chosen;
chosen=f.go2.options[f.go2.selectedIndex].value;
self.location=chosen;
return false;
}
PHP:
<?PHP if(isset($_POST['go2'])){
header('Location:'.$_POST['go2']);
}?>
La opción de PHP sería para los casos en los que el navegador no permite la
ejecución de código javascript.
¿Que pasa con onkeypress?
Según la W3C, en estos casos.
Otherwise, if you must use device-dependent attributes, provide redundant
input mechanisms (i.e., specify two handlers for the same element):
Use "onmousedown" with "onkeydown".
Use "onmouseup" with "onkeyup"
Use "onclick" with "onkeypress"
Esto suena perfecto en la teoría pero en la vida real el evento onkeypress
está mal soportado por diferentes navegadores. Los usuarios que dependen
del teclado para navegar normalmente tienen una configuración para simular
los clicks, intro o espacio. Entonces esto nos lanza el evento onclick.
Cómo alcanzar lo que deseamos cambiar
Para un desarrollador javascript inexperto, el HTML es un patio de juegos.
HTML:
<a href="index.html"
onmouseover="image1.src='1on.gif'"
onmouseout="image1.src='1off.gif'">
<img src="1off.gif" name="image1? border="0? height="150? width="150?
alt="home"></a>
O incluso puede ser un poco más avanzado.
HTML:
<a href="index.html"
onmouseover="roll('home',1)"
onmouseout="roll('home',0)">
<img src="home.gif" name="home" border="0?
height="150? width="150?
alt="home"></a>
Javascript:
// preloading image
homeoff = new Image();
homeoff.src = 'home.gif';
homeon = new Image();
homeon.src = 'homeoff.gif';
function roll(imgName,a)
{
imgState=a==0?eval(imgName + 'on.src'):eval(imgName + 'off.src');
document.images[imgName].src = imgState;
}
En cualquier caso los eventos son llamados desde el HTML y si la función
cambia de nombre, tendremos que cambiarlo en cada documento.Para ello
debemos saber que usar y cuando usarlo, por ejemplo para este rollover,
usaremos CSS que cumple nuestra misión sin alterar en nada la accesibilidad
ni el resultado.
HTML:
<a href="index.html"><img src="home.gif" id="home" alt="home"></a>
Subir por los ramas del árbol del nodo
Cada fichero XML (en ellos se incluye el xHTML) es como un árbol. Un nodo
una parte de este árbol, y al igual que en un arbol para subir a un rama en
la copa del arbol tendremos que pasar por todas las ramas que nos
encontremos por el camino, no podemos saltarnos ninguna. En javascript
disponemos de una buena serie de herramientas que nos permiten recorrer
este árbol poder manipular las propiedades de un elemento de dicho árbol.
Funciones para alcanzar un elemento en la página
getElementById('elementID')
Devuelve el elemento con el ID asignado
getElementsByTagName('tag')
Devuelve todos los elemento con la etiqueta (tag)
Funciones para recorrer las cercanias de un elemento
childNodes
Devuelve un array con todos los hijos que cuelguen del elemento. Tambien
disponemos de firstChild y lastChild, que son versiones reducidas de
childNodes[0] y childNodes[this.childNodes.length-1].
parentNode
Nos devuele el elemento padre
nextSibling
El siguiente elemento al mismo nivel dentro del árbol.
previousSibling
El elemento anterior al mismo nivel dentro del árbol.
Atributos y funciones para elementos
attributes
Devuelve un array con todos los atributos del elemento.¿Como no? No
funciona con Internet Explorer 6 o inferior.
data
Devuelve o asigna los datos textuales del nodo
nodeName
Devuelve el nombre del nodo (El nombre de elemento HTML)
nodeType
Devuelve el tipo de nodo
Es un elemento nodo
Un atriburo
Un texto
nodeValue
Devuelve o asigna el value de un nodo.
getAttribute(attribute)
Devuelve el valor del atributo demandado.
Conociendo estas funciones y atributos, podremos mejorar nuestro código y
hacer algo parecido a esto.
HTML:
<a href="index.html"><img src="home.gif" class="roll" alt="home"></a>
Javascript:
function findimg()
{
var imgs,i;
// loop through all images of the document
imgs=document.getElementsByTagName('img');
for(i=0;i<imgs.length;i++)
{
// test if the class 'roll' exists
if(/roll/.test(imgs[i].className))
{
// add the function roll to the image onmouseover and onmouseout and send
// the image itself as an object
imgs[i].onmouseover=function(){roll(this);};
imgs[i].onmouseout=function(){roll(this);};
}
}
}
function roll(o)
{
var src,ftype,newsrc;
// get the src of the image, and find out the file extension
src = o.src;
ftype = src.substring(src.lastIndexOf('.'), src.length);
// check if the src already has an _on and delete it, if that is the case
if(/_on/.test(src))
{
newsrc = src.replace('_on','');
}else{
// else, add the _on to the src
newsrc = src.replace(ftype, '_on'+ftype);
}
o.src=newsrc;
}
window.onload=function(){
findimg();
}
Bien por el momento, aunque no hemos olvidado de una cosa, ahora esta
imagen realizará un roll-over al pasar el ratón por encima, pero tenemos
que pensar en los usuarios sin ratón. Para conseguir esto debemos checkear
si el enlace de alrededor tiene el focus o no. Para ello usaremos el
comando parentNode de nuestro objeto de la siguiente forma.
Javascript:
function findimg()
{
var imgs,i;
// Loop through all images, check if they contain the class roll
imgs=document.getElementsByTagName('img');
for(i=0;i<imgs.length;i++)
{
if(/roll/.test(imgs[i].className))
{
// add the function roll to the parent Element of the image
imgs[i].parentNode.onmouseover=function(){roll(this);};
imgs[i].parentNode.onmouseout=function(){roll(this);};
imgs[i].parentNode.onfocus=function(){roll(this);};
imgs[i].parentNode.onblur=function(){roll(this);};
}
}
}
function roll(o)
{
var i,isnode,src,ftype,newsrc,nownode;
// loop through all childNodes
for (i=0;i<o.childNodes.length;i++)
{
nownode=o.childNodes[i];
// if the node is an element and an IMG set the variable and exit the loop
if(nownode.nodeType==1 && /img/i.test(nownode.nodeName))
{
isnode=i;
break;
}
}
// check src and do the rollover
src = o.childNodes[isnode].src;
ftype = src.substring(src.lastIndexOf('.'), src.length);
if(/_on/.test(src))
{
newsrc = src.replace('_on','');
}else{
newsrc = src.replace(ftype, '_on'+ftype);
}
o.childNodes[isnode].src=newsrc;
}
window.onload=function(){
findimg();
}
Creando y destruyendo contenido
Una de las fortalezas de DOM es que no es únicamente de lectura, y esto nos
permite modificar más aún nuestra aplicación. Para ello disponemos de una
serie de funciones y métodos que nos facilitarán el trabajo.
Crear un nodo
createElement(element)
Crea un nuevo elemento
createTextNode(string)
Crea un elemento de texto con el valor string
Alterando un contenido existente
setAttribute(attribute,value)
Añade un nuevo valor al atributo del objeto
appendChild(child)
Añade un nodo hijo a la lista de childNode del objeto, el hijo debe de ser
un objeto, no un texto.
cloneNode()
Copia el nodo completo con todos sus hijos.
hasChildNodes()
Comprueba que el nodo no se un nodo hoja, osea que tenga hijos
insertBefore(newchild,oldchild)
Crea un nuevo hijo (newchild) antes del hijo antiguo (oldchild)
removeChild(oldchild)
Borra un hijo.
replaceChild(newchild,oldchild)
Reemplaza el viejo hijo (oldchild) por el nuevo (newchild).
removeAttribute(attribute)
Elimina un atributo del objeto.
Vamos a ver un ejemplo práctico y accesible. Imaginar que queremos hacer
una lista en la cual tendremos enlaces a imagenes, si no disponemos de
Javascript abriremos una ventana nueva para ver la imagen seleccionada.
HTML:
<ul id="imglist">
<li><a href="home.gif" target="_blank">Home
(new window)</a></li>
<li><a href="home_on.gif" target="_blank">Home active
(new window)</a></li>
<li><a href="jscsshtml.gif" target="_blank">HTML-CSS-Javascript
(new window)</a></li>
</ul>
De esta forma tenemos una válida de mostrar una lista de imagenes, al hacer
click sobre el enlace el target actuará y mostrará la imagen en una ventana
nueva. Pero, ¿si disponemos de javascript? ¿por que no podemos enriquecer
el aspecto?
Si disponemos de Javascript y DOM vamos a hacer lo siguiente:
Eliminar el texto (new window) de los links
Añadir al evento onclick la llamada a la función popw()
Javascript:
function imgpop()
{
var il,imga,imgatxt;
// get all LIs in imagelist, loop over them
il=document.getElementById('imglist').getElementsByTagName('li');
for(i=0;i<il.length;i++)
{
// grab first link in the LI
imga=il[i].getElementsByTagName('a')[0];
// delete the wording (new window) in the link text
// (which is the nodeValue of the first node)
imgatxt=imga.firstChild;
imgatxt.nodeValue=imgatxt.nodeValue.replace(/ (new window)/,'');
// add the event handlers to call popw();
imga.onclick=function(){return popw(this);}
//imga.onkeypress=function(){return popw(this);}
}
}
La función debe:
Mostrar la imagen debajo del link.
Ocultar la imagen en caso de ya estar visible.
Hacer que la imagen desaparezca al hacer click sobre ella.
Javascript:
function popw(o)
{
var newimg;
// if there is already an image in the parentNode (li)
if(o.parentNode.getElementsByTagName('img').length>0)
{
// delete it
o.parentNode.removeChild(o.parentNode.getElementsByTagName('img')[0]);
} else {
// else, create a new image and add a handler that removes it when you
// click it
newimg=document.createElement('img');
newimg.style.display='block';
newimg.onclick=function(){this.parentNode.removeChild(this);};
newimg.src=o.href;
o.parentNode.appendChild(newimg)
}
return false;
}
Podeis ver el ejemplo de mano del autor.Activar y desactivar el javascript
para ver las diferencias.
Separacion de CSS y Javascript
Quizas en los ejemplos anteriores no se está usando la forma más apropiada,
pero es bastante clara para demostrar lo que queremos expresar. La idea
desde un principio es separar de forma bien definida las 3 capas que
influjen en una aplicación web. Por eso debemos evitar código parecidos a
estos.
Javascript:
if(!document.getElementById('errormsg')){
var em=document.createElement('p');
em.id='errormsg';
em.style.border='2px solid #c00';
em.style.padding='5px';
em.style.width='20em';
em.appendChild(document.createTextNode('Please enter or change the fields
marked with a '))
i=document.createElement('img');
i.src='img/alert.gif';
i.alt='Error';
i.title='This field has an error!';
em.appendChild(i);
}
Esto además de no ser nada claro, es un coñazo a la hora de ponerte a
modificar cualquier opción o añadir cualquier mejora. Por eso hemos de
delegar es tema del aspecto a los CSS. Para ello usaremos el nexo entre la
capa del diseño y la capa funcional, los tags.
Todos los tags tienen 2 atributos como mínimo, ID y class. ID se refiere al
nombre único que le damos a un elemento concreto de la imagen, los ID's
nunca deben repetirse en la página. Despues tenemos class, que asigna un
aspecto a nuestro elemento, en cierta manera el class engloba a todos los
elementos designados dentro de dicha clase.
Sintaxis de multiples clases
Los elementos pueden tener más de una clase, simplemente hay que separarlas
por espacios. Esto esta soportado por los navegadores más modernos. IE en
Mac no le gusta mucho cuando una clase conteniene el nombre de otra.
Aplicando clases via Javascript
Para cambiar la clase de un elemento debemos atacar al atributo className
del objeto.
HTML:
<ul id="nav">
[.]
</ul>
Javascript:
if(document.getElementById && document.createTextNode)
{
if(document.getElementById('nav'))
{
document.getElementById('nav').className='isDOM';
}
}
Esto no origina que nuestro CSS pueda tener dos estados, uno el que ataque
al ID directamente #nav y otro que ataque al ID más la clase #nav.isDOM
ul#nav{
[...]
}
ul#nav.isDOM{
[...]
}
Usando el operador += podremos añadir una o más clases a nuestro elemento.
if(document.getElementById && document.createTextNode)
{
var n=document.getElementById('nav');
if(n)
{
n.className+=n.className?' isDOM':'isDOM';
}
}
http://www.anieto2k.com/2006/10/15/...as-maneras
http://antitella.blogspot.com/ Jose Manuel Tella Llop
http://antitella.blogspot.com/ Jose Manuel Tella Llop
http://antitella.blogspot.com/ Jose Manuel Tella Llop
Christian Heilmann.
Javascript es una herramienta maravillosa para mejorar la usabilidad de las
aplicaciones web. Es una capa extra entre la estructura (HTML) y el
diseño(CSS). Javascript nos permite alterar el comportamiento de un
elemento.
Uno de los problemas con los que nos encontramos a la hora de desarrollar
aplicaciones web con javascript son problemas de accesibilidad derivados al
no contemplar la posibilidad de que un usuario nos visite con un navegador
que no interprete este lenguaje. Una técnica para corregir este problema
sería el separar el javascript de las otras 2 capas del desarrollo web
(estructura y diseño), esto recibe el nombre de Javascript no obstructivo o
Javascript Accesible.
La frase, "¡¡Divide y vencerás!!" se adapta perféctamente a esta idea, en
la cual separaremos cada capa en su respectivo fichero, de forma que en
cuanto a mantenimiento (la etapa más costosa y larga del desarrollo de una
aplicación) e incluso la comprensión de la aplicación se verán afectadas
positivamente en cualquier aplicación.
Operación limpieza
El desarrollo web ha cambiado en los últimos años, estamos dejando de
mezclar la presentación de la estructura, lo que nos está facilitando el
trabajo de mantenimiento, modificación y mejora de nuestras aplicaciones.
El código que hace años usabamos esta dando lugar a otro más complejo y
fácil de mantener.
HTML:
<table border="0? cellpadding="0? width="100%" cellspacing="5?>
<tr>
<td><font face="Arial" size="-2?>Lorem Ipsum</font></td>
</tr>
</table>
Este código con todos los atributos referentes a la presentación en el
código nos obliga a recorrer toda la aplicación para modificar cualquier
aspecto que deseemos modificar. Por este motivo, nuestro código empieza a
coger un poco de sensatez y nos permite separar las 2 capas, diseño y
estructura.
CSS:
td.content {font-family:Arial,sans-serif;font-size:12px;}
HTML:
<table cellpadding="0?
style="width:100%;border:none" cellspacing="5?>
<tr>
<td class="content">Lorem Ipsum</td>
</tr>
</table>
Y aún podemos ir más allá.
CSS:
body {font-family:Arial,sans-serif;font-size:12px;}
p {padding:5px;}
HTML:
<p>Lorem Ipsum</p>
La misma evolución ha sufrido el desarrollo con Javascript.
Reglas del Javascript no obstructivo
1. Nunca, bajo ninguna circunstancia incluyas javascript directamente en el
documento.
Una de las mayores ventajas del Javascript es que al igual que CSS permite
la ejecución en ficheros externos. Esto nos permite incluir los ficheros
que necesitemos para cada páginas, ajustando al máximo el peso de la
aplicación. Además si has de cambiar alguna funcionalidad de la aplicación
únicamente has de modificar el fichero JS en cuestión.
Pero para poder disfrutar de esta propiedad siempre tendremos que hacer
referencia a nuestro/s javascript desde el fichero HTML, añadiendo entre
los tags <head></head> la siguiente línea haciendo alusión al fichero que
deseamos adherir a nuestro proyecto.
<script type="text/javascript" src="scripts.js"></script>
2. Javascript es una mejora, no un sistema de seguridad.
Nosotros solo podemos usar Javascript como una mejora, debemos de pensar
que no siempre podremos disponer de él y que agentes externos pueden
deshabilitarlo sin darnos opción a activarlo, asi que hemos de programar
pensando en que cualquier persona en este problema tambien debe poder usar
nuestra aplicación.
Para ello podemos ver un ejemplo de javascript en el que vemos como valida
un formulario.
HTML:
<form action="index.php" onsubmit="return checkform(this)">
<p><label for="login">Login:</label>
<input type="text" name="login" id="login" /></p>
<p><label for="pw">Password:</label>
<input type="password" name="pw" id="pw" /></p>
<p><input type="submit" value="send" /></p>
</form>
Javascript:
function checkform(f)
{
var error='';
error+=f.login.value==''?'nlogin':'';
error+=f.pw.value==''?'npassword':'';
if (error!='')
{
alert('Please enter the following:'+error);
}
return error=='';
}
Esto es perfectamente válido, nos permite controlar el formulario sin
perjudicar a los usuarios que no tiene Javascript. De modo que en caso de
no tenerlo activado únicamente tendremos que tener en cuenta que en la
página de recepción de datos tendremos que validarlos directamente en el
servidor, devolviendo al usuario a la página anterior en caso de que no
sean válidos.
Otra forma de afrontar el problema sería la siguiente.
HTML:
<form action="index.php">
<p><label for="login">Login:</label>
<input type="text" name="login" id="login" /></p>
<p><label for="pw">Password:</label>
<input type="password" name="pw" id="pw" /></p>
<p><input type="button" onclick="checkform()" value="send" /></p>
</form>
Javascript:
function checkform()
{
var f=document.forms[0];
var error='';
error+=f.login.value==''?'nlogin':'';
error+=f.pw.value==''?'npassword':'';
if (error!='')
{
alert('Please enter the following:'+error);
} else {
f.submit();
}
}
De esta forma estamos condenando al fracaso nuestra aplicación ya que si el
navegador de nuestro usuario no soporta la llamada onclick, no podrá
realizar un submit ya que nuestro boton es del tipo button.
3. Checkea la disponibilidad de un objeto antes de acceder a él.
Muchos de los errores en Javascript se deben a que se intenta acceder a
elementos o métodos que no existen en un determinado momento del periodo de
ejecución. Para solucionar esto basta con realizar un pequeña comprobación
antes de utilizar dicho elemento o método.
Javascript:
function color(o,col)
{
if(o)
{
o.style.background=col;
}
}
Antes de usar el elemento o, comprobamos que exista, así conseguimos una
robustez en nuestra aplicación que el usuario agradecerá. Esta técnica es
muy usada para el famoso cross-browsing.
4. Crea un Javascript no especifico para un navegador
Quizas la regla más complicada de todas, pero la más importante. Al igual
que tenemos que tener en cuenta navegadores sin Javascript hemos de tener
en cuenta todos los navegadores, para ello usaremos la regla anterior como
la mejor baza a nuestro favor.
Javascript:
function doDOMstuff()
{
if(document.getElementById && document.createTextNode)
{
[.]
}
}
Comprobamos la existencia del método getElementById y createTextNode del
objeto document antes de usarlo, así nos aseguramos una victoria al lanzar
esta función.
5. No uses variables de otros scripts.
Cuando creemos una función o funcionalidad debemos estar seguros de usar
variables locales para dicha función o funcionalidad. De esta forma nos
prevenimos de que otras funciones o funcionalidades modifiquen nuestras
variables.
Javascript:
var iB; // global variable
function dothings()
{
for (i=0;i<200;i++) // i gets changed
{
// some code
}
}
function dothingsright()
{
var i; // define i locally
for (i=0;i<200;i++)
{
// some code
}
}
alert(i); // = 42
dothingsright()
alert(i) // = 42 (due to local definition)
dothings()
alert(i) // = 200, oops!
6. Mantén los efectos de ratón de forma independiente
Tener en cuenta que el javascript esté activo o no no es suficiente. Hemos
de tener en cuenta que hay usuarios que no pueden utilizar el ratón para
navegar como normalmente se hace, esto obliga a usar el teclado para
realizar todas las tareas que requiera nuestra aplicación. Un problema
típico es el onchange o onblur en los elementos de un formulario ya que el
teclado ejecuta estos eventos de forma distinta que el ratón.
HTML:
<form>
<p>
<label for="go2?>Go to:</label>
<select name="go2? id="go2? onchange="send(this)">
<option value="index.html">Home</option>
<option value="chapter1.html">Operation Cleanout</option>
<option value="chapter2.html">Reaching things</option>
</select>
</p>
</form>
Javascript:
function send(f)
{
var chosen;
chosen=f.options[f.selectedIndex].value;
self.location=chosen;
}
El problema que tenemos aqui es que cada vez que hacemos nos desplazamos
hacia abajo desde nuestro teclado, estamos realizando la función send(), no
siendo el resultado deseado (en FF parece no pasar). Los usuarios con
experiencia sabrán que usan alt+abajo podrán omitir este evento.
La forma de solucionar esto es delegando la obtención del valor al evento
onsubmit, de forma que podremos realizar cuantos cambios deseemos sobre
nuestro formulario y únicamente lanzará la función al realizar el submit.
HTML:
<form action="send.php" method="post" onsubmit="return send(this)">
<p>
<label for="go2?>Go to:</label>
<select name="go2? id="go2?>
<option value="index.html">Home</option>
<option value="chapter1.html">Operation Cleanout</option>
<option value="chapter2.html">Reaching things</option>
</select>
<input type="submit" value="go" />
</p>
</form>
Javascript:
function send(f)
{
var chosen;
chosen=f.go2.options[f.go2.selectedIndex].value;
self.location=chosen;
return false;
}
PHP:
<?PHP if(isset($_POST['go2'])){
header('Location:'.$_POST['go2']);
}?>
La opción de PHP sería para los casos en los que el navegador no permite la
ejecución de código javascript.
¿Que pasa con onkeypress?
Según la W3C, en estos casos.
Otherwise, if you must use device-dependent attributes, provide redundant
input mechanisms (i.e., specify two handlers for the same element):
Use "onmousedown" with "onkeydown".
Use "onmouseup" with "onkeyup"
Use "onclick" with "onkeypress"
Esto suena perfecto en la teoría pero en la vida real el evento onkeypress
está mal soportado por diferentes navegadores. Los usuarios que dependen
del teclado para navegar normalmente tienen una configuración para simular
los clicks, intro o espacio. Entonces esto nos lanza el evento onclick.
Cómo alcanzar lo que deseamos cambiar
Para un desarrollador javascript inexperto, el HTML es un patio de juegos.
HTML:
<a href="index.html"
onmouseover="image1.src='1on.gif'"
onmouseout="image1.src='1off.gif'">
<img src="1off.gif" name="image1? border="0? height="150? width="150?
alt="home"></a>
O incluso puede ser un poco más avanzado.
HTML:
<a href="index.html"
onmouseover="roll('home',1)"
onmouseout="roll('home',0)">
<img src="home.gif" name="home" border="0?
height="150? width="150?
alt="home"></a>
Javascript:
// preloading image
homeoff = new Image();
homeoff.src = 'home.gif';
homeon = new Image();
homeon.src = 'homeoff.gif';
function roll(imgName,a)
{
imgState=a==0?eval(imgName + 'on.src'):eval(imgName + 'off.src');
document.images[imgName].src = imgState;
}
En cualquier caso los eventos son llamados desde el HTML y si la función
cambia de nombre, tendremos que cambiarlo en cada documento.Para ello
debemos saber que usar y cuando usarlo, por ejemplo para este rollover,
usaremos CSS que cumple nuestra misión sin alterar en nada la accesibilidad
ni el resultado.
HTML:
<a href="index.html"><img src="home.gif" id="home" alt="home"></a>
Subir por los ramas del árbol del nodo
Cada fichero XML (en ellos se incluye el xHTML) es como un árbol. Un nodo
una parte de este árbol, y al igual que en un arbol para subir a un rama en
la copa del arbol tendremos que pasar por todas las ramas que nos
encontremos por el camino, no podemos saltarnos ninguna. En javascript
disponemos de una buena serie de herramientas que nos permiten recorrer
este árbol poder manipular las propiedades de un elemento de dicho árbol.
Funciones para alcanzar un elemento en la página
getElementById('elementID')
Devuelve el elemento con el ID asignado
getElementsByTagName('tag')
Devuelve todos los elemento con la etiqueta (tag)
Funciones para recorrer las cercanias de un elemento
childNodes
Devuelve un array con todos los hijos que cuelguen del elemento. Tambien
disponemos de firstChild y lastChild, que son versiones reducidas de
childNodes[0] y childNodes[this.childNodes.length-1].
parentNode
Nos devuele el elemento padre
nextSibling
El siguiente elemento al mismo nivel dentro del árbol.
previousSibling
El elemento anterior al mismo nivel dentro del árbol.
Atributos y funciones para elementos
attributes
Devuelve un array con todos los atributos del elemento.¿Como no? No
funciona con Internet Explorer 6 o inferior.
data
Devuelve o asigna los datos textuales del nodo
nodeName
Devuelve el nombre del nodo (El nombre de elemento HTML)
nodeType
Devuelve el tipo de nodo
Es un elemento nodo
Un atriburo
Un texto
nodeValue
Devuelve o asigna el value de un nodo.
getAttribute(attribute)
Devuelve el valor del atributo demandado.
Conociendo estas funciones y atributos, podremos mejorar nuestro código y
hacer algo parecido a esto.
HTML:
<a href="index.html"><img src="home.gif" class="roll" alt="home"></a>
Javascript:
function findimg()
{
var imgs,i;
// loop through all images of the document
imgs=document.getElementsByTagName('img');
for(i=0;i<imgs.length;i++)
{
// test if the class 'roll' exists
if(/roll/.test(imgs[i].className))
{
// add the function roll to the image onmouseover and onmouseout and send
// the image itself as an object
imgs[i].onmouseover=function(){roll(this);};
imgs[i].onmouseout=function(){roll(this);};
}
}
}
function roll(o)
{
var src,ftype,newsrc;
// get the src of the image, and find out the file extension
src = o.src;
ftype = src.substring(src.lastIndexOf('.'), src.length);
// check if the src already has an _on and delete it, if that is the case
if(/_on/.test(src))
{
newsrc = src.replace('_on','');
}else{
// else, add the _on to the src
newsrc = src.replace(ftype, '_on'+ftype);
}
o.src=newsrc;
}
window.onload=function(){
findimg();
}
Bien por el momento, aunque no hemos olvidado de una cosa, ahora esta
imagen realizará un roll-over al pasar el ratón por encima, pero tenemos
que pensar en los usuarios sin ratón. Para conseguir esto debemos checkear
si el enlace de alrededor tiene el focus o no. Para ello usaremos el
comando parentNode de nuestro objeto de la siguiente forma.
Javascript:
function findimg()
{
var imgs,i;
// Loop through all images, check if they contain the class roll
imgs=document.getElementsByTagName('img');
for(i=0;i<imgs.length;i++)
{
if(/roll/.test(imgs[i].className))
{
// add the function roll to the parent Element of the image
imgs[i].parentNode.onmouseover=function(){roll(this);};
imgs[i].parentNode.onmouseout=function(){roll(this);};
imgs[i].parentNode.onfocus=function(){roll(this);};
imgs[i].parentNode.onblur=function(){roll(this);};
}
}
}
function roll(o)
{
var i,isnode,src,ftype,newsrc,nownode;
// loop through all childNodes
for (i=0;i<o.childNodes.length;i++)
{
nownode=o.childNodes[i];
// if the node is an element and an IMG set the variable and exit the loop
if(nownode.nodeType==1 && /img/i.test(nownode.nodeName))
{
isnode=i;
break;
}
}
// check src and do the rollover
src = o.childNodes[isnode].src;
ftype = src.substring(src.lastIndexOf('.'), src.length);
if(/_on/.test(src))
{
newsrc = src.replace('_on','');
}else{
newsrc = src.replace(ftype, '_on'+ftype);
}
o.childNodes[isnode].src=newsrc;
}
window.onload=function(){
findimg();
}
Creando y destruyendo contenido
Una de las fortalezas de DOM es que no es únicamente de lectura, y esto nos
permite modificar más aún nuestra aplicación. Para ello disponemos de una
serie de funciones y métodos que nos facilitarán el trabajo.
Crear un nodo
createElement(element)
Crea un nuevo elemento
createTextNode(string)
Crea un elemento de texto con el valor string
Alterando un contenido existente
setAttribute(attribute,value)
Añade un nuevo valor al atributo del objeto
appendChild(child)
Añade un nodo hijo a la lista de childNode del objeto, el hijo debe de ser
un objeto, no un texto.
cloneNode()
Copia el nodo completo con todos sus hijos.
hasChildNodes()
Comprueba que el nodo no se un nodo hoja, osea que tenga hijos
insertBefore(newchild,oldchild)
Crea un nuevo hijo (newchild) antes del hijo antiguo (oldchild)
removeChild(oldchild)
Borra un hijo.
replaceChild(newchild,oldchild)
Reemplaza el viejo hijo (oldchild) por el nuevo (newchild).
removeAttribute(attribute)
Elimina un atributo del objeto.
Vamos a ver un ejemplo práctico y accesible. Imaginar que queremos hacer
una lista en la cual tendremos enlaces a imagenes, si no disponemos de
Javascript abriremos una ventana nueva para ver la imagen seleccionada.
HTML:
<ul id="imglist">
<li><a href="home.gif" target="_blank">Home
(new window)</a></li>
<li><a href="home_on.gif" target="_blank">Home active
(new window)</a></li>
<li><a href="jscsshtml.gif" target="_blank">HTML-CSS-Javascript
(new window)</a></li>
</ul>
De esta forma tenemos una válida de mostrar una lista de imagenes, al hacer
click sobre el enlace el target actuará y mostrará la imagen en una ventana
nueva. Pero, ¿si disponemos de javascript? ¿por que no podemos enriquecer
el aspecto?
Si disponemos de Javascript y DOM vamos a hacer lo siguiente:
Eliminar el texto (new window) de los links
Añadir al evento onclick la llamada a la función popw()
Javascript:
function imgpop()
{
var il,imga,imgatxt;
// get all LIs in imagelist, loop over them
il=document.getElementById('imglist').getElementsByTagName('li');
for(i=0;i<il.length;i++)
{
// grab first link in the LI
imga=il[i].getElementsByTagName('a')[0];
// delete the wording (new window) in the link text
// (which is the nodeValue of the first node)
imgatxt=imga.firstChild;
imgatxt.nodeValue=imgatxt.nodeValue.replace(/ (new window)/,'');
// add the event handlers to call popw();
imga.onclick=function(){return popw(this);}
//imga.onkeypress=function(){return popw(this);}
}
}
La función debe:
Mostrar la imagen debajo del link.
Ocultar la imagen en caso de ya estar visible.
Hacer que la imagen desaparezca al hacer click sobre ella.
Javascript:
function popw(o)
{
var newimg;
// if there is already an image in the parentNode (li)
if(o.parentNode.getElementsByTagName('img').length>0)
{
// delete it
o.parentNode.removeChild(o.parentNode.getElementsByTagName('img')[0]);
} else {
// else, create a new image and add a handler that removes it when you
// click it
newimg=document.createElement('img');
newimg.style.display='block';
newimg.onclick=function(){this.parentNode.removeChild(this);};
newimg.src=o.href;
o.parentNode.appendChild(newimg)
}
return false;
}
Podeis ver el ejemplo de mano del autor.Activar y desactivar el javascript
para ver las diferencias.
Separacion de CSS y Javascript
Quizas en los ejemplos anteriores no se está usando la forma más apropiada,
pero es bastante clara para demostrar lo que queremos expresar. La idea
desde un principio es separar de forma bien definida las 3 capas que
influjen en una aplicación web. Por eso debemos evitar código parecidos a
estos.
Javascript:
if(!document.getElementById('errormsg')){
var em=document.createElement('p');
em.id='errormsg';
em.style.border='2px solid #c00';
em.style.padding='5px';
em.style.width='20em';
em.appendChild(document.createTextNode('Please enter or change the fields
marked with a '))
i=document.createElement('img');
i.src='img/alert.gif';
i.alt='Error';
i.title='This field has an error!';
em.appendChild(i);
}
Esto además de no ser nada claro, es un coñazo a la hora de ponerte a
modificar cualquier opción o añadir cualquier mejora. Por eso hemos de
delegar es tema del aspecto a los CSS. Para ello usaremos el nexo entre la
capa del diseño y la capa funcional, los tags.
Todos los tags tienen 2 atributos como mínimo, ID y class. ID se refiere al
nombre único que le damos a un elemento concreto de la imagen, los ID's
nunca deben repetirse en la página. Despues tenemos class, que asigna un
aspecto a nuestro elemento, en cierta manera el class engloba a todos los
elementos designados dentro de dicha clase.
Sintaxis de multiples clases
Los elementos pueden tener más de una clase, simplemente hay que separarlas
por espacios. Esto esta soportado por los navegadores más modernos. IE en
Mac no le gusta mucho cuando una clase conteniene el nombre de otra.
Aplicando clases via Javascript
Para cambiar la clase de un elemento debemos atacar al atributo className
del objeto.
HTML:
<ul id="nav">
[.]
</ul>
Javascript:
if(document.getElementById && document.createTextNode)
{
if(document.getElementById('nav'))
{
document.getElementById('nav').className='isDOM';
}
}
Esto no origina que nuestro CSS pueda tener dos estados, uno el que ataque
al ID directamente #nav y otro que ataque al ID más la clase #nav.isDOM
ul#nav{
[...]
}
ul#nav.isDOM{
[...]
}
Usando el operador += podremos añadir una o más clases a nuestro elemento.
if(document.getElementById && document.createTextNode)
{
var n=document.getElementById('nav');
if(n)
{
n.className+=n.className?' isDOM':'isDOM';
}
}
http://www.anieto2k.com/2006/10/15/...as-maneras
http://antitella.blogspot.com/ Jose Manuel Tella Llop
http://antitella.blogspot.com/ Jose Manuel Tella Llop
http://antitella.blogspot.com/ Jose Manuel Tella Llop
Preguntas similares
- JavaScript no funciona en local con IExplorer, pero sí con otros navegadores
- [New KB] JavaScript no puede abrir una nueva ventana emergente de un mensaje de Outlook en Service Pack 2 de Windows XP
- Enlaces javascript no funcionan
- JavaScript no está habilitado
- No funciona Javascript en Internet Explorer
- no funciona javascript en ie
- Usuario Administrador: no funciona JavaScript en Local
- no me funciona más el javascript en IE6...
- no entiende javascript
- No me funciona un javaScript con ajax
Busqueda sugerida :
Leer las respuestas