Adobe Acrobat Connect Pro Goes Mobile

by Tom Krcha on February 25, 2010


Rough edges rectangle class

by Slavomír Durej on February 25, 2010

For a recent project I needed to create buttons with rough edges background. Gave it a quick google and couldn’t find a class for this, so I made a new one.

Demo

It uses drawPath command so requires flash plugin ver 10.

here’s the constructor :

/**
* @param w: width
* @param h: height
* @param col: background color
* @param distortion: amount of edges distortion (wawe-iness)
* @param density : density of distored vertexes
*/
new RoughEdgedRectangle(w, h, col, distortion, density);

so to create and add to stage you simply call something like :var sq:RoughEdgedRectangle = new RoughEdgedRectangle(500,250,0xFF00FF,3,100);
addChild(sq);
 

I made this little demo app that gives a visual preview of what the changing parameters does. It has view source enabled so you can download the source code.

Pixel Bender Disco

by josefchutka on February 18, 2010

While playing with pixel bender, I created some simple sahders that when combined, reminds me of winamp visualizations effects. Feel free to use any in your own projects.

Click and drag mouse to make some disco effects. (wait while page header flash finishes loading so it runs smoothly)

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
    enterFrame="enterFrame()" applicationComplete="init()"
    backgroundColor="#ffffff" frameRate="50"
    mouseMove="mouseMoveHandler(event)"
    mouseDown="mouseDownHandler(event)"
    mouseUp="mouseUpHandler(event)">
