How to use javascript to swap swf in html? - javascript

I embedded a swf in my html page, but I would like it to swap to another swf when I clicked on a button in html. I used swfobject.js to embed the swf, and I use prototype to write the javascript. I thought I can just do this
$('movie').value = 'swf/bhts.swf';
alert($('movie').value);
the value did change to swf/bhts.swf, but it is still playing the original swf file...
this is the code I use to embed swf
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="530" height="298" id="flashcontent">
<param id="movie" name="movie" value="swf/trailer.swf" />
</object>
thanks.

Using swfObject:
<div id='flashContent'>
</div>
<script type='text/javascript'>
// Setup your initial flash
var so = new SwfObject(.....);
so.write ('flashContent');
// Some event handler
someElement.onclick = function ()
{
// Load up the new SWF
so = new swfObject(....);
so.write('flashContent');
}
</script>

How are you using SWFObject? If you use the swfobject.embedSWF method to add the SWF to your HTML file, then you can call that again with the same ID and it should remove the old Flash player object and add a new one with your new URL.
You also can use the SWF's own methods to replace the URL that it's using. If you've got the ID of the Flash object, use something like
var swf = getElementById("flash_id");
swf.LoadMovie(0, "http://example.com/newSwfUrl.swf");
and that should direct the Flash player to reload from a different location, replacing layer 0 (the default one). That may not work with really old Flash players, but should be fine in Flash 8 and later.

Related

JavaScript DOM audio not playing

Okay, I'm losing my mind here.
I'm trying to code a very simple player just for myself -- something crude but functional.
<button onclick="javascript:PlayAudio();">Play</button>
<script>
var audio = new Audio();
audio.src = "file.mp3"; // this file is in the same directory as the html page
var PlayAudio = function()
{
audio.play();
};
</script>
Should work, right? I know it's not the BEST way to do it, but here's the thing: I've rewritten this code a couple hundred times and nothing seems to be working. There aren't even any error codes/exceptions/whatever that I can find. The browser says it's loaded the file just fine. What's even weirder is when I check the paused member in the audio object, no matter how many times I call the play() method, it still returns true.
When I load the page just as a file in my browser, lo and behold, it plays! Just fine! But if I were to change the onclick event to audio.play();, it doesn't work anymore. I want to run this on a server though.
I promise you there is no additional code. No JQuery, no weird server plugins (not even PHP!). Just Apache, Windows, nothing else.
And I know the browser can play the audio because when I copy audio.src and go to the address, it'll play just fine. Even the protocol is fine; the HTTP:/// address is not trying to load the File:/// address and vice versa. (I need the audio to play as a DOM so I can randomize the audio file later on; I'm just trying to get my browser to play one stinkin' file in the first place.)
I know I can do this in HTML with some JavaScript, but I know this can work in pure javascript too (ignoring the <button>) because I've done this before a LONG time ago. So what changed?
I've also tried to load the definitions using window.onload, but that doesn't work neither.
So... what the heck? I'm am stupid or something? I can accept that; I just need to know.
I think it's because of the path to the mp3 file. Also, separate your HTML from JavaScript code like so:
HTML
<button id="btn">Play</button>
JavaScript
const btnSound = document.querySelector('#btn');
btnSound.addEventListener('click', () => {
const sound = new Audio('./file.mp3') // assuming it's in the directory
sound.play();
});
If you're trying to create a dynamic audio element in pure Javascript...
Create a div on your document to act as container for the dynamic tag
in JS, create the audio element then add to page (via adding it to Div container)
Then you can try a code setup like this...
<div id="container">
<button onclick="PlayAudio('file.mp3')">Play</button>
<div>
<script>
//#create new audio tag
var myAudioElement = document.createElement( "audio");
myAudioElement.setAttribute("controls", "true" );
//myAudioElement.setAttribute("id", "myAudioTag"); //# if you'll need access "by ID"
//# add element to page DOM
document.getElementById('container').appendChild( myAudioElement );
function PlayAudio ( inputURL) //# input is a String like "file.mp3"
{
myAudioElement.setAttribute("src", inputURL);
myAudioElement.play();
}
</script>
Note: To run the playAudio() function without clicking a button just call:
PlayAudio ( "someOtherFile.mp3" );
PS: Below is an example of a "better" approach. Better here means less headaches (more intuitive) but it uses the HTML that you want to avoid. Notice no .src is specified because you can still use JS to update such property by code.
<!DOCTYPE html>
<html>
<body>
<h1>Test Audio Playback </h1>
<audio id="myAudioTag" controls> <source src=" " type="audio/mpeg"> </audio>
<br>
<button onclick="PlayAudio();"> Play </button>
</body>
<script>
var audio = document.getElementById("myAudioTag");
audio.src = "file.mp3"; // this file is in the same directory as the html page
function PlayAudio() { audio.play(); }
//# call this function whenever track must be changed
//# example use: changeAudio( "https://example.com/files/song2.mp3" );
function changeAudio( inputURL) //is a String of some other mp3 file
{
audio.src = inputURL;
audio.play();
}
</script>
</html>
Write your code like this
<button onclick="PlayAudio();">Play</button>
<script>
var PlayAudio = function()
{
var audio = new Audio("file.mp3")
audio.play();
};
</script>
If it still does not work then also try to write onClick

