I've been all over here and can't find an answer. I have a .swf sitting in an HTML page and I am trying to call a function inside of it from javascript. I can talk out from flash to the javascript but I can't get it to talk back in. I know I am targeting the object properly because I use console.log() on it and confirms what it is targeting.
I'm triggering the test from flash, calling a javascript function from inside the .swf, and having that function call the internal Flash function.
Flash Code:
//adds callback
ExternalInterface.addCallback("sendToFlash", flashTalkedTo);
//function called by the callback
public function flashTalkedTo():void{
//runs another function in javascript to log a string
ExternalInterface.call("callMe")
}
//calls javascript that tries to talk to Flash
ExternalInterface.call("catchFromFlash")
Javascript Code:
//function called by Flash that initiates
function catchFromFlash(){
talkToFlash()
}
//function that tries to talk to flash
function talkToFlash(){
document.getElementById('Noodleverse').sendToFlash()
}
//function called by Flash in the end to confirm call made
function callMe(){
console.log("Call Me")
}
Any help works, thanks!
Flash, and plugins in general, are a little bit fiddly. They don't behave quite like normal elements, and their functions don't behave quite like normal functions. For example, you can't save the element into a value and call a function from that. You also need to be careful because in some browsers the object is used and in others the embed is used.
The best way to call a function is to use swfobject (https://code.google.com/p/swfobject/) to abstract everything. Personally though, I use this (based on experience, maybe somebody can offer improvements):
HTML:
<object id="myplugin" ...>
...
<embed name="myplugin" ... />
</object>
JavaScript:
var o1=document.myplugin;
if(o1&&!!o1.myFlashFunction){
return document.myplugin.myFlashFunction(); // DO NOT USE o1 here. It will fail.
}
var o2=window.myplugin;
if(o2&&!!o2.myFlashFunction){
return window.myplugin.myFlashFunction(); // DO NOT USE o2 here
}
The first case (document) is for most new browsers. For example, Chrome will find the embed object. The second (window) is for IE and finds the object (IE, at least old IE, ignores embed). I'm not 100% sure the second is needed, because IE might also work with document, so call that voodoo code. Also window.myplugin will give an array of all matching elements in Chrome, FireFox, etc. (but we expect those to already be taken care of)
Related
I'm trying to modify/limit/prevent access to certain JS commands of my browser. For example commands like navigator.clipboard; However, I'm not sure how to approach this.
Is it possible to override these commands with user-defined javascript injected in the page, or do i have to edit the browser's javascript compiler and re-compile it from source for this?
I'm not really familiar with browsers and want to save time by knowing a general direction to follow. Thanks
First of all navigator.clipboard is not a function, but here is an example using the read function of navigator.clipboard:
navigator.clipboard.read = function (originalFunction) {
return function (yourParamsYouWantForThisFunction) {
// Do Stuff you wanna do before the real call. For example:
console.log(yourParamsYouWantForThisFunction);
// Call the original function
return originalFunction.call();
};
}(navigator.clipboard.read); // Pass the original function reference as a parameter
You may wonder, why there are two function statements:
The first one is there, so that we can pass the original function at runtime. If we would not do that, we would not be able to access the original navigator.clipboard.read function.
The second function is the actual function, that you will be using later, when you call navigator.clipboard.read().
So here' s the piece of code. I'm very new to JavaScript so don't be afraid to explain the obvious
$(".my-css-class").on("click", function() {
($(this).attr("data-property-1"), $(this).attr("data-property-2"), this);
});
There's an element in the .jsp page that looks like this:
<i class="clickMe"></i>
I know the .jsp creates a link-icon, and that the above JavaScript is an event handler. I know that it passes these 3 values as arguments another JavaScript method:
function doStuff(prop1, prop2, obj) {
if (prop1 == 'foo') {
//do stuff with prop2
}
else{
// do stuff with obj
}
}
It all works fine. What I want to know is what exactly is going on to make it work? I can't find anything in the code that connects what the event-handler returns to the 'doStuff' java-script function.
The names are totally different, so it's not reflection, it can't be parameter matching because there's other functions with the same number and type of parameters in the file, it can't be convention based because it still works if I find/replace the name of the function to gibberish.
I guess basically I'm asking what this line is doing:
($(this).attr("data-property-1"), $(this).attr("data-property-2"), this);
tl;dr: I'm at a loss, I know how the properties get as far as the onClick event-handler's anonymous function - but how does JavaScript know to pass them as arguments the to the doStuff() function?
the onClick event is a standard event triggered on click of any clickable html element and is automatically raised by the DOM.
You are hooking in to this by listening on any matched ".my-css-class" elements for an onClick Event.
The jquery syntax ".on" has been simplified over time and allows you to hook into any number of events like "submit" - OnSubmit event , or "load" - onLoad Event
Wherever your on("click", myFunction) event hook is picked up, your myFunction will execute.
Looking at your second point...
because it still works if I find/replace the name of the function to gibberish.
The DoStuff function will be found and replaced across all files in your site? or page? or open tabs? , so therefore it must exist somewhere as "doStuff(" or "giberish(".
so when you do a global find/replace, do each one slowly, until you locate it.
Finally, when you do a view source in the browser, this should either explicitly show you the doStuff function, or at the very least give you a clue as to satelite files loaded at runtime, where you can go and investigate.
Use firebug in firefox to debug loaded resources; the ".net tab" to view external loaded resources and the html/javascript they might contain. (for example: your master page might be loading in an embeded resource that contains the doStuff method, becuase of a user or server control reference in that master page)
Also have a look at this:
http://www.developerfusion.com/article/139949/debugging-javascript-with-firebug/
You can step through the javascipt piece by peice until it hits the doStuff method.
Just remember to set at least 1 breakpoint ;-)
As you can tell by the title, I am having some trouble with AS3 ExternalInterface and jQuery / swfobject.
ActionScript :
if (ExternalInterface.available) {
ExternalInterface.call('init');
ExternalInterface.addCallback('testFunc', returnFunc)
}
function returnFunc():void {
ExternalInterface.call('alertFunc');
}
jQuery:
function init() {
alert('init');
$('#swf_object').testFunc();
}
function alertFunc() {
alert('finished');
}
Obviously that implies the object has the id 'swf_object'
I have also tried getting the object by the following:
document.getElementById('swf_object')
document.getElementById('swf_object')[0]
$('#swf_object')[0]
To no avail.
It's giving the first alert ('init') but then not doing the last one. I'm completely baffled and hope someone can point out my mistakes! (there's bound to be a massively obvious one somewhere)
The problem is that you're calling out to the JavaScript init() which calls the Flash testFunc() before you're made testFunc available (which happens only after the call out to init() completes).
To fix this, simply swap the two lines to this:
ExternalInterface.addCallback('testFunc', returnFunc); // Needs to be available before it's used
ExternalInterface.call('init');
As for getting the Flash object in JavaScript, you can do it directly with document.getElementById('swf_object'), but it's possible using jQuery too:
var swf = $('#swf_object').get(0); // Get the actual object without the jQuery wrapper
I am trying to use javascript to run AS3 functions. When I attempt to compile I'm getting an "Access of undefined property" error message.
I've read a few things online about this but I'm still not understanding it. I want to have the flash file always listening for javascript.
Here is my AS3 code:
ExternalInterface.addCallback("song4", PauseMusicExt);
And my Javascript & HTML:
function returnVar3(song3) { return this[song3]; }
<input type="submit" name="playButton" id="playButton" value="Submit" onClick="returnVar('song3')"/>
Edit: Here is the pauseMusic function:
function pauseMusicExt():void
{
songPosition = channel.position;
channelSilence.stop();
channel.stop();
channel2.stop();
btnPlay.mouseEnabled = true;
}
I'm not sure about the extend of your app but you've got your addCallback function parameters mixed up..
See the doc, the first parameter is the name you want to expose the function as to javascript, the second is the actual internal AS3 function you want to trigger.
So the declaration should likely be something like:
ExternalInterface.addCallback("song4", pauseMusic);
(assuming that your function in the same scope as where you call addCallback)
That statement will create a "song4" method that you can call on your flash dom object
var fl = document.getElementById('myflashobject');
fl.song4()
After there's the issue that pauseMusic want a parameter (looks like you've made it a mouse event handler). You probably want to have a clean method that doesn't require a parameter like an internal as3 event param. Rewrite pauseMusic so it doesn't require it (you might need to create another method to handle the mouse event internally - like onPause(evt:MouseEvent), which then calls pauseMusic.
Edit: I don't know if a lot of people thought about doing that, but you can also totally use external interface to call firebug's console.log function to send messages to Firebug from flash (it's really helpful for debugging ExternalInterface issues, or any other flash problems - see the ExternalInterface.call function)
Hope u want to pause the audio player.
AS code :
ExternalInterface.addCallback("sndToAS",rcvdFmJS);
function rcvdFmJS(val){
if (val == "pause"){
audioPause();
}
}
JS code :
document.getElementById("movie").sndToAS("pause");
Is there a way to get a list of the exposed functions from a Flash object? For example, you could get a list of all methods in an object by executing:
for (var i in object) {
if (typeof object[i] == "function") {
console.log(i);
}
}
The only issue is that this won't expose any methods registered through the ExternalInterfaces API. I can try and see if the function exists (object['method']) and it tells me it is a function, but I would have to guess every existing method in this manner.
NOTE: Obviously, I don't have access to the actionscript.
Just hit this question, a tad to late it seems, but I'll post an answer anyways ;)
Using IE10 (windows 7) it worked perfectly fine for me to list all my methods like so:
var obj = document.getElementById('flashObj');
for(var prop in obj){
var fx = obj[prop];
if(obj.hasOwnProperty(prop) && (typeof fx == 'function') && /eval\(instance/.test(fx)){
console.log(prop)
}
}
Note that this did not work in Chrome or Firefox and only with the exact regexp since IE10 does not report "native code" as the other browsers do.
The problem is even worse: the information is neither available in ActionScript. You register a new function as ExternalInterface.addCallback('foo', foo) and you can not list already registered callbacks.
Just a guess but see if it works. All the ExternalInterface functions should be defined in the global namespace. Try embedding the SWF in an HTML page and get all the Javascript functions defined for the page after the page has loaded. List of global user defined functions in JavaScript?
The list of functions should be those defined in the SWF file.
I guess the only way to go is to parse the SWF file bytecode and try to gather the calls to ExternalInterface.addCallback method.
http://www.google.com/search?q=parse+avm2
My instinct is no, ExternalInterface is essentially a black box, or black letter box, you poke things through and sometimes things come back, but you can't open the door to see what's inside.
Without documentation as to what's been exposed in the SWF, the only other suggestion is decompiling the swf to have a look at the source.