Gestión de eventos relacionados con HTML en AIR

Adobe AIR 1.0 y posterior

Un sistema de gestión de eventos permite a los programadores responder a entradas del usuario y eventos del sistema de una forma conveniente. El modelo de eventos de Adobe® AIR® no solo es conveniente, sino que además cumple las normas pertinentes. Basado en la especificación de eventos del modelo de objetos de documento (DOM) de nivel 3, una arquitectura de gestión de eventos que es la norma del sector, el modelo de eventos ofrece una herramienta de gestión de eventos para programadores que es potente a la vez que intuitiva.

Eventos HTMLLoader

Un objeto HTMLLoader distribuye los siguientes eventos de Adobe® ActionScript® 3.0:

Evento

Descripción

htmlDOMInitialize

Se distribuye al crearse el documento HTML, pero antes de que se analicen scripts o se añadan a la página nodos del DOM.

complete

Se distribuye cuando se ha creado el DOM de HTML como respuesta a una operación de cargar, inmediatamente después del evento onload en la página HTML.

htmlBoundsChanged

Se distribuye cuando ha cambiado al menos una de las propiedades contentWidth o contentHeight .

locationChange

Se distribuye cuando ha cambiado la propiedad de ubicación de HTMLLoader.

locationChanging

Se distribuye antes de que cambie la ubicación de HTMLLoader debido a la navegación del usuario, una llamada a JavaScript o un redireccionamiento. El evento locationChanging no se distribuye cuando se llama a los métodos load() , loadString() , reload() , historyGo() , historyForward() o historyBack() .

Llamar al método preventDefault() del objeto de evento distribuido cancelará la navegación.

Si se abre un vínculo en el navegador del sistema, no se distribuye un evento locationChanging, ya que la ubicación de HTMLLoader no cambia.

scroll