<mx:Script>
<![CDATA[
    private var drawing:Boolean = false;
    private var color:uint = 0x0;
    private var bitmap:Bitmap = new Bitmap();
    private var lineX:Number = 0;

    [Bindable]
    private var fps:Number = 0;
    private var fpsDate:Date = new Date();
    private var fpsFrames:uint = 0;

    [Bindable]
    private var rotationTime:uint = 0;

    [Bindable]
    private var blurTime:uint = 0;

    [Bindable]
    private var colorizeTime:uint = 0;

    [Bindable]
    private var twirlTime:uint = 0;

    [Embed(source="../pbj/rotation.pbj", mimeType="application/octet-stream")]
    private static const ROTATION_CLASS:Class;
    private static const ROTATION_SHADER:Shader = new Shader(new ROTATION_CLASS());

    [Embed(source="../pbj/blur.pbj", mimeType="application/octet-stream")]
    private static const BLUR_CLASS:Class;
    private static const BLUR_SHADER:Shader = new Shader(new BLUR_CLASS());

    [Embed(source="../pbj/colorize.pbj", mimeType="application/octet-stream")]
    private static const COLORIZE_CLASS:Class;
    private static const COLORIZE_SHADER:Shader = new Shader(new COLORIZE_CLASS());

    [Embed(source="../pbj/twirl.pbj", mimeType="application/octet-stream")]
    private static const TWIRL_CLASS:Class;
    private static const TWIRL_SHADER:Shader = new Shader(new TWIRL_CLASS());

    private function init():void
    {
        placeholder.addChild(bitmap);
    }

    private function mouseDownHandler(event:MouseEvent):void
    {
        drawing = true;
        color = Math.random() * 0xffffff;
    }

    private function initGraphics():void
    {
        container.graphics.clear();
        container.graphics.moveTo(mouseX, mouseY);
        container.graphics.lineStyle(10, color, 1);
    }

    private function mouseUpHandler(event:MouseEvent):void
    {
        drawing = false;
    }

    private function mouseMoveHandler(event:MouseEvent):void
    {
        if(!drawing)
            return;
        container.graphics.lineTo(event.localX, event.localY);
    }

    private function countFps():void
    {
        if(++fpsFrames < 10)
            return;
        fps = Math.round(1 / (new Date().time - fpsDate.time) * 10000);
        fpsDate = new Date();
        fpsFrames = 0;
    }

    private function get w():Number
    {
        return container.width;
    }

    private function get h():Number
    {
        return container.height;
    }

    private function enterFrame():void
    {
        countFps();

        if(!container || !container.width)
            return;

        var bitmapData:BitmapData = new BitmapData(w, h, true, 0x000000);
        bitmapData.draw(bitmap);
        if(rotationCheckBox.selected)
            addRotation(bitmapData, 0.1);
        if(blurCheckBox.selected)
            addBlur(bitmapData);
        if(colorizeCheckBox.selected)
            addColorize(bitmapData, color);
        if(twirlCheckBox.selected)
        {
            var radius:Number = Math.min(w / 2, h / 2);
            addTwirl(bitmapData, 10, new Point(w / 4, h / 2), radius);
            addTwirl(bitmapData, -10, new Point(w / 4 * 3, h / 2), radius);
        }

        addAutoFill();
        bitmapData.draw(container);

        bitmap.bitmapData = bitmapData;
        initGraphics();
    }

    private function addAutoFill():void
    {
        lineX = (lineX > w) ? 0 : (lineX + 15);
        container.graphics.moveTo(lineX - 15, h / 3 * 2);
        container.graphics.lineTo(lineX, h / 3 * 2);
    }

    private function addRotation(bitmapData:BitmapData, rotation:Number):void
    {
        rotationTime = new Date().time;
        ROTATION_SHADER.data.src.input = bitmapData;
        ROTATION_SHADER.data.src.width = w;
        ROTATION_SHADER.data.src.height = h;
        ROTATION_SHADER.data.rotation.value = [rotation];
        ROTATION_SHADER.data.tx.value = [w / 2];
        ROTATION_SHADER.data.ty.value = [h / 2];

        var job:ShaderJob = new ShaderJob(ROTATION_SHADER, bitmapData);
        job.start(true);
        rotationTime = new Date().time - rotationTime;
    }

    private function addBlur(bitmapData:BitmapData):void
    {
        blurTime = new Date().time;
        BLUR_SHADER.data.src.input = bitmapData;
        BLUR_SHADER.data.src.width = w;
        BLUR_SHADER.data.src.height = h;

        var job:ShaderJob = new ShaderJob(BLUR_SHADER, bitmapData);
        job.start(true);
        blurTime = new Date().time - blurTime;
    }

    private function addColorize(bitmapData:BitmapData, color:uint):void
    {
        colorizeTime = new Date().time;
        var r:Number = ((color >> 16) & 0xFF) / 0xFF - 0.5;
        var g:Number = ((color >> 8) & 0xFF) / 0xFF - 0.5;
        var b:Number = (color & 0xFF) / 0xFF - 0.5;

        COLORIZE_SHADER.data.src.input = bitmapData;
        COLORIZE_SHADER.data.src.width = w;
        COLORIZE_SHADER.data.src.height = h;
        COLORIZE_SHADER.data.color.value = [r / 40, g / 40, b / 40];

        var job:ShaderJob = new ShaderJob(COLORIZE_SHADER, bitmapData);
        job.start(true);
        colorizeTime = new Date().time - colorizeTime;
    }

    private function addTwirl(bitmapData:BitmapData, angle:Number,
        center:Point, radius:Number):void
    {
        twirlTime = new Date().time;
        TWIRL_SHADER.data.oImage.input = bitmapData;
        TWIRL_SHADER.data.oImage.width = w;
        TWIRL_SHADER.data.oImage.height = h;
        TWIRL_SHADER.data.radius.value = [radius];
        TWIRL_SHADER.data.center.value = [center.x, center.y];
        TWIRL_SHADER.data.twirlAngle.value = [angle];

        var job:ShaderJob = new ShaderJob(TWIRL_SHADER, bitmapData);
        job.start(true);
        twirlTime = new Date().time - twirlTime;
    }
]]>
</mx:Script>
<mx:UIComponent width="100%" height="100%" id="placeholder" />
<mx:Container id="container" width="100%" height="100%" backgroundAlpha="0"/>
<mx:VBox paddingLeft="10" paddingTop="10">
    <mx:Text text="fps: {fps} / 50" />
    <mx:HBox>
        <mx:CheckBox id="rotationCheckBox" selected="true"/>
        <mx:Label text="rotation {rotationTime} ms" />
    </mx:HBox>
    <mx:HBox>
        <mx:CheckBox id="blurCheckBox" selected="true"/>
        <mx:Label text="blur {blurTime} ms" />
    </mx:HBox>
    <mx:HBox>
        <mx:CheckBox id="colorizeCheckBox" selected="true"/>
        <mx:Label text="colorize {colorizeTime} ms" />
    </mx:HBox>
    <mx:HBox>
        <mx:CheckBox id="twirlCheckBox" selected="false"/>
        <mx:Label text="twirl {twirlTime} ms" />
    </mx:HBox>
</mx:VBox>
</mx:Application>

