Playing dynamically embedded sound object via Javascript - javascript

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.

Related

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/

javascript to cancel image loading

I am looking for a way to cancel image loading using javascript. I've looked at other questions and hiding them is not enough. Also, the rest of the page must load (window.stop() is out of the question).
The page that is being loaded is not under my control, only one thing is guaranteed - the first <script> on the page is my javascript (lightweight - no jquery).
I have tried setting all img sources to nothing, that did not help since the dom is created after the page is parsed, and all browsers have the same behavior - the img is loaded once it is parsed.
Not possible with modern browsers. Even if you alter the src attribute of image tag with JavaScript browsers still insist on loading the images. I know this from developing the Lazy Load plugin.
The only way I can see to stop images loading is to not have an src attribute present in the image itself, and using a custom data-* attribute to hold the location of the image:
<img data-src="http://path.to/image.png" />
Obviously this doesn't gracefully degrade for those (admittedly rare) JavaScript disabled browsers, and therefore requires a noscript fall-back:
<img data-src="http://path.to/image.png" />
<noscript><img src="http://path.to/image.png" /></noscript>
And couple this with a simple function to load the images when you, or your users, are ready for them:
/* simple demo */
function imagePopulate(within, attr) {
within = within && within.nodeType == 1 ? within : document;
attr = attr || 'data-src';
var images = within.getElementsByTagName('img');
for (var i = 0, len = images.length; i < len; i++) {
if (images[i].parentNode.tagName.toLowerCase() !== 'noscript') {
images[i].src = images[i].getAttribute(attr);
}
}
}
document.getElementById('addImages').onclick = function(){
imagePopulate();
};
JS Fiddle demo.
I can't be sure for all browsers, but this seems to work in Chrome (in that there's no attempt, from looking at the network tab of the developer tools, to load the noscript-contained img).
It can be done with webworkers. See the following example:
https://github.com/NathanWalker/ng2-image-lazy-load.
Stopping a web worker cancels the image loading in browser
Recalling the onload event:
window.onload=function(){
imgs = document.getElementsByTagName('img');
for(i = 0; i < imgs.length(); i++){
imgs[i].src = '#';
}
};
If you want to only cancel the loading of the image , you can use sємsєм's solution
but i do not think it will work by using an window onload event .
You will probably need to provide a button to cancel the image load. Also i suggest, instead of setting the src attribute to "#" , you can remove the src attribute itself using
removeAttribute()
[Make sure you disable the cache while testing]
You need a proxy.
Your script can redirect to another server using something like
location.replace('http://yourserver.com/rewrite/php?url='+escape(this.href));
perhaps you tell us why you want to cancel image loading and whose site you are loading on so we can come up with a better solution
If there is nothing on the page other than images, you could try
document.write('<base href="http://yourserver.com/" />');
which will mess with all non-absolute src and hrefs on the page.
UPDATE Horrible hack but perhaps this almost pseudo code (I am off to bed) will do someting
document.write('<script src="jquery.js"></script><div id="myDiv"></div><!-'+'-');
$(function() {
$.get(location.href,function(data) {
$("#myDiv").html(data.replace(/src=/g,'xsrc='));
});
})
The closest you can get to what you maybe want is to have a quickly loaded placeholder image (ie. low resolution version of your image) and a hidden image (eg. {display:none}) in which the large image gets loaded but not displayed. Then in the onload event for the large image swap the images over (eg. display:block for the large image display:none for the smaller). I also use an array (with their url), to reuse any images that have already been opened.
BTW if you open an image in a new webpage when it gets closed then the image loading will be cancelled. So maybe you can do something similar in a webpage using an iframe to display the image.
To close the iframe and therefore unload the image, remove the frame from the DOM
(another advantage is that browsers spawn another process to deal with iframes, so the page won't lock up while the image loads)

MediaElement.js setSrc not working for flash fallbacks on FF, IE7-8

I've seen a few discussions about this, but no real answers. I've had a lot of success getting mediaelement.js working for me except that it simply will not let me setSrc() on flash fallbacks. This is a huge bummer after so much work.
For a little background I'm using mediaelement-and-player.js v2.1.9 and using their player's API to change the media src via player.setSrc. I'm playing audio MP3s.
I'm getting this error in FF Mac:
this.media.setSrc is not a function
And this error in IE8 Win:
SCRIPT445: Object doesn't support this action
I find it hard to believe that this wasn't fully tested given that it seems a base part of their API. I've seen some other issues about similar problems but again, no real answers.
You would need to add "flashmediaelement.swf" to your code.
Had the same problem. Solved it by adding non-empty src and type="audio/mp3" attributes:
<audio id="player" controls src="#" type="audio/mp3" preload="none"></audio>
Presence of preload="none" is recommended here, because without it the element will send an additional request to a current page's URL in an attempt to download the audio.
Update: found an alternative way, zero-length WAV file can be embedded in src, thus you may use preload attribute normally and stop worrying about that an unneeded request will be sent if a user will click the play button before you set normal src.
<audio id="player" controls type="audio/mp3" src="data:audio/wav;base64,UklGRiQAAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQAAAAA=">
Don't worry about type and src incompatibility, because, according to audio element specification, type isn't legal attribute of audio tag at all (type is only a source tag's attribute), here it's placed only to fix MediaElement.js behavior.
I answered a similar question on github. Here's my solution:
This occurs when the setSrc method is called too soon after initializing the mediaElement player. Due to the flash fallback the swf (and therefore its api methods) will not be available until the success event is fired. After that setSrc works fine in IE8..
I didn't want to set the initial source from within the success handler. Therefore I used a boolean var to check whether the success event had occurred. In my source setting method I check for its value and use recursiveness (with a setTimeout to prevent overkill) whenever the boolean var equals false.. Did the trick for me.
//create the tag
var video = $("<video>",{id:"videoElement",width:640,height:360}).appendTo('body');//jquery
var mediaElementInitialized = true
//create the mediaelement
var mediaElement = new MediaElementPlayer("#videoElement",{
/**
* YOU MUST SET THE TYPE WHEN NO SRC IS PROVIDED AT INITIALISATION
* (This one is not very well documented.. If one leaves the type out, the success event will never fire!!)
**/
type: ["video/mp4"],
features: ['playpause','progress','current','duration','tracks','volume'],
//more options here..
success: function(mediaElement, domObject){
mediaElementInitialized = true;
},
error: function(e){alert(e);}
}
);
var setSource = function(src){
if(mediaElementInitialized == true){
if(mediaElement){
mediaElement.setSrc(src);
mediaElement.play();
}
} else {
//recursive.. ie8/flashplayer fallback fix..
var self = this;
setTimeout(function(){
self.setSource(src);
},100);
}
}
var plugin = new MediaElementPlayer(#mplay_audio_p',
{
//...params...
});
var url="http://www.somesite.com/audiofile.mp3";
plugin.setSrc(url);
plugin.load();
plugin.play();

Generate sound using JavaScript

I am trying to generate sound using JavaScript. I have used the following code
<html>
<script type="text/javascript" src="jquery-1.4.2.js"></script>
<script>
function PlaySound(soundObj) {
var sound = document.getElementById(soundObj);
sound.Play();
}
function init() {
//alert("");
PlaySound('sound1')
}
window.onload = init;
</script>
<body>
<form name="myform">
<input type=button id="b1" name="b1name" value="Play Sound" onClick="PlaySound('sound1')">
</form>
Move mouse here
<embed src="beep-5.wav" autostart="false" width="0" height="0" id="sound1" enablejavascript="true">
</body>
</html>
Sound is being generated on button click and on mouseover. It is not being generated in the init function. If I call the below function in another JavaScript function, it does not work. Another point is that if I keep alerting before calling, then sound comes.
PlaySound('sound1')
I have tried using $("#b1").click(); (button click in JavaScript) but it's not working.
I know this is duplicate of this question, but the answer there did not work for me. I am really confused. Please help out.
Can I play this sound twice at a time?
The sound file may not have finished loading when init is called, but if you include an alert or when you manually click a button, there is enough time in between for the browser to have loaded the file.
That being said, embed is a non-standard and deprecated tag, and you really shouldn't be using it for playing sounds. Have a look at the HTML5 audio tag instead.
If you want a web page to play a sound via JavaScript, and you want the page to:
validate
work in all modern browsers
work across multiple platforms
work without plugins
The answer is simple: you can't do it. End of story.
Sure, you can come up with an example that works in one version of one browser on one platform, but I'll guarantee you: it won't work everywhere.
a fast and dirty way (it also compatible with old browsers, even IE5) is to use can embedded a small wave file inside your javascript which then could be played as a resources (without saving to actual file), use binary encoding (same as embedding PNG into JS).
a better way is building a JS Audio object, playing a bit (with buffer) that can be generated any frame-sound you'll like...
use JS Audio Object
var output = new Audio();
output.mozSetup(1, 44100);
var samples = new Float32Array(22050);
for (var i = 0, l = samples.length; i < l; i++) {
samples[i] = Math.sin(i / 20);
}
(also here)
If we generate sound using jquery sound plug in, http://plugins.jquery.com/project/sound_plugin playing sound on start up/java script without much delay. Working fine in IE and firefox.
By Introducing delay according to comment by casablanca, sound is playing in java script.Here is the code i have added:
This referring link Introduce delay
function callback(){
return function(){
PlaySound('sound1');
}
}
function init() {
// alert("");
setTimeout(callback(), 500);
}

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