Se distribuye siempre que el motor de HTML cambia la posición de desplazamiento. Los eventos de desplazamiento pueden deberse a la navegación a vínculos de anclaje (vínculos # ) en la página o a llamadas al método window.scrollTo() . Escribir texto en una zona de entrada de texto también puede dar lugar a un evento de desplazamiento.

uncaughtScriptException

Se distribuye cuando se produce una excepción de JavaScript en HTMLLoader y la excepción no se captura en código JavaScript.

También se puede registrar una función de ActionScript para un evento de JavaScript (por ejemplo, onClick ). Para obtener más información, consulte Gestión de eventos DOM con ActionScript .

Gestión de eventos DOM con ActionScript

Se pueden registrar funciones de ActionScript para responder a los eventos de JavaScript. Por ejemplo, tomemos el siguiente contenido HTML:

<html> 
<body> 
    <a href="#" id="testLink">Click me.</a> 
</html>

Se puede registrar una función de ActionScript como controlador de cualquier evento de la página. En el siguiente ejemplo el código añade la función clickHandler() como detector del evento onclick del elemento testLink de la página HTML:

var html:HTMLLoader = new HTMLLoader( ); 
var urlReq:URLRequest = new URLRequest("test.html"); 
html.load(urlReq); 
html.addEventListener(Event.COMPLETE, completeHandler); 
 
function completeHandler(event:Event):void { 
    html.window.document.getElementById("testLink").onclick = clickHandler; 
} 
 
function clickHandler( event:Object ):void { 
    trace("Event of type: " + event.type ); 
}

El objeto de evento distribuido no es de tipo flash.events.Event ni una de las subclases Event. Utilice la clase Object para declarar un tipo para el argumento de función del controlador de eventos.

También se puede utilizar el método addEventListener() para registrarlo para estos eventos. Por ejemplo, se podría sustituir el método completeHandler() del ejemplo anterior con el código siguiente:

function completeHandler(event:Event):void { 
    var testLink:Object = html.window.document.getElementById("testLink"); 
    testLink.addEventListener("click", clickHandler); 
}

Cuando un detector hace referencia a un elemento DOM concreto, conviene esperar a que el objeto HTMLLoader principal distribuya el evento complete antes de añadir los detectores de eventos. Las páginas HTML cargan a menudo varios archivos y el DOM de HTML no se termina de crear hasta no haberse cargado y analizado todos los archivos. HTMLLoader distribuye el evento complete una vez creados todos los elementos.

Respuesta a excepciones en JavaScript sin capturar

Tomemos el siguiente HTML:

<html> 
<head> 
    <script> 
        function throwError() { 
            var x = 400 * melbaToast; 
        } 
    </script> 
</head> 
<body> 
    <a href="#" onclick="throwError()">Click me.</a> 
</html>

Contiene una función de JavaScript, throwError() , que hace referencia a una variable desconocida, melbaToast :

var x = 400 * melbaToast;

Si una operación de JavaScript se encuentra con una operación no válida que no es capturada en el código JavaScript con una estructura try / catch , el objeto HTMLLoader que contiene la página distribuye un evento HTMLUncaughtScriptExceptionEvent. Se puede registrar un controlador para este evento, como en el código siguiente:

var html:HTMLLoader = new HTMLLoader(); 
var urlReq:URLRequest = new URLRequest("test.html"); 
html.load(urlReq); 
html.width = container.width; 
html.height = container.height; 
container.addChild(html); 
html.addEventListener(HTMLUncaughtScriptExceptionEvent.UNCAUGHT_SCRIPT_EXCEPTION, 
                           htmlErrorHandler); 
function htmlErrorHandler(event:HTMLUncaughtJavaScriptExceptionEvent):void  
{ 
    event.preventDefault(); 
    trace("exceptionValue:", event.exceptionValue) 
    for (var i:int = 0; i < event.stackTrace.length; i++) 
    { 
        trace("sourceURL:", event.stackTrace[i].sourceURL); 
        trace("line:", event.stackTrace[i].line); 
        trace("function:", event.stackTrace[i].functionName); 
    } 
}

En JavaScript se puede controlar el mismo evento con la propiedad window.htmlLoader:

<html> 
<head> 
<script language="javascript" type="text/javascript" src="AIRAliases.js"></script> 
 
    <script> 
        function throwError() { 
            var x = 400 * melbaToast; 
        } 
         
        function htmlErrorHandler(event) { 
            event.preventDefault(); 
            var message = "exceptionValue:" + event.exceptionValue + "\n"; 
            for (var i = 0; i < event.stackTrace.length; i++){ 
                message += "sourceURL:" + event.stackTrace[i].sourceURL +"\n"; 
                message += "line:" + event.stackTrace[i].line +"\n"; 
                message += "function:" + event.stackTrace[i].functionName + "\n"; 
            } 
            alert(message); 
        } 
         
        window.htmlLoader.addEventListener("uncaughtScriptException", htmlErrorHandler); 
    </script> 
</head> 
<body> 
    <a href="#" onclick="throwError()">Click me.</a> 
</html>

El controlador de eventos htmlErrorHandler() cancela el comportamiento predeterminado del evento (que es enviar el mensaje de error de JavaScript a la salida de la sentencia trace de AIR) y genera su propio mensaje de salida. Presenta el valor exceptionValue del objeto HTMLUncaughtScriptExceptionEvent. Presenta las propiedades de cada objeto del conjunto stackTrace :

exceptionValue: ReferenceError: Can't find variable: melbaToast 
sourceURL: app:/test.html 
line: 5 
function: throwError 
sourceURL: app:/test.html 
line: 10 
function: onclick

Gestión de eventos del motor de ejecución con JavaScript

Las clases del motor de ejecución admiten añadir controladores de eventos con el método addEventListener() . Para añadir una función de controlador para un evento, llame al método addEventListener() del objeto que distribuye el evento, indicando el tipo de evento y la función de gestión. Por ejemplo, para detectar el evento closing distribuido cuando un usuario hace clic en el botón de cierre de la ventana situado en la barra del título, utilice la sentencia siguiente:

window.nativeWindow.addEventListener(air.NativeWindow.CLOSING, handleWindowClosing);

Creación de una función de controlador de eventos

El código siguiente crea un archivo HTML sencillo que presenta información sobre la posición de la ventana principal. Una función de controlador denominada moveHandler() detecta si hay un evento de traslado (definido por la clase NativeWindowBoundsEvent) de la ventana principal.

<html> 
    <script src="AIRAliases.js" /> 
    <script> 
        function init() { 
            writeValues(); 
            window.nativeWindow.addEventListener(air.NativeWindowBoundsEvent.MOVE, 
                                                     moveHandler); 
        } 
        function writeValues() { 
            document.getElementById("xText").value = window.nativeWindow.x; 
            document.getElementById("yText").value = window.nativeWindow.y; 
        } 
        function moveHandler(event) { 
            air.trace(event.type); // move 
            writeValues(); 
        } 
    </script> 
    <body onload="init()" /> 
        <table> 
            <tr> 
                <td>Window X:</td> 
                <td><textarea id="xText"></textarea></td> 
            </tr> 
            <tr> 
                <td>Window Y:</td> 
                <td><textarea id="yText"></textarea></td> 
            </tr> 
        </table> 
    </body> 
</html>

Cuando el usuario desplaza la ventana, los elementos "textarea" muestran las posiciones X e Y actualizadas de la ventana:

Obsérvese que el objeto de evento se pasa como argumento al método moveHandler() . El parámetro de evento permite que la función de controlador examine el objeto de evento. En este ejemplo se utiliza la propiedad type del objeto de evento para notificar que se trata de un evento move .

Eliminación de detectores de eventos

El método removeEventListener() sirve para eliminar un detector de eventos que ya no se necesita. Siempre conviene eliminar los detectores que no se vayan a usar más. Los parámetros obligatorios incluyen eventName y listener , los mismos que para el método addEventListener() .

Eliminación de detectores de eventos de páginas HTML que permiten la navegación

Cuando el contenido HTML se desplaza, o se desecha porque se cierra la ventana que lo contiene, los detectores de eventos que hacen referencia a objetos en la página descargada no se eliminan automáticamente. Cuando un objeto distribuye un evento a un controlador que ya se ha descargado, aparece el siguiente mensaje de error: "The application attempted to reference a JavaScript object in an HTML page that is no longer loaded." (La aplicación intentó hacer referencia a un objeto JavaScript en una página HTML que ya no está cargada).

Para evitar este error, elimine los detectores de eventos de JavaScript que haya en una página HTML antes de que esta desaparezca. En el caso del desplazamiento por páginas (en un objeto HTMLLoader), elimine detector de eventos durante el evento unload del objeto window .

En el siguiente ejemplo, el código JavaScript elimina un detector de eventos para un evento uncaughtScriptException :

window.onunload = cleanup; 
window.htmlLoader.addEventListener('uncaughtScriptException', uncaughtScriptException); 
function cleanup() 
{ 
    window.htmlLoader.removeEventListener('uncaughtScriptException', 
                            uncaughtScriptExceptionHandler); 
}

Para evitar que se produzca el error al cerrar ventanas con contenido HTML, llame a una función "cleanup" (limpieza) como respuesta al evento closing del objeto NativeWindow ( window.nativeWindow ). En el siguiente ejemplo, el código JavaScript elimina un detector de eventos para un evento uncaughtScriptException :

window.nativeWindow.addEventListener(air.Event.CLOSING, cleanup); 
function cleanup() 
{ 
    window.htmlLoader.removeEventListener('uncaughtScriptException', 
                            uncaughtScriptExceptionHandler); 
}

Este error se puede evitar eliminando un detector de eventos cuando se ejecute (si el evento solo se debe gestionar una vez). En el siguiente ejemplo, el código JavaScript crea una ventana html llamando al método createRootWindow() de la clase HTMLLoader y añade un detector de eventos para el evento complete . Cuando se llama al controlador de eventos complete , elimina su propio detector de eventos con la función removeEventListener() :

var html = runtime.flash.html.HTMLLoader.createRootWindow(true); 
html.addEventListener('complete', htmlCompleteListener); 
function htmlCompleteListener() 
{ 
    html.removeEventListener(complete, arguments.callee) 
    // handler code.. 
} 
html.load(new runtime.flash.net.URLRequest("second.html"));

La eliminación de detectores de eventos que ya no se necesitan permite al recolector de datos innecesarios del sistema recuperar la memoria asociada con esos detectores.

Comprobación de detectores de eventos existentes

El método hasEventListener() permite verificar si existe un detector de eventos en un objeto.