Using javascript to update <embed> parameter

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/

video fallback using object tag doesn't work with appendChild

I've got a video player application that uses a variant of video For everybody. With a HTML5 <video> tag enclosing a <object> tag for flash falback on internet exploder. It all works well when I do this statically, however when the video elements are built using javascript, it seems that IE9 doesn't like this.
If i use static code like this it works:
<video id="video" width="360" height="240>
<source type="video/ogg" src="content/mov1.ogv"></source>
<source type="video/mp4" src="content/mov1.mp4"></source>
<object data="player.swf" type="application/x-shockwave-flash" height="384" width="512">
<param name="movie" value="player.swf" >
<param value="autostart=true&file=/mov1.mp4" name="flashvars">
</object>
</video>
but when I use a javascript function to build the video player as below, it doesn't.
function makeV4EPlayer(mp4URL, ogvURL, movieWidth, movieHeight, displayname){
//create the video element and set its attributes
var videoObject= document.createElement('video');
videoObject.setAttribute("id", "video");
videoObject.setAttribute("width", movieWidth);
videoObject.setAttribute("height", movieHeight);
//add mp4 source
var mp4Src=document.createElement('source');
mp4Src.setAttribute("src", mp4URL);
mp4Src.setAttribute("type","video/mp4");
videoObject.appendChild(mp4Src);
//add ogv source
var oggSrc=document.createElement('source');
oggSrc.setAttribute("src", ogvURL);
oggSrc.setAttribute("type","video/ogg");
videoObject.appendChild(oggSrc);
//add object with flash player
var flashObject=document.createElement('object');
flashObject.setAttribute("width", movieWidth);
flashObject.setAttribute("height", movieHeight);
flashObject.setAttribute("type", "application/x-shockwave-flash");
flashObject.setAttribute("data","swf/player.swf");
var params1 = document.createElement('param');
params1.setAttribute("name", "movie");
params1.setAttribute("value","swf/player.swf");
var params2=document.createElement('param');
params2.setAttribute("name","flashvars");
params2.setAttribute("value",'autostart=true' + '&file=/' + mp4URL);
flashObject.appendChild(params1);
flashObject.appendChild(params2);
videoObject.appendChild(flashObject);
return videoObject;
}
The Javascript builds the <video> tag just fine, and populates it with all the stuff, it's just that IE won't play it. Of course it works happily on every other browser in the universe.
When I use the IE9 developer tools to inspect the pages I note that in the static version it sees the video tag and the object tag as being siblings - that is the object isn't inside the video tag, but in the javascript version the object is nested inside the video tag. That I believe is the nub of the problem.
I don't think it's relevant, but I'm using the JW Player as my fallback flash player.
The IE doesn't support the ogg format (also see the browser compatibility page), the other brwoser do.
Maybe the MP4 URL is not correct or the file broken?
=== UPDATE ===
In the following line you are using imagesrc which is not defined before:
params2.setAttribute("value",'autostart=true' + imagesrc + '&file=/' + mp4URL);
You should initialze it before.
=== UDPATE ===
If the object tag shouldn't be in the video tag you have to make changes, because you can only return one element. E.g. put both in a wrapper element:
function makeV4EPlayer(mp4URL, ogvURL, movieWidth, movieHeight, displayname){
// create a wrapper
var videoWrapper = document.createElement('div');
videoWrapper.style.width = movieWidth+'px';
videoWrapper.style.height = movieHeight+'px';
videoWrapper.style.padding = '0';
videoWrapper.style.margin = '0';
//create the video element and set its attributes
var videoObject= document.createElement('video');
videoObject.setAttribute("id", "video");
videoObject.setAttribute("width", movieWidth);
videoObject.setAttribute("height", movieHeight);
//add mp4 source
var mp4Src=document.createElement('source');
mp4Src.setAttribute("src", mp4URL);
mp4Src.setAttribute("type","video/mp4");
videoObject.appendChild(mp4Src);
//add ogv source
var oggSrc=document.createElement('source');
oggSrc.setAttribute("src", ogvURL);
oggSrc.setAttribute("type","video/ogg");
videoObject.appendChild(oggSrc);
// add video to wrapper
videoWrapper.appendChild(videoObject);
//add object with flash player
var flashObject=document.createElement('object');
flashObject.setAttribute("width", movieWidth);
flashObject.setAttribute("height", movieHeight);
flashObject.setAttribute("type", "application/x-shockwave-flash");
flashObject.setAttribute("data","swf/player.swf");
var params1 = document.createElement('param');
params1.setAttribute("name", "movie");
params1.setAttribute("value","swf/player.swf");
var params2=document.createElement('param');
params2.setAttribute("name","flashvars");
params2.setAttribute("value",'autostart=true' + '&file=/' + mp4URL);
flashObject.appendChild(params1);
flashObject.appendChild(params2);
// add flash player to wrapper
videoWrapper.appendChild(flashObject);
return videoWrapper;
}
You can also test with this jsfiddle (I've no IE9 so I can't do it for you).
Alternatively, you can create two functions, one for the video tag, the other for the object tag.

