How can I include JavaScript dynamically from Flash using ActionScript? - javascript

I have a flash movie that requires some JavaScript from an include file but I'd like to be able to embed it anywhere without requiring a script tag.
Is there a way to include an external JavaScript file using the ExternalInterface library so I can call the methods in the JavaScript include file later?
Thanks!

Not many people realize it, but you can write inline Javascript in your .as files, and even pass in values, like so:
var someVarInAS : String = 'foo';
var someOtherVarInAS : int = 10;
var jsXML : XML =
<script type="text/javascript">
var someVarInJS = '{someVarInAS}';
var someOtherVarInJS = {someOtherVarInAS};
<![CDATA[
//here be code
alert( 'this comes from flash: ' + someVarInJS + ', ' + someOtherVarInJS );
]]>
</script>;
ExternalInterface.call( "function js_" + ( new Date().getTime() ) + "(){ " + jsXML + " }" );
A few things to note:
the {} inside the javascript code will translate to the value of whatever variable you put in between
the cdata section enables you to write whatever javascript code you want, otherwise the compiler can complain.
All javascript code called through externalinterface should be placed in a named function, otherwise it will not work in a few browsers. In this code snippet I employ a little trick (new Date().getTime()) to ensure the function always has a unique name and can't conflict with another one with possibly the same name.
don't forget the ; behind </script> it tells the compiler your javascript ends there

everything javascript can do, can be done with externallinterface. i think the best way would be to port the js script to ac.
this is how you can include a tag:
ExternalInterface.call("document.getElementsByTagName('head')[0].appendChild(document.createElement('script'))");
ExternalInterface.call("document.getElementsByTagName('script')[document.getElementsByTagName('head')[0].getElementsByTagName('script').length-1].setAttribute('type', 'text/javascript')");
ExternalInterface.call("document.getElementsByTagName('script')[document.getElementsByTagName('head')[0].getElementsByTagName('script').length-1].setAttribute('src', 'http://your.server/your.js')");

Related

Allow the user to change their own JavaScript

I'm teaching students how to write JavaScript, so I've got this on the page:
<textarea name="PgmJS">console.log(1);</textarea>
<script id="PgmJS">
</script>
What I'd like to do is:
$('textarea[name=PgmJS]').on('keyup',PgmJSKeyUp);
function PgmJSKeyUp() {
$('#PgmJS').text('function init() {' + $(this).val() + '}');
init();
}
But the browser is saying that init() is not defined.
It doesn't work this way, you need the evil eval:
function PgmJSKeyUp() {
eval($(this).val());
}
You could also use Function, setTimeout or setInterval (if you clear it), which are as evil as eval when used with strings.
Or, if you really want to use <script> element,
function PgmJSKeyUp() {
var $s = $('<script type="text/javascript">');
$s.text($(this).val());
$('body').append($s);
}
But keep in mind that JS code inside <script> elements is only executed when they are added to the document.
That's because you're specifying the init function inside the textarea's text property - which by default, does not get picked up by the browser's JS compiler.
You will need to define the init function as normal JS code, and execute the custom JS code inside it. I smell an eval() coming on (ugh!) :|

Actionscript 3 Inline Javascript

