Dotstore
Canais iMasters

Javascript

Tudo sobre Javascript não-obstrutivo - Parte 02 (Alcançando os objetos)

Nesta etapa explicaremos como alcançar e manipular os objetos de um documento utilizando as funções do Javascript DOM.

Para desenvolvedores Javascript inexperientes, o HTML é o seu playground.

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>

Ou se ele é um pouco mais avançado:

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:
// pre-carregamento da imagem
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;
}  

De qualquer forma, todas as chamadas dos eventos estão no HTML, e se uma função muda de nome, nós somos obrigados a mudar cada documento. Além disso, cada roll-over significa um monte de marcações que serão adicionadas ao peso da página.

Fora! Fora! - Nada de chamada de eventos direto nas tags

Vamos esquecer, por enquanto, que quase todo efeito roll-over, hoje em dia, pode ser feito via CSS, sendo uma opção melhor do que com Javascript. Vamos supor que nós queremos usar a seguinte marcação para criar um roll-over para a imagem:

HTML:  
<a href="index.html">
   <img src="home.gif" id="home" alt="home">
</a>  

Agora, como mudar a imagem quando o mouse passar por cima dela?

Escalando os galhos do documento

Cada documento XML (e isso inclui o HTML) é um node tree (a tradução mais adequada desse termo seria "árvore de nós"). Um nó é uma parte dessa árvore (imagine um arquivo ou diretório no Windows Explorer quando você navega pelo seu disco rígido). Um nó pode ser 12 coisas diferentes - mas, para o HTML, somente 3 realmente interessam: Elemento, TextNode e AttributeNode.

Nosso equipamento de escalada

Vamos ver quais funções e atributos que nós podemos usar para escalar a árvore de nós do documento, e como alternar de um elemento para outro.

Funções para alcançar um elemento na pagina

getElementById('elementID') - retorna o elemento que tem a id 'elementID' como um objeto.

getElementsByTagName('tag') - retorna todos os elementos cujo nome seja 'tag' como um vetor.

Mas é claro que você pode misturar e combinar esses dois. Por exemplo:

document.getElementById('navigation').getElementsByTagName('a')[3];
retorna o quarto link dentro do elemento com o id 'navigation'

document.getElementsByTagName('div')[2].getElementsByTagName('p')[0];
retorna o primeiro paragrafo dentro da terceira div do documento.
Ferramentas para navegar dentro de certo elemento
childNodes
retorna um vetor com todos os nós dentro do atual elemento. Também existem firstChild e lastChild que são apelidos curtos para childNodes[0] e childNodes[this.childNodes.length-1] respectivamente.
 
parentNode
O elemento em que o atual elemento está contido (Ou simplesmente o elemento pai).
 
nextSibling
o próximo elemento no mesmo nível na árvore do documento.
 
previousSibling
o elemento anterior no mesmo nível na árvore do documento.

Todos esses elementos podem ser mesclados de acordo com as suas necessidades.

Javascript:  
var other=document.getElementById('nav').childNodes[3].firstChild;
// retorna o primeiro elemento do quarto // elemento dentro do elemento com o id 'nav'.

var prevlink=o.parentNode.previousSibling.firstChild.childnodes[2];
// retorna o terceiro elemento dentro do primeiro // elemento do elemento anterior no mesmo nivel do // elemento pai do elemento o (pode parecer complicado, // mas leia novamente com atenção e veja como é simples).
Atributos e funções para os elementos
attributes
retorna um vetor de todos os atributos deste elemento. Não funciona com o Internet Explorer anteriores a versão 6.
 
data
retorna ou altera os dados textuais de um nó.
 
nodeName
retorna o nome do nó (o nome do elemento HTML).
 
nodeType
retorna o tipo do node; - 1 é um elemento nó, 2 é um atributo e 3 é texto.
 
nodeValue
retorna ou altera o valor do nó. Esse valor é o texto quando o nó é do tipo texto, um atributo quando é do tipo atributo e null se for um outro elemento.
 
getAttribute(attribute)
retorna o valor do atributo 'attribute' .
Javascript:
var other=document.getElementById('nav').firstChild;
if(other.nodeType==3)
{ other.data='newtext';
} if(other.nodeType==1)
{ other.firstChild.data='newtext';
}

Agora, para alcançar a imagem no nosso exemplo, nós podemos usar qualquer um, getElementByTagName ou getElementById.

HTML:
<a href="index.html">
   <img src="home.gif" id="home" alt="home">
</a>

Javascript:
function findimg()
{
   var image;
   image=document.getElementById('home');
   if (image)
   {
      image.style.border='3px dashed #ccc';
} }
ou: function findimg() { var imgs,i; imgs=document.getElementsByTagName('img'); for(i in imgs) { if(/home.gif/.test(imgs[i].src)) { imgs[i].style.border='3px dashed #ccc'; } } }

Usando o getElementById é muito mais fácil, como nós não temos que ter um loop através de todos os elementos para achar um identificador único. Neste exemplo, nós verificamos se o atributo src da imagem contem 'home.gif'. O modo mais comum é verificar uma classe especial.

HTML:  
<a href="index.html">
   <img src="home.gif" class="roll" alt="home">
