ExternalInterface ou navigateToURL?


Alguns desenvolvedores costumam se questionar sobre o uso do ExternalInterface no lugar navigateToURL para executar um JavaScript afinal de contas a classe existe para executar esta tarefa mas, será que não existem exceções?

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:

botoes

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:

favorito

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:

timeOut

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.

VN:F [1.9.11_1134]
Rating: 3.8/5 (4 votes cast)
VN:F [1.9.11_1134]
Rating: 0 (from 0 votes)
ExternalInterface ou navigateToURL?, 3.8 out of 5 based on 4 ratings

, , , , ,

  1. #1 by Victor Carvalho Tavernari on 26 de outubro de 2009 - 16:35

    Fala Renato.

    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!

    VA:F [1.9.11_1134]
    Rating: 0.0/5 (0 votes cast)
    VA:F [1.9.11_1134]
    Rating: +1 (from 1 vote)
  2. #2 by Renato Pacheco on 26 de outubro de 2009 - 22:55

    Olá Victor.

    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.

    VN:F [1.9.11_1134]
    Rating: 0.0/5 (0 votes cast)
    VN:F [1.9.11_1134]
    Rating: 0 (from 0 votes)
(não será publicado)


Google plus one provided by online-casino.eu.com