Here is the web page I'm working on: http://sebastianbiermanlytle.com/music.htm
When you click the arrows on the sides of the media players, a javascript changes the source. All of the soundcloud players are refreshing as they are supposed to, but the mixcloud plugins (under "Full 1+ Hour Sets") are not when using chrome or ie (and probably safari), but are refreshing fine in Mozilla. If you inspect the element, you can see that the src and value attributes are changing as they should when the arrows are pressed - the players are just not refreshing to show the new content.
How can I get these players to refresh?
UPDATE:
This code works:
var curSet=0;
var sets = ['<object>....</object>', '<object>...</object>',....];
function nextSet(direction){
....//update curSet value
$('#firstSet').html(sets[curSet]);
}
You're right, it doesn't work in Safari either... Unfortunately it's a known behavior: check this discussion, for example. The only way to get past it is to move manipulation on the higher level. ) You wrap your dynamic elements in <div> element, like this:
<div id="flash-container">
<object ...>
<embed...></embed>
</object>
</div>
... then completely refresh a container with the new flash object (with the required src value) each time a control fires:
$('#flash-container')
.html('<object ...><param value="new src" ...><embed ... src="new src">')
Hope this'll help. )
Related
We've been using the CreateJS suite for a while now, but have just realised that our audio is not working on IOS9. Unfortunately we only have one IOS9 test device, running IOS9.2.4, but are getting mixed results with audio playback.
The rough process I'm using is;
Preload all assets (scripts/images/audio) via PreloadJS
Construct an initial splash screen in EaselJS, including a start button
Continue with the main content
It would be advantageous to be able to preload all audio before presenting that splash screen. The splash screen was added initially to allow audio to play on mobile Safari, with an empty sound played on click. This does of course work for IOS7/8, but not for 9.
I've created this test case on codepen as an attempt to track down the issue and try some options.
Codepen sample
HTML
<p id="status">Hello World</p>
<canvas id="canvas" width="200" height="200"></canvas>
JS
var canvas, stage, rect;
function init() {
canvas = document.getElementById('canvas');
canvas.style.background = "rgb(10,10,30)";
stage = new createjs.Stage("canvas");
createjs.Touch.enable(stage);
rect = new createjs.Shape();
rect.graphics.f("#f00").dr(50,75,100, 50);
rect.on("mousedown", handleStart, null, true);
rect.on("touchend", handleStart, null, true);
//rect.on("click", handleStart, null, true);
stage.addChild(rect);
stage.update();
$('#status').text("Touch to Start");
createjs.Sound.initializeDefaultPlugins();
//createjs.Sound.alternateExtensions = ["ogg"];
createjs.Sound.registerSound("https://www.freesound.org/data/previews/66/66136_606715-lq.mp3", "ding1");
}
function handleStart(event) {
createjs.WebAudioPlugin.playEmptySound();
$('#status').text("Touch to Play");
rect.graphics._fill.style = '#0f0';
rect.removeAllEventListeners();
rect.on('click', handlePlay);
stage.update();
}
function handlePlay(){
createjs.Sound.play("ding1");
$('#status').text("Playing");
}
init();
Apologies for the lack of ogg version, was struggling to get test files to load x-domain.
With this, audio partially works for us on IOS9. If we leave clicking the red rectangle (figure start button) and leave it ~20 seconds, then click the green button no audio plays. If we click it immediately, audio plays fine.
I have been reviewing this bug/thread and attempting to follow Grant's suggestions. I gather SoundJS v0.6.2 now automatically attempts to play the empty sound appropriate when plugins are initialized, however moving the initializeDefaultPlugins and registerSounds calls into the handleStart function appears to make no difference. If I'm understanding the issue correctly, calling the WebAudioPlugin.playEmptySound method should be sufficient?
Have also been looking at the event binding, trying mousedown/touchend instead of click, but the result is the same with the 20 second wait. Event also appears to fire twice, although I could probably dig deeper into that if I could get it to work correctly.
I'm aware of the Mobile Safe Approach article aimed at this issue, but the need for a namespace at this level would mean a substantial rewrite of our existing content. Could someone perhaps advise if it is completely necessary to take this approach? I'm under the impression it should be feasible by correctly playing some empty audio within that initial handler.
Can't actually get the main project to this point, but if I can get a working example perhaps I'll be a step closer.
Any thoughts would be appreciated!
The Mobile-safe tutorial is not really relevant anymore since the updates in 0.6.2. It will likely be updated or removed in the near future.
You should never need to initializeDefaultPlugins(), unless you want to act on the result (ie, check the activePlugin before doing something). This method fires automatically the first time you try and register a sound.
The playEmptySound is also no longer necessary. SoundJS will listen for the first document mousedown/click, and automatically do this in the background.
touch events are not directly propagated from the EaselJS stage, but are instead turned into mouse events (touchstart=mousedown, touchmove=mousemove, touchend=pressup/click)
Based on this, you should be able to play sound once anywhere in the document has been clicked, regardless of whether you listen for it or not.
That is not to say that there isn't a bug, just that the steps you are taking shouldn't be necessary. I did some testing, and it appears to work in iOS9. Here is a simplified fiddle.
https://jsfiddle.net/lannymcnie/b4k19fwc/ (link updated Dec 3, 2018)
I'm new to Firefox add-on development, and I have a problem while trying to play a sound in my add-on.
It's an add-on for timekeeping. Users can configure meetings settings (duration, participants... etc) through a Panel. There is a toolbar. It contains several buttons (Start, Next, Stop, Add Participant) and a Frame (to display how many participants haven't speaked yet). I change the document.border.style property from "green" to "red" as timers countdown.
This works fine. But I was asked to make my add-on play a sound when the document.border.style property turns "orange" and then "red" and I can't make it works.
I have tried several things :
1-Adding a property/attribute (I don't know which term is the right to use in that context, maybe both, anyway) to my TimeKeeper variable for each sound that has to be played. Meaning in my code :
orangeBorderStyle: new Audio(relativePathToMyMp3orWAVFile),
redBorderStyle: new Audio(relativePathToMyMp3orWAVFile),
and then calling their play() method in the countdown() method. But it didn't work.
2-Currently, I'm trying to play the sounds from HTML5 audio tags I added to the frame.url HTML file. But it doesn't work either.
The HTML file looks like this :
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Frame</title>
</head>
<body>
<script type="text/javascript" src="../javascript/Frame_script.js"></script>
Speakers Left : <input id="speakers" size="4" value="" disabled />
<audio id="orangeSound" src="Audio/orangeBorderSoundTest.mp3" type="audio/mpeg">
Your browser does not support the audio element.
</audio>
<audio id="redSound" src="Audio/redBorderSoundTest.mp3" type="audio/mpeg">
Your browser does not support the audio element.
</audio>
</body>
</html>
In Frame_script.js I have :
window.addEventListener("message", reactToMessages, false);
var orangeBorderSound=document.getElementById("orangeSound");
var redBorderSound=document.getElementById("redSound");
//console.log(orangeBorderSound);
function reactToMessages(e){
if(isNaN(e.data)==false){
displaySpeakersLeft(e);
}
if(e.data=="orangeBorderSound")
{
document.getElementById("orangeSound").play();
//console.log("Je joue le son Orange.");
} else if(e.data=="redBorderSound")
{
document.getElementById("redSound").play();
//console.log("Je joue le son Rouge.");
}
}
function displaySpeakersLeft(e){
document.getElementById("speakers").value=e.data;
}
and in Timers.js I have the following calls :
Frame.get().postMessage("orangeBorderSound", Frame.get().url);
Frame.get().postMessage("redBorderSound", Frame.get().url);
Both calls trigger the right code (when the console.log() are commented out, they are displayed correctly) but there is no sound in the end.
Please, note that the value of the input tag with ID "speakers" is correctly displayed in my add-on so it seems that the document.getElementById() methods returns the right thing, and that it is the right way to do things with an input tag. Meaning, the paths are the right ones. I can't see why it would be different with audio tags.
So here comes my question : I now see the error "Security Error: Content at moz-nullprincipal:... may not load or link to resource..." (the resource path given seems to be the right one for each audio file) in the Error Console.
Is this really a security issue ? Or would I have little to change to make my code works ? What would you do ?
Any explanation or suggestion would be appreciated. I really don't see what's wrong with what I've done. Why would it cause security problems ?
Please, note that I've tried to use the audio tags method in a new add-on with just a Play button in the Panel and nothing else, but this time with the audio tags in the Panel contentURL HTML file, calling the play() method in the contentScriptFile and it worked.
No security error this time.
But I suppose I can't accept such a solution in my timekeeping add-on since I need to synchronize the call of the play() method with the change of the border style and that there is no Play button this time. It does not correspond to what I want to obtain. It was just for testing purpose.
Timers.js which is in my lib directory cannot interact with the Panel contentScriptFile which is in the data directory, so it couldn't be a solution even if the sounds were correctly loaded and ready to be played.
What do I get wrong ?
I've been using SublimeVideo, and I've done so much with it already for the site I'm working on.
I've got 15-20 videos that I'm successfully using via SublimeVideo on a site in the basic way, by having a link on the page the user clicks on, and when clicked, the video opens in the SublimeVideo lightbox and starts playing.
But now, I'm needing to create "shorter URLs" for these videos that can be sent out in print publications and emails, and where the user is taken to the website to view, not just the video file.
Ideally, I was hoping to just use the id/data-uid with a hashtag in a single-page url and have the chosen video to automatically launch'n'play within the lightbox. That seems to be impossible (?).
I could settle with having a single page with the video tags hidden and have the hashtag unhide it and play it when in the URL. If none of this can work in a slick way, maybe I'll just go old-school and make a page for each video and just embed it in the page..
Anyway, after scouring all the documentation pages, their forums, and searching the web, I've only found a couple of options - neither of which have actually worked. I'll paste them below:
First, here's an example of the HTML I'm using for all the videos:
<p class="">video1 text link on page</p>
<video id="video1" data-uid="video1" title="video1 description" poster="/assets/images/video1.jpg" width="1084" height="574" style="display:none" data-autoresize="fit" preload="none">
<source src="/assets/videos/video1.mp4" />
</video>
That, by itself, works great! I don't want to change that. When the text link is clicked, the lightbox opens and the video plays perfectly.
So, let's say the page that holds the 15-20 videos with the above code for them is at:
http://example.com/resources/index.php
I thought I could simply make that URL for the first video:
http://example.com/resources/index.php#video1
...or even better...
http://example.com/resources#video1
...and follow suit for all the other video IDs.
And to get that to work, I've tried:
<script type="text/javascript">
sublimevideo.ready(function()
{
if (window.location.hash == '#video1') {
sublime('video1').play();
} else
if (window.location.hash == '#video2') {
sublime('video2').play();
} else
if (window.location.hash == '#video3') {
sublime('video3').play();
}
});
</script>
...that doesn't work. For some reason it works with whatever the first video is on the page, but by "work" I mean, it unhides it and makes it playable, not open in the lightbox and auto play.
So then I found code in the sharing documentation area like this:
<script type="text/javascript">
var hashtag = "#video1";
var hashtag = "#video2";
var hashtag = "#video3";
if (document.location.hash == hashtag) {
showTheVideo(hashtag);
}
function showTheVideo(hashtag) {
}
</script>
...but that doesn't work either.
Could somebody that does know JavaScript please spell it out for me?
I'll put the code that fixed the issue for me here in hopes it helps somebody else someday that may search and find it.
By putting the below code in the head of the page, under the...
<script type="text/javascript" src="//cdn.sublimevideo.net/js/UniqueIDprovidedInYourAccountGoesHere.js"></script>
...library (which is the random characters/numbers .js that SublimeVideo gives you in your account area), I was able to finally get the above detailed problem to work (YAY!!!).
So, using the same example as above, this URL now works as I needed (by not only taking you to the resources page, but also by launching the particular video in its lightbox).
http://example.com/resources.php#video=interview2
...and by putting:
RewriteRule ^resources$ resources.php [L]
...in the .htaccess file in the same dir, I was able to make it even easier for the user:
http://example.com/resources#video=interview2
As I understand it, the below JavaScript addition finds the hash, then looks for the "video=", then takes whatever is after that, and if it finds a matching "id" in an "a" tag, then it tells it to do it's SublimeVideo thing by launching that video in the lightbox. Brilliant!
<script type="text/javascript">
$(document).ready(function () {
var lochash = location.hash.substr(1);
var mylocation = lochash.substr(lochash.indexOf('video='))
.split('&')[0]
.split('=')[1];
sublime.ready(function () {
var lightbox = sublime.lightbox(mylocation);
lightbox.open();
});
});
</script>
Here's the HTML part (for reference):
<p class="">video2 text link on page that i left as reference for the user in case they close the video that was launched from the publication</p>
<video id="video2" data-uid="video2" title="video2 description" poster="/assets/images/interview2.jpg" width="1084" height="574" style="display:none" data-autoresize="fit" preload="none">
<source src="/assets/videos/interview2.mp4" />
</video>
Also note: I found out through trial and error that the name of the video in the URL, after the "#video=" must be the same as the "ID" in the "A" tag, not the "video" tag! So, you'll notice that the "id=" is (and needs to be) different between the two. The "id=" in the "video" tag is instead the same as the "href=".
I've got this in the <head>:
<script>
function log(event){
var Url = "./log.php?session=<?php echo session_id(); ?>&event=" + event;
xmlHttp = new XMLHttpRequest();
xmlHttp.open( "GET", Url, true );
xmlHttp.send( null );
}
</script>
And this in the <body>:
<video id="video" src="./video/LarryVideo.mp4"
controls="controls"
poster="./img/video_poster.jpg"
onabort="log('onabort');"
oncanplay="log('oncanplay');"
oncanplaythrough="log('oncanplaythrough');"
ondurationchange="log('ondurationchange');"
onemptied="log('onemptied');"
onended="log('onended');"
onerror="log('onerror');"
onloadeddata="log('onloadeddata');"
onloadedmetadata="log('onloadedmetadata');"
onloadstart="log('onloadstart');"
onpause="log('onpause');"
onplay="log('onplay');"
onplaying="log('onplaying');"
onprogress="log('onprogress');"
onratechange="log('onratechange');"
onreadystatechange="log('onreadystatechange');"
onseeked="log('onseeked');"
onseeking="log('onseeking');"
onstalled="log('onstalled');"
onsuspend="log('onsuspend');"
ontimeupdate="log('ontimeupdate');"
onvolumechange="log('onvolumechange');"
onwaiting="log('onwaiting');">
<script>
QT_WriteOBJECT('./video/LarryVideo.mp4',
'380px', '285px', // width & height
'', // required version of the ActiveX control, we're OK with the default value
'scale', 'tofit', // scale to fit element size exactly so resizing works
'emb#id', 'video_embed', // ID for embed tag only
'obj#id', 'video_obj'); // ID for object tag only
</script>
</video>
My normal Safari creates nice log-file entries as expected. Mobile Safari from iPad however doesn't do anything at all.
What could be wrong with this?
I have not been able to get a hold of readystate on an ipad either, but you can get other events that more-or-less let you infer the readystate.
var audio = new Audio("someSource.mp3");
audio.play();
/* you may need to use .load() depending on how the event was initiated */
audio.addEventListener("canplay", handleCanPlay, false);
audio.addEventListener("durationchange", handleDurationChange, false);
But let's be clear, the problem is Apple pretty much telling the whole world they're using the internet wrong. Granted, everyone hates sites that start playing music the second they load, but then Apple goes nuts and kills ANY/ALL buffering of audio/video that isn't explicitly initiated by a user gesture because Apple, apparently, thinks their users can't hit "back" if a site bothers them; fanboys agree too. This basically leaves the rest of us to hack up our applications if we dare try and manage any kind of sound effects. I know this isn't the place to rant, but building ANY soft of interesting/interactive experience in HTML5 on the iPad is one facepalm after another -- be it the 5mb cache limit that simply crashes the browser if a page has "too" many (according to Apple) images, or the difficulty to preload any sort of media to enhance UI. Seriously, outside of Wordpress blogs and RSS readers, mobile Safari's implementation of HTML5 is pretty worthless. And so the dream of HTML5 "build once, play anywhere" value proposition is dead and we go back to developing native apps. At least this gives us good job security! /rant
I've got a page with links to MP3s, when the link is clicked I use javascript to show a small Flash player (NiftyPlayer) under the link. When a different link is clicked, the old player is hidden and the new player is revealed.
The player auto-starts when the element is shown, and auto-stops when hidden - in Firefox.
In IE it will only auto-start and NOT auto-stop. This is what I would like to solve.
This is an example HTML with link and player
Misunderstood What You Said
<div id="player662431" class="playerhide"><embed src="http://www.example.com/shop/flash/player.swf?file=/mp3/Beat The Radar - Misunderstood What You Said.mp3&as=1" quality="high" bgcolor="#000000" width="161" height="13" name="niftyPlayer662431" align="" type="application/x-shockwave-flash" swLiveConnect="true" pluginspage="http://www.macromedia.com/go/getflashplayer"></embed>
Here is the javascript (I've got jQuery installed to let me hide all the open players on this page apart from the new one)
function toggle_visibility(id) {
$('.playerhide').hide();
var e = document.getElementById(id);
e.style.display = 'block';
}
I think what I need to do is start the player manually with javascript (rather than using the autostart as=1 function in the URL string)
There is some javascript that comes with NiftyPlayer to allow this EG
niftyplayer('niftyPlayer1').play()
there is also a stop method.
I need some help with javascript - how do I add this call to play into my toggle_visibility function (it has the same unique ID number added to the name of the player as the ID of the div that's being shown, but I don't know how to pull this ID number out of one thing and put it in another)
I also would like to be able to do
niftyplayer('niftyPlayer1').stop()
to stop the audio of the previously running player. Is it possible to store the current ID number somewhere and call it back when needed?
Thanks for the help, i'm a PHP programmer who needs some support with Javascript - I know what I want to achieve, just don't know the commands to do it!
Thanks
If you assigned each niftyplayer object a classname, f.x. ".players", then you could loop through each player, like this:
function toggle_visibility(id) {
$(".players").each(function(){
playerId = $(this).attr('id');
if(niftyplayer(playerId).getState() == 'playing') {
//Stop the currently playing player
niftyplayer(playerId).stop();
//Hide the div that was playing
$("#" + playerId).hide();
}
});
//Start the new player
niftyplayer(id).play();
$("#" + id).show();
}
So what this actually does, is it loops through all the players on the website. It checks if the status of each player is equal to "playing", if it is, then it stops it and hides the div tags. Then it starts the new player and shows that div tag.
I think this does it. Try it out.
I have a much better solution after I noticed a very nasty bug / 'feature' when using Internet Explorer in conjunction.
I had noticed that in IE the pages were taking a very long time to load when I had a lot of hidden Nifty Players, I looked closer using Fiddler and found that each instance of NiftyPlayer was preloading the MP3 in full, rather than loading on demand as with Firefox and Chrome etc.
This meant that a page with 100 items (each item having up to 4 MP3s) took several minutes to load at times with obvious data transfer implications.
My solution which is rather simpler (but maybe clunkier) than Indyber's is to just use
function toggle_visibility(id,mp3location) {
// hide all players
$(".playerarea").html('');
// show clicked player
$('#' + id).html('<embed src=\"http://www.xxx.com/shop/flash/player.swf?file=http://www.xxx.com/mp3/' + decodeURIComponent(mp3location) + '.mp3&as=1\" quality=high bgcolor=#000000 WMODE=transparent width=\"161\" height=\"13\" align=\"\" type=\"application/x-shockwave-flash\" swLiveConnect=\"true\" pluginspage=\"http://www.macromedia.com/go/getflashplayer\" class=\"playerNew\">');
}
which works fine with IE, and also solves the problem of not being able to stop the players from playing in IE