« Things I want to see in Adobe Apollo | Main | JavaScript injection through ActionScript »

June 16, 2006

A MXML component that embeds JavaScript in html

I know subject line is confusing but I am not able to think a better one. I have written a Adobe Flex 2.0 component(JavaScript.as), which can be used as MXML tag in Flex 2.0 applications. You can write JavaScript code as text of this MXML tag. When your application loads, all that JavaScript code would be exported to HTML container's context.

Confused? Let code speak rather than me :)

Sample MXML application using this component (test.mxml):-


<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="com.abdulqabiz.utils.*" width="100%" height="100%">
<JavaScript>
<![CDATA[
var myName = "Abdul Qabiz";
function saySomething (str)
{
alert (str);
}
function sayHelloWorld ()
{
alert ("Hello World!");
}
]]>
</JavaScript>
<mx:Script>
<![CDATA[
import flash.external.ExternalInterface;
private function invokeSayHelloWorld ()
{
ExternalInterface.call ("sayHelloWorld");
}
]]>
</mx:Script>
<mx:Button label="invoke javascript sayHelloWorld () function" click="invokeSayHelloWorld ()"/>
</mx:Application>

HTML code that embeds test.swf(output of above code):-


<html>
<head>
<!-- swfobject -->
<script type="text/javascript" src="http://blog.deconcept.com/swfobject/swfobject_source.js"></script>
</head>
<body>
<div id="flashcontent" class="playerContent" >You don't have Flash Player 9.</div>
<script type="text/javascript">
var swfObj = new SWFObject ("JavaScriptComponentTest.swf","JavaScriptComponentTest", "300", "300", "9", "#C0D4DD", true);
swfObj.write("flashcontent");
</script>
<a href="javascript:void(0)" onclick="saySomething ('hey')" >invoke saySomething ()</a><br />
<a href="javascript:void(0)" onclick="sayHelloWorld ()" >invoke sayHelloWorld ()</a><br />
<a href="javascript:void(0)" onclick="alert (myName);">show myName </a><br />
</body>
</html>

See an example Or Download (zip 2.5kb).

The code is available under the MIT license.

Disclaimer: I have only tested this in FireFox on Windows. So please drop a comment, if doesn't work in your system.

Posted by Abdul Qabiz at June 16, 2006 03:31 AM

Comments

Subject of this post could be either of these:-

- JavaScript injection through ActionScript
- JavaScript injection through MXML
- Inject JavaScript through MXML or JavaScript


Listing, so that search-engines can index this comment and show this entry..

-abdul


Posted by: Abdul Qabiz at June 16, 2006 04:50 AM

Really cool, I thought I would be the only one to see usefullness in something like this. Though I dont use your version, I have something very similar.

Question though, In my component I had to strip out "\n", "\r", etc.... how did you get around this? navigateToURL decode this stuff for you? ExternalInterface did not.

One other thing to think about, should the script keep track of what it has sent to HTML already? What if a component contains JavaScript and you need two instances of the component? Would that send the script twice? If so, are two sayHello() functions allowed in javascript? Didnt test if thats the case but I have a static array to keep track of all source properties so it only sends it once.

Posted by: Scotty at June 16, 2006 10:56 AM

Neat.

About the subject, you'd have a much better chance if you linked to the blog entry with the various subject lines as the anchor text.

Posted by: Manish Jethani at June 16, 2006 05:29 PM

Manish, remember this is the idea I discussed long. I wanted that compiler folks or FB team do that...

Anyways, hope this idea has some use-cases. I have some in my mind. I would post some examples.

Scotty, I tried using ExternalInterface then I realized I don't need it because it is one way call. And I also faced issues you mentioned.

I have not checked but you can create multiple instances of JavaScript component and inject scripts...It should work, I am just using "eval()" to make it work.

If you try to inject a function, which is already present. New injection would override the things...


-abdul

Posted by: Abdul Qabiz at June 16, 2006 08:16 PM

ah, I didnt know if you specified two of the same functions in javascript it would just override the previous one.

Use cases...
if your component relies on javascript and dont want to have to make sure the calling page contains a special wrapper.
Another being a way to hide your javascript logic, kinda of an encryption method. Im not sure if there are Javascript debuggers that pay attention to eval()'ed calls.

Posted by: Scotty at June 16, 2006 11:07 PM

Thanks for the code sample Abdul. I used your class to inject javascript that sets the focus to an swf, instead of modifying the html wrapper page. I think that mySWF.focus() only works in IE, but that's better than nothing. At least now the function wont be accidentally overwritten by Flex Builder.

Best Wishes,
Tim Hoff

Posted by: Tim Hoff at June 27, 2006 09:02 AM



Post a comment




Remember Me?

(you may use HTML tags for style)