Rotation pixel bender

<languageVersion : 1.0;>

kernel RotationFilter
<
	namespace : "sk.yoz";
	vendor : "Yoz";
	version : 1;
	description : "Image rotation over transform point";
>
{
	input image4 src;
	output pixel4 dst;

	parameter float tx
	<
		minValue: float(0.0);
		maxValue: float(4096.0);
		defaultValue: float(0.0);
		description: "The amount of movement along the x axis to the right, in pixels.";
	>;

	parameter float ty
	<
		minValue: float(0.0);
		maxValue: float(4096.0);
		defaultValue: float(0.0);
		description: "The amount of movement down along the y axis, in pixels.";
	>;

	parameter float rotation
	<
		minValue: float(0.0);
		maxValue: float(4096.0);
		defaultValue: float(0.0);
		description: "Rotation in radians";
	>;

	void evaluatePixel()
	{
		float2 pos = outCoord();
		float rc = cos(rotation);
		float rs = sin(rotation);
		float dx = pos.x - tx;
		float dy = pos.y - ty;
		dst = sampleNearest(src, float2(
			tx + rc * dx + rs * dy,
			ty + rc * dy - rs * dx));
	}
}

Blur pixel bender

<languageVersion : 1.0;>

kernel BlurFilter
<
	namespace : "sk.yoz";
	vendor : "Yoz";
	version : 1;
	description : "Simple blur";
>
{
	input image4 src;
	output pixel4 dst;

	void evaluatePixel()
	{
		float2 pos = outCoord();

		dst = 1.0 / 9.0 * (
			sampleNearest(src, pos - float2(-1.0, -1.0))
			+ sampleNearest(src, pos - float2(0.0, -1.0))
			+ sampleNearest(src, pos - float2(1.0, -1.0))
			+ sampleNearest(src, pos - float2(-1.0, 0.0))
			+ sampleNearest(src, pos - float2(0.0, 0.0))
			+ sampleNearest(src, pos - float2(1.0, 0.0))
			+ sampleNearest(src, pos - float2(-1.0, 1.0))
			+ sampleNearest(src, pos - float2(0.0, 1.0))
			+ sampleNearest(src, pos - float2(1.0, 1.0)));
	}
}

Colorize pixel bender

<languageVersion : 1.0;>

kernel ColorizeFilter
<
	namespace : "sk.yoz";
	vendor : "Yoz";
	version : 1;
	description : "Simple colorize";
>
{
	input image4 src;
	output pixel4 dst;

	parameter float3 color
	<
		minValue: float3(-1.0, -1.0, -1.0);
		maxValue: float3(1.0, 1.0, 1.0);
		defaultValue: float3(0.0, 0.0, 0.0);
		description: "Color";
	>;

	void evaluatePixel()
	{
		dst = sampleNearest(src, outCoord());
		dst.r += color.r;
		dst.g += color.g;
		dst.b += color.b;
	}
}

Twirl pixel bender effect is available for download here

Flash Gaming on NVIDIA Tablets

by Tom Krcha on February 17, 2010


Inline Images

by josefchutka on February 16, 2010

Have you ever heard about inline images? Inline images use the data URI scheme to embed images directly within web pages. As defined by RFC 2397, data URIs are designed to embed small data items as “immediate” data, as if they were referenced externally. This basicaly means, you can insert base64 encoded byte code of any image directly into html file. Using inline images saves HTTP requests over externally referenced objects. Data URIs can potentially store any type of data, not just images!

This example creates snapshot of flash application (on left side) and dynamicly (using javascript) creates inline image (right side) with base64 encoded bytes in src attribute. (right side is html <img>)

Application source:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical"
    enterFrame="enterFrame()" borderStyle="solid" borderColor="#000000"
    backgroundColor="#ffffff">
