I am having in issue with IE passing a string back into an swf using the EternalInterface class in Flash CS4.
I have an swf with the following code:
var externalString:String = ExternalInterface.call("IncomingJS")
which is inside an event listener attached to an Event.ENTERFRAME and an if statement waiting for ExternalInterface.available.
The IncomingJS function looks like:
function IncomingJS() {
return stringFromHTML;
}
and sits on the HTML page with the swf.
I am able to successfully get the externalString variable and procceed with the rest of the AS3 script in Firefox, Safari and Chrome, but not in IE.
If I add in an alert (stringFromHTML) before the return statement in the Javascript, I get the value of the stringFromHTML spammed, which looks like Flash is firing the function at the right rate.
The embed code in HTML for the swf is a little simple:
<object width="750" height="200" id="controlledScale"><param name="movie" value="http://www.myURL.com/controlledScale.swf"><param name="allowScriptAccess" value="sameDomain" /><embed src="http://www.myURL.com/controlledScale.swf" width="750" height="200" allowScriptAccess="sameDomain"></embed></object>
Any help or advice would be greatly appreciated.
Thanks,
DavidB
Edit
I realise how poor the SWF embed code is.
Unfortunately, the HTML code is actually working within a 3rd party HTML generator, and one of it's limitations is that I can only have a single line (with unlimited length) of html at a time.
Are the other options (swfObject etc) able to run either with no line breaks in the code, or would I be asking for trouble with Javascript and the SWF to, instead of embedding the SWF directly, use something like an iFrame and refer to a 'proper' flash delpoyment html file?
Kind of at a point on this one where I'm not even sure where the problem is actually located. The swf's are find sending out to Javascript across all browsers, just not getting info back in IE only.
You must add an id to the object tag to work in IE.
<object width="750" id="myflash" height="200"><param name="movie" value="http://www.myURL.com/controlledScale.swf"><param name="allowScriptAccess" value="sameDomain" /><embed src="http://www.myURL.com/controlledScale.swf" width="750" height="200" allowScriptAccess="sameDomain"></embed></object>
I pretty sure there is a security "feature" in IE that stops JS being called too many times from Flash, to stop it crashing the browser.
Is there a reason why you have to call it every frame?
I'd suggest against this at all costs as it's putting a LOT of extra stress on the browser.
***** EDIT *****
If you want to call an ExternalInterface method from JS -> Flash in IE you have to reference the object slightly differently, like this:
function thisMovie(movieName) {
if (navigator.appName.indexOf("Microsoft") != -1) {
return window[movieName];
} else {
return document[movieName];
}
}
Then once you're sure the string you want to pass is constructed correctly you can call it like this from the JS:
thisMovie( "theFlashElementID" ).giveMeMyStringAlready();
Then in your Flash you would have something like this:
if( ExternalInterface.available )
{
ExternalInterface.addCallback( "giveMeMyStringAlready", handleTheStringFromJS );
}
else
{
handleTheFactIDontHaveExternalInterfaceAvailable();
// the only reason this would be is if container that
// is embedding the swf isn't fully loaded by the browser
}
The standout line from the AS3 docs regarding ExternalInterface is this:
Note: When using the External API with
HTML, always check that the HTML has
finished loading before you attempt to
call any JavaScript methods.
This:
Unfortunately, the HTML code is
actually working within a 3rd party
HTML generator
is the problem.
The swf is sitting inside a <form> tag.
At the browser stage, there is a huge volume of really verbose code, and I missed the tags at the very beginning and end of the html code.
Thanks for the help. If I have learnt nothing else from the experience, it's to be full with the question and look well beyond the immediate problem, breaking each element down as fully as I can.
Related
I've been recently trying to implement a flash application, which at some point needs to be embedded via html. It looks something like>
<embed src=".." quality=".." ... and at some point FlashVars="&firstparam&secondparam..."
What I am trying to do is implement a dropdown, which would when pressed change that FlashVars parameter so the app shows something different. I've tried with
document.getoElementByID().FlashVars="new parameters"
but it doesn't work (it works perfectly for highlited default parameters such as src, height, width...)
I've also tried to write whole embed part again with javascript snippet, but it also didn't work. How is this done in javascript? I'm a beginner in this field so any help is greatly appreciated.
Thanks.
To understand why your code didn't work, you should understand what's flashvars parameter and how it's working.
Adobe said about that here, for example :
The FlashVars parameter of the HTML <OBJECT> tag sends variables into the top level of a SWF file when it loads in a web browser. The <OBJECT> tag is used to add SWF files to HTML pages. The <EMBED> tag can also be used, but is older and now obsolete.
So here we can understand that those variables are loaded when the SWF is loaded and that's why even if you've changed the flashvars parameter, that will do nothing, absolutely nothing to that loaded SWF which should be loaded again to get them (variables) applied.
So to do that, take this simple example :
HTML :
<div id='swf_container'>
<embed id='swf_object' src='swf.swf' flashvars='id=1' />
</div>
JavaScript :
// change the flashvars attribute
var swf_object = document.getElementById('swf_object');
swf_object.setAttribute('flashvars', 'id=2');
var swf_container = document.getElementById('swf_container');
var inner_html = swf_container.innerHTML;
// reload the swf object
swf_container.innerHTML = '';
swf_container.innerHTML = inner_html;
This manner is, of course, working but maybe it's not a good idea to reload the SWF object everytime we need it to do something, and that's why we have ExternalInterface to communicate between the SWF and JavaScript.
So in the case where you've access to the ActionScript code to create that SWF, you can use ExternalInterface to call any function in your SWF when it's already loaded.
For that, take this example :
ActionScript :
if(ExternalInterface.available)
{
// registers an AS function to be called from JS
ExternalInterface.addCallback('from_JS_to_AS', from_JS);
}
function from_JS(id:int) : void
{
// use the id sent by JS
}
JavaScript :
var swf_object = document.getElementById('swf_object');
swf_object.from_JS_to_AS(1234);
... and don't forget to use swfobject to avoid some browsers compatibility and to be sure that you establish the communication between your ActionScript side and the JavaScript one ...
Hope that can help.
Just do this :
$('embed') // targets the embed tag in the DOM
.attr("attribute-name","attribute-value");
Here's an example : https://jsfiddle.net/DinoMyte/1a6mwb13/2/
I am trying do some modification to an greasemonkey userscript to implement a feature I need. The code is like
showAddress:function(addrString,type)
{
this.addrBox=$('<div id="batchPublish"></div>')
.append('<div id="batchHeader"></div>')
.append('<div id="batchContent" style="float:left;clear:both"></div>');
.........
var batchContent=this.addrBox.find('#batchContent')
.append('<pre width="300" style="text-align:left" id="batchedlink"></pre>');
this.addrBox.find('#batchedlink').css({'width':'500px','height':'250px','overflow':'auto','word-wrap': 'break-word'})
.append(addrString);
$.blockUI({message:this.addrBox,css:{width:"520px",height:"300px"}}); }
Basically this code writes data to html. What I want to implement is to have "addrString" written to an iframe embedded. Now It's in the "pre" tag. I have tried many approaches but still no luck. Iframe was always empty.
I am completely a novice in javascript and unclear whether this is possible.
Thank you for the help.
Since you are adding the iFrame in the same domain, then you can manipulate its contents like this:
(See it in action at jsBin.)
$("#batchContent").append ('<iframe id="batchedlink"></iframe>');
/*--- Compensate for a bug in IE and FF, Dynamically added iFrame needs
some time to become "DOM-able".
*/
setTimeout ( function () {
var iframeBody = $("#batchedlink").contents ().find ("body");
iframeBody.append (addrString);
},
333
);
NOTE:
For a Chrome userscript, you apparently don't need the timer delay. But for FF and IE 8 (the other 2 browsers I double-checked), a dynamically added iFrame is not manipulable until after it has "settled" for some reason. This seems to take about 200 mS.
A statically loaded iFrame does not have this lag, see the jsBin demo.
Sort of hard to tell exactly what you're asking -- but if you want to know whether or not you can append DOM elements to an iFrame, the answer is "no".
In my actionscript file I have:
ExternalInterface.addCallback("loadHotspotsXMLCallback", hotspotsXMLCallback);
In html I have:
<embed width="100%" height="100%" align="middle" type="application/x-shockwave-flash" salign="" allowscriptaccess="sameDomain" allowfullscreen="false" menu="false" name="FloorplanViewer" bgcolor="#FFFFFF" id="FloorplanViewer" devicefont="false" wmode="transparent" scale="showall" loop="false" play="true" pluginspage="http://www.adobe.com/go/getflashplayer" quality="high" flashvars="..." src="swf/FloorplanViewer_V110228b.swf">
In JS I have:
$("FloorplanViewer")["loadHotspotsXMLCallback"](response.responseText);
And I've also tried:
window["loadHotspotsXMLCallback"](response.responseText)
and
document["loadHotspotsXMLCallback"](response.responseText)
But the JS part DNW in IE, and it does in FF and GC.
Does anybody know why?
I've read this documentation on using ExternalInterface, and while my problem is occuring for IE8, I tried the follwing suggested IE7 solutions mentioned there:
making sure that the added external callback name is not the same as the internal callback name for the actionscript code above.
delaying the code that adds the callback by 500ms
But these changes had no effect.
I suggest trying it as simple as possible from my article, http://work.arounds.org/issue/10/calling-flash-functions-from-javascript/
<object id="flash" data="file.swf" width="420" height="300"></object>
<script>
onload = function() {
var flash = document.getElementById('flash');
flash.NextFrame();
}
</script>
First try converting your embed to an object, then just a simple get element by ID after window load. Also try alert( 'functionName' in flash ); to make sure the method exists.
I would try something like this:
var fpViewer = document["FloorplanViewer'] || window["FloorplanViewer"];
fpViewer.loadHotspotsXMLCallback(response.responseText);
Also, I lose track on what the best practice is for inserting Flash into pages nowadays. But I'd definitely wrap that embed element with an object element, to ensure maximum cross browser compatibility.
Rich
I had a really hard time solving problems like that with IE 6, 7, 8, etcs..
Some things that helped, in order of priority:
delaying the code that CALLS the callback
If you have more than 1 SWF using that, try not to attach all the SWF files that adds callbacks/etcs at the same time
Two or more concurrent javascript calls ( addCallbacks / ExternalInterface.call / etcs ) normally results in some IE fail.
If you need to do many javascript calls, may be is the case to implement a "Javascript call stack" that will call each operation after another one with a little delay.
really hope it helps
i had really bad times struggling with IE / cross-browser compatibility with more than 1 swf file in the same page needing control from/to javascript
It seems this is a known problem and has been asked several times before here in SO however I do not see anything specific to jQTouch so I thought I would give it a try.
jQT will dynamically load pages when a link is clicked. In this page I would like to include something like
<script>
$.include('javascriptfile.js', function() {alert('do something with results of this file to an already existing div element');};
</script>
The $.include is a jquery plugin I found that mimics the $.load with a few more smarts added to it. Tested to work on FF but not in Chrome or most importantly, Safari.
The alert is never displayed. FireBug never shows the javascript even being loaded. If I put an alert before the $.include I still do not see anything.
I have tried an onclick/ontap event that would then run this code that was included in the head tag, no luck.
Edit: I am using the r148 revision of jQT. This was working prior to moving to this version, i believe.
Did you try to add the javascript file using one of these two methods:
Static Way:
<script type="text/javascript">
function staticLoadScript(url){
document.write('<script src="', url, '" type="text/JavaScript"><\/script>');
}
staticLoadScript("javascriptfile.js");
modifyDivFn(processFnInFile());
</script>
Dynamic way:
<script type="text/javascript">
function dhtmlLoadScript(url){
var e = document.createElement("script");
e.src = url;
e.type="text/javascript";
document.getElementsByTagName("head")[0].appendChild(e);
}
onload = function(){
dhtmlLoadScript("javascriptfile.js");
modifyDivFn(processFnInFile());
}
</script>
After the include you can call a function that does the processing you want (that being processFnInFile()) which result will be passed to modifyDivFn (and modify the div you want.) You could do this in one function, just to illustrate the idea.
Source: Dynamically Loading Javascript Files
Well Geries, I appreciate your help but ultimately the answer required a drastic rethinking of how I was using JQTouch. The solution was to move everything to an onclick event and make all the hrefs link to #. This might be what you were talking about Geries.
In the onclick function I do the logic, preloading, loading of the page through my own GET through jquery, then use the public object jQT.goTo(div, transition). This seems to get around the WebKit bugs or whatever I was running into and this now owrks on FireFox, Chrome, Safari, iPhone, and the lot.
I do run into a few animation issues with JQT but I think these are known issues that I hope Stark and the gang at JQTouch are working on.
I need to background load some WAV files for an HTML page using AJAX. I use AJAX to get the details of the WAV files, then use the embed tag, and I can confirm that the files have loaded successfully because when I set autostart to true, the files play. However, I need the files to play only when the user clicks on a button (or an event is fired). The following is my code to preload these files:
function preloadMedia() {
for(var i = 0; i < testQuestions.length; i++) {
var soundEmbed = document.createElement("embed");
soundEmbed.setAttribute("src", "/media/sounds/" + testQuestions[i].mediaFile);
soundEmbed.setAttribute("hidden", true);
soundEmbed.setAttribute("id", testQuestions[i].id);
soundEmbed.setAttribute("autostart", false);
soundEmbed.setAttribute("width", 0);
soundEmbed.setAttribute("height", 0);
soundEmbed.setAttribute("enablejavascript", true);
document.body.appendChild((soundEmbed));
}
}
I use the following code to play the file (based on what sound file that user wants to play)
function soundPlay(which) {
var sounder = document.getElementById(which);
sounder.Play();
}
Something is wrong here, as none of the browsers I have tested on play the files using the code above. There are no errors, and the code just returns.
I would have left it at that (that is - I would have convinced the client to convert all WAV's to MP3 and use MooTools). But I realized that I could play the sound files, which were not dynamically embeded.
Thus, the same soundPlay function would work for a file embeded in the following manner:
<embed src="/media/sounds/hug_sw1.wav" id="sound2" width="0" heigh="0" autostart="false" enablejavascript="true"/>
anywhere within the HTML.
And it plays well in all the browsers.
Anyone have a clue on this? Is this some sort of undocumented security restriction in all the browsers? (Please remember that the files do get preloaded dynamically, as I can confirm by setting the autostart property to true - They all play).
Any help appreciated.
Hmm.. perhaps, you need to wait for the embed object to load its "src" after calling preloadMedia() ?
Are you sure that the media file is loaded when you call soundPlay() ?
i know your question got a bit old by now, but in case you still wonder...
soundEmbed.setAttribute("id", testQuestions[i].id);
you used the same id twice, yet getElementById returns only one element, or false if it doesn't find exactly one matching element.
you could try something like this:
soundEmbed.setAttribute("id", "soundEmbed_"+testQuestions[i].id);
always keep in mind that an id must be unique
Just a tip for more compatibility:
I read here that width and height need to be > 0 for Firefox on MacOS.