AIR HTML with “_blank” Links

I have played with the WebKit engine of AIR which is exposed to Flex with the HTML control.

You can set the content by specifying a http location or by setting the htmlText which should be HTML code as a String. Let’s play with the HTML so create a new Flex/AIR project in Flex Builder and use this code:

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
 
	<mx:Script>
		<![CDATA[
			[Bindable]
			private var htmlCode:String = "<a href='http://adobe.com'>Adobe</a>";
		]]>
	</mx:Script>
 
	<mx:HTML htmlText="{htmlCode}" width="100%" height="100%" />
 
</mx:WindowedApplication>

If you test the application you see the link to Adobe and when you click it the Adobe site is shown. Now let’s change the htmlCode to:

private var htmlCode:String = "<a href='http://adobe.com' target='_blank'>Adobe</a>";

Everything looks the same when you test but when you click the link nothing happens but since target=”_blank” is set you would expect that the link opens in a new window. But AIR does not know where to open the link because the property navigateInSystemBrowser from the HTMLLoader class which is used by the HTML control is set to false.

If we now simply switch navigateInSystemBrowser to true the effect would be that all links open in the system browser but we (at least me) only want the target=”_blank” links to open in the system browser and a normal link (like implicit target=”_self”) would substitute the current site.

For that purpose we have to manipulate the DOM of the loaded HTML content so we can handle _blank links differently. This application then would look like this:

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
	width="1000" height="600">
 
 
	<mx:Script>
		<![CDATA[
			import mx.logging.Log;
			import mx.logging.ILogger;
 
			private static const logger:ILogger = Log.getLogger("Main");
 
			[Bindable]
			private var htmlCode:String = "<a href='http://adobe.com' target='_blank'>Adobe (in new window)</a><br/><a href='http://adobe.com'>Adobe</a>";
 
			private function onComplete(e:Event):void
			{
				var document:Object = HTML(e.currentTarget).htmlLoader.window.document;
				var anchors:Object = document.getElementsByTagName("a");
 
				for(var i:Number=0; i < anchors.length; i++) {
					var a:Object = anchors[i];
 
					// Check if anchor has target and if it is _blank so it should be handled seperatly
					var targetAttr:Object = a.attributes.getNamedItem("target");
					if(targetAttr != null && targetAttr.nodeValue == "_blank")
					{
						var urlAttr:Object = a.attributes.getNamedItem("href");
						logger.debug("set link to " + urlAttr.nodeValue);
 
						a.onmouseup = function(o:Object):void{
							o.preventDefault();
							logger.info("handle link " + o.srcElement);
							navigateToURL(new URLRequest(o.srcElement), "_blank");
						};
					}
				}
			}
 
		]]>
	</mx:Script>
 
	<mx:TraceTarget fieldSeparator="->" includeCategory="true" />
 
	<mx:HTML htmlText="{htmlCode}" width="100%" height="100%" complete="onComplete(event)" />
 
</mx:WindowedApplication>

We have added a listener for the HTML complete event and then we get all anchors from the DOM to add own listeners when they are clicked. In this inline defined event handler we call navigateToUrl with target set to “_blank” which perfectly opens the URL in the system browser.

7 comments to AIR HTML with “_blank” Links

  • Forrest Grant

    I implemented this, and it works great… except with each a.onmouseup function, it seems to update EVERY “a” not just the current one. Therefor, when it is done… every link on the page opens to the last link’s location.

    Any suggestions? Thanks.

  • Yes, all anchor tags are update. Are you maybe trying to solve something different?

  • Forrest Grant

    My Sample HTML:

    Google
    Yahoo

    Then I implement the code to open the “a”‘s in a new window. This also works great, however, clicking on both google and yahoo brings me to yahoo. Neither one will bring me to google.

  • Did you change the code in the the mouseup event listener?

  • and what does the logging say? there is logger.info(“handle link ” + o.srcElement);
    which should show which url is opened.

  • lingo

    Hello – thanks for posting this example online. I have tried to convert it to a Flash (AS3) project. The HTMLLoader loads the site fine, however when a link, which is outside of the current domain), on the loaded page is clicked it is not trapped by preventDefault. Here’s what I have so far, perhaps I’m missing something here, any help would be appreciated, thank you.

    public class AirWithJs extends MovieClip
    {

    public var myHtml:HTMLLoader;
    public var document:Object;
    public var anchors:Object;

    public function AirWithJs(){

    myHtml = new HTMLLoader();
    myHtml.navigateInSystemBrowser = false;
    myHtml.width = 1920;
    myHtml.height = 1080;
    myHtml.load(new URLRequest(“http://www.yahoo.com/”));
    addChild(myHtml);
    myHtml.addEventListener(Event.COMPLETE, onload);

    }

    public function onload(Event):void
    {
    document = myHtml.window.document;
    anchors = document.getElementsByTagName(“a”);

    for(var i:Number=0; i 7){

    a.onmouseup = function(o:Object):void
    {
    trace(“o.currentTarget.href = ” + o.currentTarget.href + ” : ” + “index = ” + o.currentTarget.href.indexOf(“http://www.yahoo.com”));

    if(o.currentTarget.href.indexOf(“http://www.yahoo.com”) != 0)
    {
    o.preventDefault();
    trace(“\t” + “trap it”);
    }
    }

    }
    }
    }