Pode ser que você se lembre do getURL que até o Flash 7 era o nosso meio de comunicação com o navegador antes da chegada do ExternalInterface ainda no AS2 e que felizmente logo na seqüência, o getURL saiu de cena para dar lugar ao navigateToURL no AS3.
Passada por esta fase tornou-se obrigatório o uso do ExternalInterface e o navigateToURL foi deixado de lado para o uso exclusivo de acesso a links. Eu até concordaria, desde que todos os pontos fossem cobertos.
Vamos a um exemplo criando dois botões, um usando o ExternalInterface e outro usando navigateToURL para executar um JavaScript. Vou utilizar neste exemplo um script para adicionar a favoritos que encontrei no site codigofonte que funciona em vários navegadores.
JavaScript:
function addFav(title,url)
{
if (window.sidebar)
{
window.sidebar.addPanel(title, url,"");
}
else if(window.opera && window.print)
{
var mbm = document.createElement('a');
mbm.setAttribute('rel','sidebar');
mbm.setAttribute('href',url);
mbm.setAttribute('title',title);
mbm.click();
}
else if(document.all)
{
window.external.AddFavorite(url, title);
}
}
Agora no Flash, fiz dois botões:
![]()
Cada um executando o mesmo JavaScript de maneiras diferentes:
ActionScript:
// Importando as classes que vamos utilizar.
import flash.external.ExternalInterface;
import flash.net.navigateToURL;
// Vamos definir o título do favorito.
var titulo:String = "Renato Pacheco";
// Aqui, definimos a url do favorito.
var url:String = "http://www.renatopacheco.com.br";
// Juntando os dois dados acima, montamos um JavaScript covencional.
// Poderiamos usar até em um link de página HTML.
// É muito importante usar a função void(0) para anular o retorno da função qe vamos executar.
var javaScript:String = "javascript:addFav('" + titulo + "','" + url+ "');void(0);";
// Aplicando a um dos botões a função ExternalInterface.
ExtIntBtn.addEventListener(MouseEvent.CLICK,function($e:MouseEvent):void{
ExternalInterface.call("addFav",titulo,url);
});
// Aplicando ao outro botão o navigateToURL.
NavToUrlBtn.addEventListener(MouseEvent.CLICK,function($e:MouseEvent):void{
navigateToURL(new URLRequest(javaScript),"_self");
});
Ao colocar o SWF na mesma página que o código JavaScript e clicar em qualquer um dos botões aparentemente temos quase o mesmo resultado:

A primeira vista temos o mesmo resultado, mas não podemos esquecer que esta ação depende do usuário para ser concluída.
No caso do navigateToURL não faz diferença pois o flash continuará sua execução normalmente mas, para o ExternalInterface a história não é bem assim. Quando é executado o ExternalInterface.call() espera um retorno do javascript seja ele nulo ou não, então espere que o usuários demore uns quinze segundos para terminar a ação e veja o que acontece:

Você pode até achar que isso não acontece e que ninguém vai levar mais de quinze segundos para adicionar um link aos favoritos, pois eu lhe digo que já aconteceu e não interessa sua justificativa, o cliente vai entrar em pânico quando vir uma mensagem dessa.
Por isso eu pensaria duas vezes antes de tornar o uso de o ExternalInterface uma regra indiscutível e a prova de falhas.
#1 by Victor Carvalho Tavernari on 26 de outubro de 2009 - 16:35
Bom artigo, muito interessante, mas sobre ExternalInterface…
Neste seu caso, entendi, o usuario demorou mais de 15 segundos para retornar um valor.. e é um risco muito grande, pois com este erro podemos perder toda funcionalidade de uma “web”.
Mas para resolver este problema acho que adicionaria no javascript um “return”, tipo return null
Assim evitaria tal erro!
Obs: Não testei esta solução, apenas uma suposição de que poderia dar certo!.. Prometo testar em breve, agora não estou podendo!
function addFav(title,url)
{
if (window.sidebar)
{
window.sidebar.addPanel(title, url,”");
}
else if(window.opera && window.print)
{
var mbm = document.createElement(‘a’);
mbm.setAttribute(‘rel’,'sidebar’);
mbm.setAttribute(‘href’,url);
mbm.setAttribute(‘title’,title);
mbm.click();
}
else if(document.all)
{
window.external.AddFavorite(url, title);
}
return null
}
Uma boa tarde e parabens pelo exemplo!
#2 by Renato Pacheco on 26 de outubro de 2009 - 22:55
Sua idéia foi muito boa mas você esta pensando como o Actionscript e não como Javascript.
No Actionscript se você faz um código como esse ele é executado por completo, não importa ser ele vai executar outras funções ou não.
Você pode fazer com que um script secundário fique processando até terminar e dar continuidade ao script principal mas, com exeção do ExternalInterface.call, nenhum espera por uma interação do usuário para continuar. É por isso que no Flash fazemos scripts em partes quando queremos que o usuário interaja com o processo.
Já no Javascript você pode fazer isso facilmente usando funções como as do exemplo. Assim ele jamais chegará a linha do return seja ela nula ou não, deixando assim o Flash na espera até que a função Javascript termine e é claro que você não pode colocar o return antes por que senão a função termina e o que você quer executar não vai acontecer.
Ainda sim, testei sua idéia e até tentei usar o void(0) pois afinal se funciona-se um dos dois casos seria excelente e resolveria o problema mas, infelizmente não deu certo.
Até mais e obrigado por participar com suas idéias.