PostComo impedir que um onclick se propague
Postado por
Everton J. Carpes - everton.carpes@gmail.com
em
07/03/2009 04:23
Blog: MyWay
Karmômetro (?)
tende a neutroApesar de ser excelente termos a capacidade de dinamizarmos nossos trabalhos com Javascript e ainda mais com AJAX, devemos manter em mente sempre o objetivo de não ser intrusivos no funcionamento de determinadas ferramentas, ou seja, devemos usar JS adicionando capacidades ao que já existe, e não tornando nossas aplicações dependentes desta tecnologia.
Existe uma tendencia natural das pessoas, ao aprenderem sobre algo que lhes responda bem a determinadas demandas, a “se apaixonarem” pela coisa de tal maneira que passam a adota-la (muitas vezes inapropriadamente) para tudo.
O maior e pior exemplo disso certamente é o uso do Flash, um abuso exagerado, consequência direta de programadores e principalmente designers mal informados e que só conhecem martelos…
Mas o mesmo problema se estende ao uso das ECMA scripts como Javascript.
Certamente o exemplo que da origem a este post é extremamente comum e normalmente as pessoas o fazem errado, ou pelo menos não da forma mais adequada. Veja o exemplo:
<a href="#" onclick="myFunction(); return false">Link que dispara evento</a>
A marcação do exemplo acima apesar de válida, é conceitualmente imprópria, pois ela define através de si, manipuladores de eventos e chamadas explicitas a uma camada que NÃO diz respeito a marcação, ou ao DOM.
Se pretendemos ter eventos associados a um determinado script, como no caso, imaginemos, que determinado link, deveria funcionar chamando uma função que por sua vez faz o papel do link, como por exemplo, carregando através de AJAX o conteúdo que o link apontava, e abrindo o mesmo em uma área sem a necessidade do reload. O evento em si não é o problema, o problema se encontra em fixar a informação sobre ele direto na marcação, a qual deveria descrever o conteúdo. Este é exclusivamente o papel da marcação, descrever o seu conteúdo, descrever os objetos que representa. Associar camadas de controle a isto, é em essência sujar a marcação, e gerar um alto acoplamento entre camadas.
Este tipo de coupling não é apenas atestado de trabalho mal feito, este tipo de coisa vem do hábito de pensar da “maneira mais rápida”, logo estamos fazendo funcionalidades e mais funcionalidades que dependem exclusivamente de JS e isso parece sem grandes conseqüências.
A maneira correta de trabalhar isso, eh desacoplar e sempre que projetar as características da aplicação para que funcionem da “maneira correta” ou sem maiores dependências, então sobre as camadas que já existem, se adiciona características que alterem o padrão e adicionem as vantagens que desejamos.
Usando a classe Event da Prototype, adicionar um evento a um elemento é uma tarefa simples, digamos que você pretenda adicionar um evento no onClick de um elemento cujo id é item1, neste caso, o Javascript para isto poderia ser algo como isto:
Event.observe($("item1"), "click", myFunction);
Este exemplo funciona muito bem para a maioria dos elementos, porém se você pretendia aplicar isto para interceptar o onClick de um um link, isto não será o bastante. A sua função será executada como esperado, no entanto o link seguirá seu comportamento natural e a o browser será redirecionado para uri de sua href.
A solução simples para evitar este problema, esta em uma outra funcionalidade da Event, o método stop que lhe permite (obviamente) parar a cadeia de execuções através de um evento. para compreender isto, é necessário capturar duas informações:
- Eventos não acontecem isolados, mas em uma cadeia de fatos, quando você passa a observar um evento, está apenas se cadastrando como mais um observer.
- Quando sua função for chamada, ela receberá como parâmetro um objeto evento…
Partindo destas informações, pode-se imaginar um código que responde ao exemplo citado, de contornarmos um link que funcione normalmente, para que ao invés de termos um reload da pagina, o conteúdo desejado seja inserido através de uma requisição AJAX e algum lugar da página ou coisa do gênero, através de uma função (myFunction) que foi como exemplificado antes, adicionada a cadeia de eventos do link, porém em sua execução, ela deve fazer uma chamada ao método stop da Event:
function myFunction(event) { // A FUNCIONALIDADE QUE SE ESPERA COMO UMA CHAMADA AJAX, ETC Event.stop(event); };
Com isto, a cadeia de execução de eventos será parada na sua função, portanto o link não será submetido.
Assim como neste exemplo simples, existem várias formas de se eliminar o coupling entre as camadas de marcação e os estilos. Com um bom projeto, este tipo de funcionalidade pode tornar muitas coisas simples. Com o apoio solido de uma framework ou de um código bem escrito server side e o cuidado de separar bem as coisas, você consegue agregar capacidades a sua aplicação, sem excluir determinados públicos (como alguns bots não sabem muito de JS), ou ainda sem se tornar refém de determinadas tecnologias. Um sólido apoio server-side é necessário para que por exemplo você tenha automaticamente uma distinção entre as origens das requisições (como AJAX Vs. ou chamadas simples), de forma que tenha um tratamento simples ou trivial para a distinção do que se esta devolvendo!
Facilmente se consegue imaginar soluções simples onde você pode alterar automaticamente através de JS todo o comportamento de um conjunto (senão todos) de links de sua aplicação, tornando-os requisições AJAX, sem muitos esforços.
A Prototype obviamente não é a única biblioteca que te permite isso, e é possível obter resultados melhores se você adotar alguma biblioteca que seja orientada ao uso não obstrusivo dos scripts, inclusive existem bibliotecas de apoio baseadas na própria Prototype.
De qualquer forma, resolvi escrever sobre esta funcionalidade pois a considero útil para coisas simples e creio que mais alguem possa precisar.
Algumas referencias:
- API da Prototype
- Low Pro, uma biblioteca de apoio para Javascript inobstrusivo, baseada na Prototype
- Artigo sobre unobstrusive JS na A List Apart
- Um PDF da PeepCode sobre o uso inobstrusivo da prototype
- W3C schools sobre Eventos em Javascript
- Ruby on Rails – uma framework web que eu recomendo
UPDATE – Tue Mar 10 03:37:30 BRT 2009
A framework Javascript MooTools (utilizada por projetos importantes como o Joomla), oferece um mecanismo idêntico ao da Prototype para gerenciar a cadeia de execução de eventos DOM através de Javascript no MooTools
Postado por Everton J. Carpes - everton.carpes@gmail.com - em 07/03/2009 04:23
Comentários 
Postar um novo comentário
voltar ao início

Karmômetro (?)
tende a neutroNossa!
Postado por Foffano em 09/03/2009 09:28
Karmômetro (?)
tende a neutroEu trabalho bastante com javascript e não entendi qual o problema em colocar o function no elemento. Ou se o problema todo é colocar o function num , coloque o onClick num .
=]
Postado por Fiote em 09/03/2009 14:10
Karmômetro (?)
tende a neutro@Fiote
Provavelmente a abordagem presente neste artigo da A List Apart sobre Unobtrusive Javascript seja mais simples de compreender.
Existem vários motivos para tu separar tua marcação dos teus scripts:
Postado por Everton J. Carpes - everton.carpes@gmail.com em 10/03/2009 03:25
Karmômetro (?)
tende a neutroMeu amigo! Além do seu texto ser confuso (não dá entender o que você está falando exatamente) seu comentário sobre ser “errado” colocar um evento em um link, está completamente equivocado. O padrão Observer implementado no javascript para captura de eventos é apenas uma maneira de se obter um resultado mais desacoplado, mas tanto a sua estratégia quando a de colocar um “comando” no href são são equivalentes.
Não estou dizendo que seu post é ruim, nada disso, mas dizer que é errado colocar eventos na tag href é um equivoco no mínimo conceitual.
Postado por Ricardo em 01/05/2009 13:57
Karmômetro (?)
tende a neutro@Ricardo :
>> não dá entender o que você está falando exatamente
Essencialmente eh sobre como conter a propagacao de um evento (como o onclick) de dentro de observers.
>> O padrão Observer implementado no javascript para captura de eventos
>> é apenas uma maneira de se obter um resultado mais desacoplado
Basicamente ela eh uma das poucas senao a unica maneira de se obter um resultado onde a marcacao nao esteja acoplada a dinamizacao. Se tu conheces outras formas poderias apontar elas por favor?
>> mas tanto a sua estratégia quando a de colocar um “comando”
>> no href são são equivalentes.
Nao, de forma alguma sao equivalentes… quando eu especifico um callback na marcacao estou “sujando-a”, tornando a mesma dependentende da linguagem de script, inclusive presumindo que a mesma esteja presente o que nao necessariamente eh verdade.
>> Não estou dizendo que seu post é ruim
Tu teres comentado o que comentou ateh aqui, jah provou que meu post nao tah ruim, pois serviu para despertar exatamente a discucao que eu pretendia, de que por traz desta questao dos observers, existe algo mais complexo e importante, que eh a relacao do desacoplamento. Ateh tua pergunta eu estava cogitando que o post nao havia servido pra muita coisa, mas agora tou vendo que tah servindo sim… obrigado!
>> mas dizer que é errado colocar eventos na tag href é um
>> equivoco no mínimo conceitual.
Nao, quem tah comentendo um equivoco eh tu.
Como eu disse, isso nao eh INVALIDO, mas eh errado!
Colocar uma chamada a funcao no href de um link torna o link inutil para quem (como os spiders) nao tem javascript. Alem disso, o atributo href de uma anchor representa uma referencia a uma location (de um recurso). Notas sobre isso podem ser vistas ateh na pagina sobre a Tag Anchor no W3C schools
E indo alem do href, o problema persiste no onclick, onde apesar de ser um local mais adequado (do que o href), ainda perssiste o problema do acoplamento.
O caso eh o seginte, seu HTML funciona se eu desabilitar o JS no meu browser? Nao? entao sua marcacao eh dependente do JS. Se voce consegue manter seu HTML funcional e acima disso ter funcionalidades JS para quando isso for possivel, entao isso eh uma indicacao de que sua marcacao esta desacoplada da dinamizacao.
Postado por Everton J. Carpes - everton.carpes@gmail.com em 01/05/2009 18:04
Karmômetro (?)
tende a neutroOlá Everton,
Você tem razão. Se o js for desabilitado a página vai perder boa parte da funcionalidade. Mas se o js for desabilitado de que vai adiantar o uso do Event. Eu entendo quando você diz que o link vai nao irá mais funcionar, nem para o que foi previsto pelo W3C nem para a funcionalidade que foi pensada pelo programador quando colocou um evento onClick.
Mas eu ainda reafirmo que não é errado essa estratégia. Se o que você quer dizer que existem melhores práticas ok, mas NÃO está errado.
Para provar isso, vamos partir do princípio que o cara desabilitou o javascript do browser dele e com isso ferrou a funcionalidade do HREF junto com o onClick. Meu, amigo, o problema do href nesse caso será o menor dos males. Se o cara fazer isso, muita coisa vai parar de funcionar no browser dele. No mínimo, o layout vai se comportar de uma maneira um tanto indesejado dependendo da implementação javascript/css/dom. Mas isso não será o pior. Eu já estive envolvido em problemas onde a área de atendimento ficou congestionada (e isso quase me custou o emprego) por reclamações de usuários que não conseguiam se logar no sistema (trata-se de uma grande rede de supermecados que não vou citar o nome). O problema era exatamente porque os usuários reclamantes desabilitaram o javascript do browser fazendo com que a autenticação (estou me referindo a sessão) não conseguia ser feita por causa dos cookies. Usavamos a ferramenta WebSphere só para citar que era uma ambiente bem testado de algums milhões de reais.
Então esse negócio que o href vai parar de funcionar se o js for desabilitado é besteira. Esse é o menor dos males. Infelizmente temos muitos usuários mal informados que desabilitam o js com a justificativa que se não o fizerem os “sites” irão reter informações deles (acho que você entende o que estou falando). Se o cara desabilitar o js dele, problema dele. O usuário tem que conhecer a ferramenta que usa, no mínimo. O sistema não vai funcionar e acabou.
E pior. Se o cara usar uma das primeiras versões do Lynx aí é que “ferrou tudo”. Nem vou comentar isso pra não perder tempo.
Você comentou sobre os spiders. Ora, se eu coloquei na minha página que um determinado click deve chamar outra página ou realizar uma chamada Ajax o problema é de ordem do projeto que estou trabalhando. Eu não programo “orientado a indexação” de ferramentas de busca. E ninguém em sã consciência deve ou tem que fazer isso. Aliás, se o desgraçado trabalhar assim, está fora da minha equipe. Quando estou programando um sistema tenho que atender aos requisitos e não fazer com que a Internet funcione como um “eco-sistema” inteligente. Isso não é minha função e não acho que tenho que fazer diferente.
Todo mundo falava em baixo acoplamento e alta coesão (que é o que você está falando). Não está errado, mas o mundo real funciona de outra maneira. Dizem por aí que programação é uma arte. Arte porcaria nenhuma. Arte você faz como bem entende, programação você tem que atender um requisito, da maneira mais otimizada e com a melhor performance possível e para fazer isso muitas vezes você tem que ferir o conceito mais profundo aprendido na faculdade pra satisfazer a necessidade do usuário. Não vai ter pattern, best pratice ou qualquer outra balela que resista a um requisito necessário. As vezes tem que ser “assim” e pronto. Não tem conversa. E olha que já muito cara bom fazer coisas que eram de arrancar os cabelos.
Concluindo, se você acha “errado” colocar onclick no href, ótimo… Mas o mundo vai continuar fazendo assim e nem por isso poderá ser dito que está errado. É só mais uma forma de fazer a mesma coisa. Agora se você disser, “poxa isso pode ser melhor assim” então perfeito. Errado nunca!
Postado por Ricardo em 02/05/2009 00:21
Karmômetro (?)
tende a neutro@Ricardo
>> O problema era exatamente porque os usuários reclamantes
>> desabilitaram o javascript do browser
Isso nao necessariamente eh uma escolha, o usuario pode estar usando browsers para algum dispositivo embarcado q limitem o uso de scripts, podem estar em algum ambiente controlado (por um nazista), ou como tu mesmo disse, serem desinformados e desligarem o JS por acharem que isso eh bom…
>> Eu não programo “orientado a indexação” de ferramentas de busca.
>> E ninguém em sã consciência deve ou tem que fazer isso.
Sinceramente terei que discordar profundamente de ti, tu estas tratando SEO como se fosse uma tarefa ilegitima a programadores, e estas usando frases como:
>> estou programando um sistema tenho que atender aos requisitos
justificando algo irreal, pois sistemas web hoje que independem de “encontrabilidade” sao apenas um nicho (normalmente ferramentas de empresas, etc)… para grande maioria das ferramentas da web, ser encontrado por engines de busca EH UM DOS REQUISITOS e nao interessa quanto tu tente discordar disso, teus empregadores definirao isso com clareza… dizer o contrario significa afirmar que tu nao acha importante que um site seja encontrado, e neste caso te pergunto rpa que crias ele e se teus contratantes estao cientes de que tua onpiao eh que as ferramentas que fazes pra eles nao precisam aparecer no google?
A justificativa de que isso tudo eh teoria academica e de que no mundo real eh diferente me parece mais desculpa pra nao fazer a coisa direito. Hoje em dia temos muito mais suporte para fazermos a coisa da forma certa do que ao contrario, a prova disso eh que temos varias libs JS que dao solido suporte a codificacao de scripts nao obstrusivos.
O pensamento a favor do desacoplamento eh o que mais cresce, a anos vemos a web sendo repensada com a introducao cada vez mais forte do uso de estilos e scripts isolados da marcacao, seja no XHTML, seja em outras tecnologias web emergentes… o M de HTML refere-se a marcacao e eh isso mesmo que ela eh, uma linguagem de marcacao, de identificacao, onde se descreve a estrutura, modelagem de objetos contidos no documento, isso nao tem nada a ver com efeitos visuais ou com formas dinamicas de se alterar ou visualizar isto…
>> Eu já estive envolvido em problemas onde a área de atendimento
>> ficou congestionada (e isso quase me custou o emprego)
Acho que esta tua citacao a experiencia pessoal deveria ao contrario do que estas fazendo aqui, servir de justificativa pra entenderes a importancia de criares ferramentas cujas dependencias sejam minimas, ferramentas apropriadamente construidas de forma a trabalharem nos mais diversos ambientes, que eh o que a web sugere. Quando leio tua frase citada acima, a unica coisa que penso eh “mas entao?”…
>> Mas o mundo vai continuar fazendo assim
Qual mundo? Estas ofendendo uma ampla quantidade de programadores que como eu trabalham corretamente! Eu sou um desenvolvedor, conheco dezenas de outros no Brasil, mas pelo mundo desde os criadores e a ampla comunidade de usuarios de libs como o LowPro, as centenas de desenvolvedores que diariamente blogam e discutem sobre isso, ateh a propria W3C, criadora da web, todos incentivam o trabalho no sentido de tornar a marcacao o mais limpa, semantica e flexivel possivel, para que a web seja acessivel a um ampla gama de dispositivos… Esse “Mundo que vai continuar a fazer assim” eh uma pequena minoria de “tablelovers” que a cada dia diminui para o bem da propria web e de todos seus usuarios que nao precisam mais estar toda hora ligando para servicos de atendimento por aih soh pq esse ou aquele site nao funciona no Celular, NetBook, relogio ou seja la o que for que ele estiver usando.
Nao precisa nem ir muito longe, basta uma minuscula busca no google sobre sites brasileiros falando sobre javascript nao obtritivo e jah vais achar uma boa quantidade de material.
Postado por Everton J. Carpes - everton.carpes@gmail.com em 02/05/2009 02:36
Karmômetro (?)
tende a neutroAlias, seguindo minha propria dica de busca no google, tu chega a este artigo em portugues sobre javascript nao-obstrutivo no imasters
Postado por Everton J. Carpes - everton.carpes@gmail.com em 02/05/2009 02:53
Karmômetro (?)
tende a neutroOu ainda como comentou a Claudia regina neste post informativo sobre o que eh javascript nao-obstrutivo
“afinal eles [usuarios] nos pagam então merecem algo compatível com seja lá o que for que eles usam como navegador ou seja lá qual for o conhecimento (normalmente nulo xD) de internet!!! Vida longa ao usuário! :)”
Concordo plenamente e se alguem acha que eu nao gostaria de me ver em sua equipe pq eu sou um programador preocupado com o usuario, ohtimo pq o ultimo lugar em que eu iria querer trabalhar na vida eh ao lado dessa pessoa!
Postado por Everton J. Carpes - everton.carpes@gmail.com em 02/05/2009 02:58
Karmômetro (?)
tende a neutroValeu amigo,
Continue assim! forte abraço!
Postado por Ricardo em 02/05/2009 18:33
Karmômetro (?)
tende a neutro@Ricardo
Cara, você é completamente ultrapassado. Trabalhar pra você não deve ser fácil!
Postado por Augusto em 15/05/2009 11:28
Karmômetro (?)
tende a neutroEverton, parabéns pelo belíssimo post e por responder a altura as questões discutidas aqui..
li todas as respostas e concordo com cada palavra sua….
Continue assim, e como disse o Augusto, realmente não deve ser fácil trabalhar pra alguém que pense dessa maneira, como o Ricardo pensa… kkkkkkkkkkk
Postado por Marcelo em 15/05/2009 16:09
Karmômetro (?)
tende a neutroObrigado pelos elogios, mas o mais importante mesmo eh que a discucao seja mantida.. A opniao do Ricardo ainda reflete a opniao de varios programadores e web designers e esse talvez seja um ponto critico para a evolucao da Web, pois somente discutindo sobre assuntos do dia a dia como este eh que realmente se evolui.
Veja bem, respeito muito o trabalho da W3C e sempre que possivel acompanho suas novidades, mas vejo que soh nas discucoes do dia a dia (como esta pequena questao de botar ou nao um onclick num link), podemos realmente mudar alguma coisa a curto prazo…
Os “microformats”: http://microformats.org/ sao pra mim o maior exemplo disso, pois refletem a necessidade de tomarmos mais decisoes tecnicas praticas que mudem o estado atual da Web, explorando mais as suas possibilidades com o que ja existe hoje. Esta eh uma questao de ordem economica, muito dinheiro foi investido na infraestrutura atual da Web e ela eh pouco utilizada.
Chega a ser estranho observar que estamos discutindo como representar e organizar pecas de conhecimento – veja SKOS Simple Knowledge Oganization System Reference e nao temos uma definicao oficial do que caracteriza um Blog, precisamos de um microformat para definir que um post eh uma entry, que uma tag eh uma tag e para descrever o que eh um dialogo e entre quem.
Exatamente quando observamos o que o Ricardo alega, ao dizer que por o onclick no link nao eh errado, que surge a pergunta, nao eh errado aos olhos de quem? O fato de que a W3C nao traz uma objecao direta a isso nao significa que esteja certo, eh preciso abrirmos nossos olhos, as recomendacoes da W3C sao apenas uma parte, devemos segui-las obviamente e mais do que isso, incentivar para que as coisas andem para frente adotando versoes mais atuais de seus padroes e exigindo que fornecedores de tecnologia avancem suas plataformas adequadamente, porem isso por si, nao basta!
Nossa obrigacao eh criar os padroes, critica-los e adapta-los objetivando melhorias para todos ou para grande maioria e tentar manter ou evitar as praticas que jah foram superadas ou que prejudicam alguem.
A Web eh feita de relacoes, e relacoes evoluem.
Postado por Everton J. Carpes - everton.carpes@gmail.com em 15/05/2009 20:20
Karmômetro (?)
tende a neutroBoa explicação!
Postado por gratis em 18/05/2009 15:37
Karmômetro (?)
tende a neutroNa verdade nem precisa da Prototype ou qq. outro framework javascript: dá pra fazer nativamente, algo como
document.getElementById(“meu_id”).onclick = function() {};
Mas, é claro que com os frameworks fica muito mais simples escrever o código!
Sobre ser errado ou não… errado não é, mas em linguagens mais antigas usar goto() também não era errado. Mas é uma boa prática não usar, da mesma forma que nas interfaces web também não é uma boa prática escrever um
Vale lembrar que html deve cuidar do conteúdo, css da apresentação e javascript do comportamento.
[]s!
Postado por Chris Benseler em 19/05/2009 14:38
Karmômetro (?)
tende a neutroRespondendo ao Ricardo; eu particularmente não uso, Javascript no meu navegador. Quero deixar bem claro que isso é uma opção, falo como um usuario e não como um especialista.
Postado por Rs em 09/07/2009 00:19