i have this javascript code:
<script type="text/javascript">
$(document).ready(function() {
$("body").append('<div id="ajaxBusy" class="ajaxBusy"></div>');
</script>
My code works fine so far but i thought to load this javascript code inside an AS3.
Is there any possibility to make it happen? To write inline javascript code inside my flash;
I found this code but i dont know how to implement
import flash.external.ExternalInterface;
var someVarInAS : String = 'foo';
var someOtherVarInAS : int = 10;
var jsXML : XML =
<script type="text/javascript">
var someVarInJS = '{$("body").append('<div id="ajaxBusy" class="ajaxBusy"></div>');}';
var someOtherVarInJS = '{$('#login').fadeIn();}';
<![CDATA[
alert( 'this comes from flash: ' + someVarInJS + ', ' + someOtherVarInJS );
]]>
</script>;
ExternalInterface.call( "function js_" + ( new Date().getTime() ) + "(){ " + jsXML + " }" );
Can anyone help me to do this?
Here's a link to an example to show how ExternalInterface works
https://dl.dropboxusercontent.com/u/15551758/eitest.zip
What's happening is that once the Flash object is loaded on the page, it uses
ExtenalInterface.call();
to call a javascript function that's been registered on the page that the swf is on. In the case of the example:
ExternalInterface.call('toJS', 'flash text');
calls the javascript function toJS and sends one argument, a string "flash text".
The opposite direction is supported as well. Calling a function on the flash object and passing in arguments will send them to flash. You register ExternalInterface callbacks with:
ExternalInterface.addCallback(callback_name, flash_function_to_call);
In the example, we register in flash a callback:
ExternalInterface.addCallback("fromJS", this.fromJS);
that listens for an event from javascript called fromJS and calls an internal function fromJS. For the example, I've added a textbox on the stage to visualize the data coming in from javascript.
Please let me know if this answers your question or if you need more explanation.
Edit:
If you must inject javascript, you can pass in a function that does the injection as the first parameter of ExternalInterface.call:
var inject:String = "function(){var body = document.getElementsByTagName('body')[0], testNode = document.createElement('div'); testNode.innerHTML = 'This is a test'; body.appendChild(testNode);}";
ExternalInterface.call(inject);
But I'd recommend against it. Keeping languages separate will lead to more concise and easier to debug code.

passing parameters into ANT javascript task?

In my ANT scripts, I sometimes write tasks runnning javascript with Rhino.
However, I am at a loss as to how pass parameters into these tasks. Any ideas?
For example... here is an example of such a task:
<script language="javascript"> <![CDATA[
//some nonsense to fake out rhino into thinking we've a dom, etc.
this.document = { "fake":true };
this.window = new Object( );
this.head = new Object( );
eval(''+new String(org.apache.tools.ant.util.FileUtils.readFully(new java.io.FileReader('coolJavascript.js'))));
//... do some stuff
var s = java.io.File.separator;
var fstream = new java.io.FileWriter( ".." + s + "build" + s + "web" + s + "js" + s + "coolChangedJavascript.js" );
var out = new java.io.BufferedWriter( fstream );
out.write( jsCode );
out.close( );
]]> </script>
For using scripting to define an ant task you can use the scriptdef task instead of script. With scriptdef there are predefined objects to access the attributes and nested elements in your task.
This works for accessing attributes from javascript in Ant:
<scriptdef name="myFileCheck" language="javascript">
<attribute name="myAttribute" />
<![CDATA[
importClass(java.io.File);
importClass(java.io.FileReader);
importClass(java.io.BufferedReader);
var fileName = attributes.get("myAttribute"); //get attribute for scriptdef
var reader = new BufferedReader(new FileReader(new File(fileName)));
//... etc
project.setProperty("my.result", result));
]]>
</scriptdef>
Then can just go: <myFileCheck myAttribute="./some.file" /> same as you would for a regular ant task.
Also possible to use filesets etc if you want, more details at: http://ant.apache.org/manual/Tasks/scriptdef.html
The nice thing is you can define your tasks inline in your ant script, instead of writing them in Java then having to build and include the class files.
You will need to use Java1.6 (or later), or have apache BSF in your classpath.
Two suggestions come to mind. First, you can access Ant properties from within the javascript. There are examples in the documentation you refer to:
var x = project.getProperty( "my.property" );
can be used in the script to get the value of a property set in the XML, perhaps like this:
<property name="my.property" value="x" />
Second, you might consider using a scriptdef, which will allow you to define attributes and child elements that you can easily access from the javascript.

embedding javascript variable within razor syntax

I have a method that looks like this
function endcall_click(leadid) {
document.location = '#Url.Action("index","dispo",new{id=leadid})/';
}
Of course it doesn't work because it treats "leadid" as a server side variable but I want to inject the javascript variable passed into the method.
I tried wrapping lead id in but that didn't work.
function endcall_click(leadid) {
document.location = '#Url.Action("index","dispo",new{id="<text>leadid</text>"})/';
}
Any ideas?
You can't inject javascript variable to a script that is evaluated at the server simply because at the moment this script executes and generates the output this variable hasn't yet come to existence. The only way to achieve this is to manipulate the resulting string:
function endcall_click(leadid) {
document.location = '#Url.Action("index", "dispo")/' + leadid;
}
The drawback is that this assumes manipulating the routes in javascript and if you decide to change them on the server the code might break.
I finally found the solution (*.vbhtml):
<script type="text/javascript">
function razorsyntax() {
/* Double */
#(MvcHtmlString.Create("var szam =" & mydoublevariable & ";"))
alert(szam);
/* String */
var str = '#stringvariable';
alert(str);
}
</script>

Pass vars to JavaScript via the SRC attribute

In my HTML file I have linked to the JS with:
src="myscript.js?config=true"
Can my JS directly read the value of this var like this?
alert (config);
This does not work, and the FireFox Error Console says "config is not defined". How do I read the vars passed via the src attribute in the JS file? Is it this simple?
<script>
var config=true;
</script>
<script src="myscript.js"></script>
You can't pass variables to JS the way you tried. SCRIPT tag does not create a Window object (which has a query string), and it is not server side code.
Yes, you can, but you need to know the exact script file name in the script :
var libFileName = 'myscript.js',
scripts = document.head.getElementsByTagName("script"),
i, j, src, parts, basePath, options = {};
for (i = 0; i < scripts.length; i++) {
src = scripts[i].src;
if (src.indexOf(libFileName) != -1) {
parts = src.split('?');
basePath = parts[0].replace(libFileName, '');
if (parts[1]) {
var opt = parts[1].split('&');
for (j = opt.length-1; j >= 0; --j) {
var pair = opt[j].split('=');
options[pair[0]] = pair[1];
}
}
break;
}
}
You have now an 'options' variable which has the arguments passed. I didn't test it, I changed it a little from http://code.google.com/p/canvas-text/source/browse/trunk/canvas.text.js where it works.
You might have seen this done, but really the JS file is being preprocessed server side using PHP or some other language first. The server side code will print/echo the javascript with the variables set. I've seen a scripted ad service do this before, and it made me look into seeing if it can be done with plain ol' js, but it can't.
You need to use Javascript to find the src attribute of the script and parse the variables after the '?'. Using the Prototype.js framework, it looks something like this:
var js = /myscript\.js(\?.*)?$/; // regex to match .js
var jsfile = $$('head script[src]').findAll(function(s) {
return s.src.match(js);
}).each(function(s) {
var path = s.src.replace(js, ''),
includes = s.src.match(/\?.*([a-z,]*)/);
config = (includes ? includes[1].split('=');
alert(config[1]); // should alert "true" ??
});
My Javascript/RegEx skills are rusty, but that's the general idea. Ripped straight from the scriptaculous.js file!
Your script can however locate its own script node and examine the src attribute and extract whatever information you like.
var scripts = document.getElementsByTagName ('script');
for (var s, i = scripts.length; i && (s = scripts[--i]);) {
if ((s = s.getAttribute ('src')) && (s = s.match (/^(.*)myscript.js(\?\s*(.+))?\s*/))) {
alert ("Parameter string : '" + s[3] + "'");
break;
}
}
Whether or not this SHOULD be done, is a fair question, but if you want to do it, http://feather.elektrum.org/book/src.html really shows how. Assuming your browser blocks when rendering script tags (currently true, but may not be future proof), the script in question is always the last script on the page up to that point.
Then using some framework and plugin like jQuery and http://plugins.jquery.com/project/parseQuery this becomes pretty trivial. Surprised there's not a plugin for it yet.
Somewhat related is John Resig's degrading script tags, but that runs code AFTER the external script, not as part of the initialization: http://ejohn.org/blog/degrading-script-tags/
Credits: Passing parameters to JavaScript files , Passing parameters to JavaScript files
Using global variables is not a so clean or safe solution, instead you can use the data-X attributes, it is cleaner and safer:
<script type="text/javascript" data-parameter_1="value_1" ... src="/js/myfile.js"></script>
From myfile.js you can access the data parameters, for instance with jQuery:
var parameter1 = $('script[src*="myfile.js"]').data('parameter_1');
Obviously "myfile.is" and "parameter_1" have to match in the 2 sources ;)
You can do that with a single line code:
new URL($('script').filter((a, b, c) => b.src.includes('myScript.js'))[0].src).searchParams.get("config")
It's simpler if you pass arguments without names, just like function calls.
In HTML:
<script src="abc.js" data-args="a,b"></script>
Then, in JavaScript:
const args=document.currentScript.dataset.args.split(',');
Now args contains the array ['a','b'].

Categories