<mx:Script>
<![CDATA[
    import com.adobe.images.PNGEncoder;
    import com.dynamicflash.util.Base64;

    private function enterFrame():void
    {
        if(!container || !container.width)
            return;

        container.graphics.beginFill(Math.random() * 0xffffff, Math.random());
        container.graphics.drawCircle(
            Math.random() * container.width,
            Math.random() * container.height, Math.random() * 30);

    }

    private function makeSnapshot(source:DisplayObject):void
    {
        var script:String = 'var img = document.getElementById("img");'
            + 'if(!img)'
            + '{'
                + 'img = document.createElement("IMG");'
                + 'img.id="img";'
                + 'document.body.appendChild(img);'
            + '}'
            + 'img.src="' + getSrc(source) +'";';
        ExternalInterface.call("function(){" + script + "}");
    }

    private function getByteArray(source:DisplayObject):ByteArray
    {
        var bitmapData:BitmapData = new BitmapData(source.width, source.height);
        bitmapData.draw(source);
        var bitmap:Bitmap = new Bitmap(bitmapData);
        return PNGEncoder.encode(bitmapData);
    }

    private function getSrc(source:DisplayObject):String
    {
        var byteArray:ByteArray = getByteArray(source);
        return 'data:image/png;base64,'
            + Base64.encodeByteArray(byteArray);
    }
]]>
</mx:Script>
<mx:Container id="container" width="100%" height="100%"/>
<mx:Button label="Make Snapshot" click="makeSnapshot(this)"/>
</mx:Application>

Data URLs save HTTP requests. When combined with CSS sprites, data URLs can save numerous HTTP requests. It would be interesting to see if data URLs can be combined with USEMAPS or make a data URL CSS sprite. Data URLs are a convenient way to create self-enclosed web pages that don’t rely on external objects to render.

  • Save HTTP requests, avoids adding to object overhead
  • Save concurrent thread – browsers default to two simultaneous connections per hostname
  • HTTPS requests are simplified and performance improved

Well, for now I have no idea how can flash benefit from data urls :-) but if I come to something I let you know.

Processing Audio in ActionScript 3 and Pixel Bender

by josefchutka on February 16, 2010

Recently I was trying to make some noise with flash, and soon I realized that audio processing is not that easy thing as it may look like. Anyway here is a list of some interesting articles and examples with gain, equalizer, pitch, effects, pixel bender, I have came across while gathering information.

Volume, Equalizer, Effects, Pitch

Spectrum Analyzer

Theory and Hints

Správné načasování pro prodej aplikace

by Robin on February 14, 2010

Správné načasování pro prodej aplikace

Pokud přemýšlíte o tom jak se dostat s vaší aplikací k potenciálním zakazníkům App Store, kterých je už přes 58 miliónů (34 miliónů iPhone a 24 miliónů iPod touch) tak potřebujete vědět několik klíčových věcí.

Jak správně načasovat prodej vaší aplikace. Co mít již připraveno před odesláním ke schválení. Co dělat v následujících dnech po doručení emailu, že vaše aplikace je schválená.

 

Shrňme úkoly, které jste si již připravili dle tipů v minulém článku:

  • máte připravený propagační web na jednoduché doméně .com optimálně včetně formuláře pro přihlášení k odběru novinek
  • připravili jste video, které ukazuje co vaše aplikace umí (max. 1 min, 30 sec je ideální čas)
  • řekli jste o vaší aplikaci všem kamarádům a jejich kamarádům, podělili jste se o tuto super novinku na sociálních sítích
  • máte založený Twitter účet pro vaší aplikaci nebo brand
  • založený účet na iPhone Dev Center
  • máte připravené pěkné screenshoty a všechny další potřebné podklady pro submit
  • v neposlední řadě máte hotovou a funkční aplikaci ve verzi 1.0

Tip #1: Pokud web vaší aplikace vypadá k světu, přihlašte jej do různých css galerií webů jako např. CSS Manía, CSS Import, BestWebGallery atp. Docela se nám to v tapmates osvědčilo — na našem nedávno spuštěném webu jsme tím získali cca 3,5 až 4 tisíce návštěvníků denně (první týden) a poté konstantně tisíc denně, do dnes. Návštevnost je potřeba využít, proto klademe důraz na newsletter, který je dominantní částí našeho webu a získáváme tím denně nové “klienty”, které zajímá s čím přijdeme přístě.

Tip #2: Pokud je vaše aplikace hra, je dokázáno, že když je první screenshot přímo ukázkou ze hry tak vám to může zvednout sales.

Načasování

App Store Review Status

Apple schvaluje aplikace v průměru za 7 dní. Tudíž řekněme, že dnes je 1.března, aplikaci budete mít schválenou + – kolem 8. března, abyste spustili vše potřebné, domluvili si recenze na portálech, nahonili pár followerů a udělali menší buzz před spuštěním, tak si nastavíte datum publikování na né dřív než. 1.dubna, což je apríl (toho také můžete skvěle využít a vytvořit nějaký podpůrný virálek).