Update flashvars and reload flash with jQuery

I would like to update the flashvars value argument to view another video:
<param name='flashvars' value='movieId=1002' />
I found out that I can make it work in Firefox by updating the parameter with the extra step of readding the whole flash contents.
$("param[name=flashvars]").attr("value", "movieId=33");
$("embed").attr("flashvars", "movieId=33");
$(".root").append($("#video"));
But this does not work in IE8 as the browser won't refresh the flash contents. Any ideas on how to reload the flash contents without external dependencies like swfobject.js?
I'm curious about this too. I'm trying to send a new string via flashvars to a SWF that I have no opportunity to change, and just changing the flashvars with jQuery, without having to use externalinterface, is the best option.
// update flashvars
var fv = 'foobar=1';
$("object param[name='flashvars']").attr("value", fv);
$("embed").attr("flashvars", fv);
// create new object to hold it
var obj = $("object");
// remove existing Flash from DOM
$("object").remove();
// add new HTML to DOM
$("#mviewer").append(obj.html());
If you want to change the flash vars and reload the Flash, you should just remove the SWF from the DOM and embed it again with your new vars (using SWFObject or whatever other method suits your fancy!).
If you want to change the flash vars without reloading the Flash, you're out of luck: there's no officially-supported way. In this case, you should use ExternalInterface to call ActionScript methods that update your values from JavaScript.
Instead of using flashvars, you could use the ExternalInterface AS3 class to send the new value to Flash.
ExternalInterface allows for a two way communication between AS3 & Javascript
Actually, why not use swfobject.js ?
I did like this :
<script type="text/javascript" src="js/jquery-1.4.4.min.js"></script>
<script type="text/javascript" src="js/swfobject.js"></script>
<div id="qsound"></div>
<script type="text/javascript">
if(q.sound) {
swfobject.embedSWF("js/dewplayer/dewplayer.swf", "qsound", "60", "20", "9.0.0", false, {'mp3': 'sounds/'+q.sound}, {'wmode': 'transparent'});
$('#qsound').show();
} else {
$('#qsound').hide();
}
</script>

Flash and JavaScript communication within IE

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.

Categories

Resources