package com.oyvindnordhagen.bannerads
{
import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.display.Graphics;
import flash.display.LoaderInfo;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.external.ExternalInterface;
import flash.geom.Rectangle;
import flash.net.URLRequest;
import flash.net.navigateToURL;
import flash.system.ApplicationDomain;
/**
* Enables clickTag functionality in AS3 banner ads. Automatically detects clickTag url if
* present (both clickTag and clickTAG) and creates an invisible button that is always on top
* of the display list with similar bounds as the clickTarget argument. Logging is on by default
* and will write a minimum of info to the trace output, FireBug and to Olog if available.
* @author Oyvind Nordhagen
*
* Copyright notice: You are free to use and distribute this class as
* much as you like, as long as you give proper credit by leaving this
* class header comment in.
*
* @see www.oyvindnordhagen.com/blog/olog
* @see www.oyvindnordhagen.com
*/
public class ClickTag
{
private var _url:String;
private var _window:String;
private var _campaignPrefix:String;
private var _hitArea:Sprite;
private var _clickTarget:DisplayObjectContainer;
private var _logging:Boolean;
/**
* Enables clickTag functionality in AS3 banner ads. Automatically detects clickTag url if
* present (both clickTag and clickTAG) and creates an invisible button that is always on top
* of the display list with similar bounds as the clickTarget argument. Logging is on by default
* and will write a minimum of info to the trace output, FireBug and to Olog if available.
* @author Oyvind Nordhagen
*
* Copyright notice: You are free to use and distribute this class as
* much as you like, as long as you give proper credit by leaving this
* class header comment in.
*
* @see www.oyvindnordhagen.com/blog/olog
* @see www.oyvindnordhagen.com
* @param root The root instance containing LoaderInfo with the clickTag parameter, typically just pass "root"
* @param clickTarget (optional) The item on the display list that serves as the clickable area, typically just pass "this",
* or you can pass in something else in case you don't want the entire stage to be clickable. Leaving this argument at the
* default null will prevent setting up a click listener. In which case, you can call the "go" function manually.
* @param campaignName (optional) String that identifies this banner among several others. This identifyer is appended to any log messages.
* @param newWindow (optional) Pass in "true" (default) to launch landing page in a new window, or fals to use the same window.
* @param logging Tunrs on/off logging.
* @return ClickTag instance
* @see ClickTag.go()
*/
public function ClickTag ( root:DisplayObject, clickTarget:DisplayObjectContainer = null, campaignName:String = "", newWindow:Boolean = true, logging:Boolean = true ):void
{
_logging = logging;
root.loaderInfo.addEventListener( Event.COMPLETE, _onLoaded, false, 0, true );
_campaignPrefix = (campaignName) ? "[" + campaignName + "] " : "";
_setClickTarget( clickTarget );
_window = newWindow ? "_blank" : "_self";
}
/**
* Navigates to the predefined of specified url. Note that when specifying a url as an argument to this function,
* you effectively bypass the tracking systems associated with clickTag, and statistics for these calls will not be recorded.
* @param url The url to navigate to
* @return void
*/
public function go ( url:Object = null ) : void
{
if (!_url && !(url is String) )
{
_log( "Target url missing" );
return;
}
var urlTarget:String = (url as String) || _url;
var broswer:String = _jsOut( "function getBrowser(){return navigator.userAgent}" );
if (broswer.indexOf( "Firefox" ) != -1 || broswer.indexOf( "MSIE 7.0" ) != -1 && _window == "_blank")
{
_jsOut( "window.open", urlTarget );
}
else
{
navigateToURL( new URLRequest( urlTarget ), _window );
}
}
/**
* Toggles the visibility of the clickable area. Implemented for debug purposes.
*/
public function set hitAreaVisible ( visible:Boolean ):void
{
if (_hitArea)
{
_hitArea.alpha = (visible) ? 1 : 0;
}
}
/**
* Returns an invisible button to serve as the clickable are of the banner.
* @param sourceBounds A Rectangle or DisplayObject instance to define the bounds of the clickable area.
* @return Sprite with clik event listener.
*/
public function getHitArea ( sourceBounds:Object ) : Sprite
{
var clickTarget:Rectangle;
if (sourceBounds is DisplayObject)
clickTarget = (sourceBounds as DisplayObject).getBounds( sourceBounds.parent || sourceBounds );
else if (sourceBounds is Rectangle)
clickTarget = sourceBounds as Rectangle;
var hit:Sprite = new Sprite();
var g:Graphics = hit.graphics;
g.beginFill( 0x00ffff, 0.5 );
g.drawRect( 0, 0, clickTarget.width, clickTarget.height );
hit.x = clickTarget.x;
hit.y = clickTarget.y;
hit.alpha = 0;
hit.buttonMode = true;
hit.useHandCursor = true;
hit.addEventListener( MouseEvent.CLICK, go );
return hit;
}
private function _setClickTarget ( clickTarget:DisplayObjectContainer = null ) : void
{
if (clickTarget)
{
_clickTarget = clickTarget;
_hitArea = getHitArea( clickTarget );
if (clickTarget.stage)
{
clickTarget.stage.addChild( _hitArea );
clickTarget.stage.addEventListener( Event.ADDED, _moveHitAreaToTop );
}
else
{
clickTarget.addChild( _hitArea );
clickTarget.addEventListener( Event.ADDED, _moveHitAreaToTop );
}
}
}
private function _moveHitAreaToTop ( e:Event ) : void
{
if (_clickTarget.stage)
_clickTarget.stage.addChild( _hitArea );
else
_clickTarget.addChild( _hitArea );
}
private function _onLoaded ( e:Event ) : void
{
var params:Object = (e.target as LoaderInfo).parameters;
for (var key:String in params)
{
if (key.toLowerCase() == "clicktag")
{
_url = params[key] as String;
break;
}
}
if (_url)
{
_log( "clickTag found: " + _url );
}
else
{
_log( "clickTag missing" );
}
}
private function _jsOut ( func:String, ... arguments ):String
{
var result:String;
if (ExternalInterface.available)
{
try
{
result = ExternalInterface.call( func, arguments );
}
catch (e:Error)
{
result = "";
}
}
else
{
result = "";
}
return result;
}
private function _log ( text:String ) : void
{
if (!_logging)
return;
text = _campaignPrefix + text;
_jsOut( "console.log", text );
trace( text );
/*
* Sends log messages to Olog if installed. Can be safely left in even though
* Olog is not used, but feel free to delete it.
*
* For information about Olog, check out www.oyvindnordhagen.com/blog/olog
*/
if (ApplicationDomain.currentDomain.hasDefinition( "no.olog.Olog" ))
{
ApplicationDomain.currentDomain.getDefinition( "no.olog.Olog" )["trace"]( text, 1, this );
}
}
}
}