Tímto tahem si zajistíte klidné spuštění, kdy máte již vše nachystáno a pár lidí už o vaší aplikaci ví. V opačném případě by se aplikace automaticky vložila do App Store v okamžiku schválení a vy byste pravděpodobně neměli nic nachystáno, což není optimální start.

Co očekávat v průběhu schvalování

Můžete sledovat vývoj vašeho požadavku přes Dev Center, kde v seznamu vašich aplikací uvidíte u každé zároveň popisek, který indikuje v jakém stavu právě jste (Waiting for Upload, In Review apod.). Můžete si také nastavit notifikace emailem o změně.

Odesláno

Nyní nastává chvíle, kdy byste měli spustit web (teasing), vložit video na YouTube či Vimeo, začít uživatele lákat — pomalu odhalovat vaší aplikaci (např. každý den ukázat novou část UI) a připravovat si novináře na recenze.

Recenze

Tyto PR články jsou pro vaší aplikaci nejlepší možnost jak může být vystřelena do výšin. Recenze na hojně navštěvovaných webech jsou k (ne)zaplacení (např. takový TechCrunch efekt dokáže posunout aplikaci o 500 míst nahoru či shodit web server — proto je dobré být na podobné situace technologicky připraven).

Pokud máte dobrou aplikaci, bude se o vás psát (propagace per huba je mocná) a nemusíte pro to nic extra dělat, stačí odpovídat na dotazy uživatelů a občas přihodit nějaký sneak peek.

Tip: Na vašem webu by měl být ke stažení press kit, který obsahuje např. logo, ikonku, wallpaper, nějaký art work — prostě cokoliv líbivého co můžou novináři použít v článku.

Na druhou stranu si recenze můžete pokusit zajistit následovně:

  • přes kontakty kamarádů na novináře (ano, takto se dělá hodně recenzí)
  • vložením tipu na stránkách magazínů (skoro každý web ma sekci “Submit a News Tip” a když budete mít kliku a váš email si přečtou, tak možná bude recenze)
  • zadarmo na prMac
  • můžete si najmout PR společnost, která se vám o to postará
  • kontaktovat novináře přímo např. přes Twitter (tak tohle je metoda hop nebo trop :-))
  • zaplatit si recenzi na placených sekcích blogů

Tip: Email, který budete posílat do redakcí by měl mít v předmětu “Název aplikace + Free Promo Codes for Readers” promo kódy (3-5) přiložte do obsahu zprávy. Tím si zajistíte větší čitelnost recenze když vyjde. Zpráva by měla být krátká a jednoduchá; přiložte odkaz na YouTube video a web.

Zaměřte se hlavně na weby/blogy/magazíny, které mají samozřejmě něco společného s vaší cílovou skupinou a důležité je to nevzdát. I malá recenze je dobrá.

Pozitivní recenze vám mohou pomoci a zvýšit prodej, ale většinou se jedná o chvilkovou záležitost. Dejte možnost novinářům napsat o nečem jako první — když jím povíte, že máte něco cool a můžou o tom napsat první, tak to velmi rádi udělají a obě dvě strany mohou být spokojené.

Příště se můžete těšit na další rady a zkušenosti ze světa iPhone marketingu. Zaměřím se na cenu aplikace a jak vydělávat na free aplikacích.

Quick tip: ExternalInterface.call is synchronous!

by josefchutka on February 12, 2010

It is a little wonder to me how flash player communicates with JavaScript. Calls are fully synchronous, it works as those (fp and js) were fully integrated into each other. To simulate this lets test some simple flow:

Flash Player calls JavaScript
    JavaScript calls FlashPlayer
        FlashPlayer do some stuff and finishes
    JavaScript finishes
FlashPlayer continues

Following flex application runs simple JavaScript:

document.getElementById("flash").universalCallback();
return "synchronous return";
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
    applicationComplete="init()">
<mx:Script>
<![CDATA[
    [Bindable]
    private var lastResult:String = "";

    private function init():void
    {
        ExternalInterface.addCallback("universalCallback", universalCallback);
    }

    private function runScript():void
    {
        var script:String = 'document.getElementById("flash").universalCallback();' +
                'return "synchronous return";';

        var result:String = ExternalInterface.call("function(){" + script + "}");
        lastResult += result + "\n";
    }

    private function universalCallback(... rest):void
    {
        lastResult += "universalCallback" + "\n";
    }
]]>
</mx:Script>
<mx:Button click="runScript()" label="Run"/>
<mx:TextArea width="100%" height="100%" text="{lastResult}" />
</mx:Application>