</a> 
	
Javascript:
function findimg()
{
   var imgs,i;
   imgs=document.getElementsByTagName('img');
   for(i in imgs)
   {
      if(/roll/.test(imgs[i].className))
      {
         imgs[i].style.border='3px dashed #ccc';
      }
   }
}

Agora, para adicionar um efeito roll-over, tudo que nós precisamos fazer é adicionar uma função que faz a mudança da origem da imagem, e adicionar os manipuladores de eventos na imagem.

function findimg()
	{
	   var imgs,i;
	   // loop através de todos os elementos do documento
	   imgs=document.getElementsByTagName('img');
	   for(i=0;i<imgs.length;i++)
	   {
		  // testa se a classe roll existe
		  if(/roll/.test(imgs[i].className))
		  {
			 // adiciona a função roll na imag
          // em quando 'onmouseover' e 'onmouseout'   
			 // levando como argumento a img como objeto
			 imgs[i].onmouseover=function(){roll(this);};
         imgs[i].onmouseout=function(){roll(this);};
		  }
	   }
	}
	
function roll(o)
{
   var src,ftype,newsrc;
   // pega o atributo src da imagem, e descobre a extensão do arquivo
   src = o.src;
   ftype = src.substring(src.lastIndexOf('.'), src.length);
   // verifica se o atributo src já tem '_on' e se tiver apaga ele
	
   if(/_on/.test(src))
   {
      newsrc = src.replace('_on','');
   }
   else
   {
      // senão, adiciona o '_on' no src da imagem
      newsrc = src.replace(ftype, '_on'+ftype);
   }
	
   o.src=newsrc;
}
	
window.onload=function(){   findimg();  }

Teste esse exemplo  

Muito bom por enquanto. Mas nós esquecemos uma coisa: mesmo sendo meramente um efeito visual, um roll-over deveria funcionar mesmo sem o mouse. Para isto, nós precisamos verificar se o link em volta da imagem está em foco ou não, pois a imagem propriamente dita não é acessível pelo teclado quando está envolvida em um link.

Para fazer isso, nós precisamos pegar o elemento que contém a imagem, nesse caso o link. Faremos usando o comando parentNode. Como isto muda o objeto que vai como parâmetro para a função roll(), nós precisamos encontrar a imagem novamente.

Daqui, nós vamos rodar através dos childNodes do link e descobrir qual element é uma imagem, verificando o nodeType e o nodeName. Isso é necessário pois alguns navegadores vêem o espaço em branco como um nó, enquanto outros não.

function findimg()
{
   var imgs,i;  // Faz um loop através de todas as imagens
                //verificando se alguma delas contém a classe 'roll'
   
   imgs=document.getElementsByTagName('img');
   for(i=0;i<imgs.length;i++)
   {
      if(/roll/.test(imgs[i].className))
      {  // adiciona a função roll ao elemento-pai da imagem
         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 através de todos os childNodes
   for (i=0;i<o.childNodes.length;i++)
   {
      nownode=o.childNodes[i];  
      // se o nó é um elementoif the node is an element and
      // e é uma IMG, muda a variável e sai do loop
		 
      if(nownode.nodeType==1 && /img/i.test(nownode.nodeName))
      {
         isnode=i;
         break;
      }
   }  // verifica o src e faz o roll-over
   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();  } 
	
Teste esse exemplo clicando aqui.

Bom pessoal, então é isso, espero que tenha sido útil para vocês. No próximo artigo falaremos sobre como criar e destruir objetos no documento.

Abraços! Até a próxima!


Comente também

4 Comentários

adriano donisete machado machado
adriano donisete machado machado

o artigo é muito bom, parabéns...
fiquei com uma dúvida, já q eu nao devo misturar js com html, como seria numa situação em q a chamada

de uma função js for montado dinâmicamente. Imagine montar uma lista e cada item desta lista chama

uma mesma função js, com seu respectivo id, como eu faria isso? existe uma regra pra isso?

<?php
while ($ob = $rs->fetchRow()) {
echo '<a href="#" onclick"alterar(' . $ob->id_item . ');">Alterar</a>';
}
?>

André Metzen
André Metzen

Uma solução possivel para esse problema é aplicar a alguma outra propriedade da tag <a> o id do item. Por exemplo: <a href="..." title="id: #10">. Ou seja, o link se refere ao id 10. Talvez a propriedade title não seja a melhor, você poderia usar alguma outra como rel="10" ou até mesmo usar o id: <a href="..." id="id_10">. Ou qualquer outra que não prejudique sua pagina ou a semantica.
Espero te ajudado, abraços.

Diego Fleury
Diego Fleury

Para quem quiser ir adiantando, a próxima matéria que ele vai postar sobre "criar e destruir objetos no documento" está aqui: http://www.onlinetools.org/articles/unobtrusivejavascript/chapter3.html

adriano donisete machado machado
adriano donisete machado machado

entendi, isso resolveria esse problema...
obrigado

Qual a sua opinião?

Comentários considerados ofensivos serão moderados.

Parceiros

IBM
PagSeguro
Internet Innovation
Dialhost
HostNet
Tecla
KingHost
DotStore
Dinamize