and results are logged into TextArea:

universalCallback
synchronous return

This means that ExternalInterface.call() is synchronous and waits until called JavaScript finishes. Just after that, flash player moves on the next line. This interesting behaviour makes flash player to hold (but not to freeze) on one line while it is able to continue on different execution (universalCallback()).

Notice, JavaScript to ActionScript data can be sent via ExternalInterface.addCallback() or simple by synchronous return:

var result:String = ExternalInterface.call("function(){" + script + "}");

however, you can not use eval method this way!

var result:String = ExternalInterface.call("eval", script);

Full JavaScript Access From ActionScript (update)

by josefchutka on February 10, 2010

Have you ever tought about accessing DOM from ActionScript? In fact, you can do it and even far more. You can create and call JavaScript methods and objects, access cookies, change styles… All you need is correct AllowScriptAccess parameter within your flash object. No framework needed here, no hacks, ExternalInterface takes care.

Following application runs JavaScript from textarea:

Application. Line 16 does all the fun :-)

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
    applicationComplete="init()">
<mx:Script>
<![CDATA[
    [Bindable]
    private var lastResult:String = "";

    private function init():void
    {
        ExternalInterface.addCallback("universalCallback", universalCallback);
    }

    private function runScript():void
    {
        ExternalInterface.call("eval", script.text);
    }

    private function universalCallback(... rest):void
    {
        lastResult = String(rest[0]);
    }
]]>
</mx:Script>
<mx:HBox width="100%" height="100%">
    <mx:TextArea id="script" width="100%" height="100%">
        <mx:text>
            <![CDATA[
function myFunction(){
    var flash = document.getElementById("flash");
    var data = document.childNodes[1].innerHTML;
    flash.universalCallback(data);
}

myFunction();
alert(document.getElementsByTagName('title')[0].innerHTML);
            ]]>
        </mx:text>
    </mx:TextArea>
    <mx:TextArea width="100%" height="100%" text="{lastResult}" />
</mx:HBox>

<mx:Button click="runScript()" label="Run"/>
</mx:Application>

HTML template

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" dir="ltr">
<head>
    <title>Full Javascript Access</title>
    <meta http-equiv="Content-Type" content="application/xml; charset=utf-8" />
    <meta http-equiv="Cache-Control" content="no-cache" />
    <meta http-equiv="expires" content="1" />
    <meta http-equiv="pragma" content="no-cache" /> 

    <meta name="author" content="http://studio.yoz.sk" />
    <meta name="description" content="Full Javascript Access" />
    <meta name="robots" content="all" /> 

    <script type="text/javascript" src="js/swfobject.js"></script>
    <script type="text/javascript">
    <!--
        var flashvars = {}

        var params = {
            allowscriptaccess: "always"
        };
        var attributes = {
            id: "flash",
            name: "flash"
        };
        swfobject.embedSWF("Tests.swf", "alternative", "100%", "100%", "10.0.0",
            "flash/expressInstall.swf", flashvars, params, attributes);
    //-->
    </script>

    <style type='text/css'>
    <!--
        body {margin:0px;overflow:hidden;}
        html, body, object, embed {width:100%;height:100%;outline:none;}
    -->
    </style>
</head>
<body>
    <div id="alternative">
        <a href="http://www.adobe.com/go/getflashplayer">
            <img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" />
        </a>
    </div>
</body>
</html>

No additional nothing here just:

  • line 20: allowscriptaccess: “always” (“sameDomain” may also be used)
  • line 24: tip – add name attribute with swfobject so ExternalInterface.objectID will get correct value

Considerations of using eval:

  • Improper use of eval opens up your code for injection attacks
  • Debugging can be more challenging (no line numbers, etc.)
  • eval’d code executes more slowly (no opportunity to compile/cache eval’d code)

Update (Feb 11, 2010): You can use either eval call:

ExternalInterface.call("eval", script.text);

or wrap your script into anonymous function:

ExternalInterface.call("function(){" + script.text + "}");

Personally, I do not see any difference in execution, it seems to be the same, maybe some performance testing would clarify it. What do you think?

Simple chat with P2P NetGroup in FP 10.1

by Tom Krcha on February 9, 2010