I am attempting to piece together a jPlayer example that plays two audio files, one right after another.
I need to have full event control, so i decided not to use the playlist option, unless somebody can give me an example of having a way of controlling when the events fire, something like:
first media 'before' function
first media 'after' function
second media 'before' function
second media 'after' function
My example below is using a global variable in the "ended:" function and seems pretty clumsy.
Does anybody have a better suggestion how i might accomplish this? here is my working example of using the global variable:
$(document).ready(function(){
$("#jquery_jplayer_1").jPlayer({
ready: function (event) {
console.log('ready function.');
},
ended: function() {
console.log('ending function starting.');
var player = $("#jquery_jplayer_1");
player.jPlayer("stop");
player.jPlayer("clearMedia");
player.jPlayer("setMedia", {
wav: globalParmTwo
});
player.jPlayer("play", 0);
globalParmTwo = null;
},
loop: false, // added to remove the if condition
supplied: "wav, oga",
wmode: "window",
useStateClassSkin: true,
autoBlur: false,
smoothPlayBar: true,
keyEnabled: true,
remainingDuration: true,
toggleDuration: true
});
});
var globalParmTwo = null;
function komPare(parmOne, parmTwo) {
globalParmTwo = parmTwo;
var player = $("#jquery_jplayer_1");
player.jPlayer("stop");
player.jPlayer("clearMedia");
player.jPlayer("setMedia", {
wav: parmOne
});
player.jPlayer("play", 0);
}
And here my working example using the playlist, which seems like a better solution, assuming there is some way to fire specific functions at specific times:
var myPlaylist = null;
$(document).ready(function(){
myPlaylist = new jPlayerPlaylist({
jPlayer: "#jquery_jplayer_N",
cssSelectorAncestor: "#jp_container_N"
}, []
, {
playlistOptions: {
enableRemoveControls: true
},
supplied: "wav, ogv",
useStateClassSkin: true,
autoBlur: false,
smoothPlayBar: true,
keyEnabled: true,
audioFullScreen: false
});
$('.jp-playlist').hide();
myPlaylist.option("autoPlay", true);
});
function komPare(firstMediaUrl, secondMediaUrl) {
myPlaylist.setPlaylist([
{ wav: firstMediaUrl },
{ wav: secondMediaUrl }
]);
};
any suggestions are very appreciated.
UPDATE: i removed an if-condition and put in "loop: false," instead in the first example.
We can bind events to the playlist player, and then use a global media counter. This still uses global variables, but the code is cleaner.
as always, any suggestions are most appreciated.
var myPlaylist = null;
var mediaCounter = null;
$(document).ready(function(){
myPlaylist = new jPlayerPlaylist({
jPlayer: "#jquery_jplayer_1"
}, [] // empty initial playlist
, {
playlistOptions: {
enableRemoveControls: true
},
supplied: "ogv",
useStateClassSkin: true,
autoBlur: false,
smoothPlayBar: true,
keyEnabled: true,
audioFullScreen: false
});
$('#jquery_jplayer_1').bind($.jPlayer.event.ready,
function(event) {
console.log('ready.');
}
);
$('#jquery_jplayer_1').bind($.jPlayer.event.loadeddata,
function(event) {
console.log('loadeddata ' + mediaCounter++ );
}
);
$('#jquery_jplayer_1').hide();
$('.jp-playlist').hide();
$('.jp-controls').hide();
myPlaylist.option("autoPlay", true);
});
function komPare() {
var playlist = [];
for ( urlName of arguments ) {
playlist.push( { ogv: urlName } );
};
mediaCounter = 0;
myPlaylist.setPlaylist(playlist);
};
Related
The player works fine on all other browsers, but isn't working in IE11. I'm getting the error message "Could not add internal listener" 8 times (one time for each playlist item, I assume).
The script gets to the onReady event, but never gets to onPlay. I'm running version 6.8. I have confirmed that the playList is being generated as it should, and as I mentioned, it works in all browsers except for IE11.
//get our playlist
var playListItems = [];
$(courseXML).find("audiofile").each(function() {
var newItem = {
file: "assets/audio/"+ $(this).text(),
type: "mp3"
};
playListItems.push(newItem);
});
//redoing this as a playlist
jwplayer("mediaplayer").setup({
flashplayer: "js/jwplayer.flash.swf",
html5player: "js/jwplayer.html5.js",
controls: false,
width: 1,
height: 1,
autostart: false,
playlist: playListItems,
allowscriptaccess: 'always',
events: {
onComplete: function() {
alert("I'm completed");
},
onReady: function() {
alert("I'm ready");
},
onPlay: function() {
alert("I'm playing!");
}
}
});
I'm trying to send values of an array created by checkboxes to the constructor of a "buzz" sound object. Code Follows.
<input type="checkbox" name="loops" value="drums01" id="drums01" class="Checkbox" > Drums #1</li>
<li><input type="checkbox" name="loops" value="drums02" id="drums02" class="Checkbox"> Drums #2</li>
<li><input type="checkbox" name="loops" value="guitar01" id="guitar01" class="Checkbox"> Guitar #1</li>
//CHECKBOXES
<button class="button button_type_sound" id="b01">Play<q class="key" id="key_q">Q</q></button>
//BUTTON
var arr = new Array();
var drums01 = new buzz.sound("drumloop01", {
formats: [ "wav" ],
preload: true,
autoplay: false,
loop: true
});
var drums02 = new buzz.sound("drumloop02", {
formats: [ "wav" ],
preload: true,
autoplay: false,
loop: true
});
var guitar01 = new buzz.sound("guitarloop01", {
formats: [ "wav" ],
preload: true,
autoplay: false,
loop: true
});
//ATTEMPT TO CREATE SOUND OBJECT FROM ARRAY AND PLAY IT
$("#b01").click(function(event){
event.preventDefault();
var arr = new Array( $("input:checkbox:checked").map(function(){
return this.value;
}).toArray());
console.log(arr.toString());
console.log("Try Playing Sound");
console.log(arr.toString());
var myGroup = new buzz.group(arr.toString());
myGroup.play();
});
Console Gives me the following error:
drums01,drums02 index.html:68
Try Playing Sound index.html:71
drums01,drums02 index.html:72
Uncaught TypeError: Cannot call method 'apply' of undefined
Here is a working fiddle created fixing the code you posted in your question.
http://jsfiddle.net/fmKeV/3/
Explanation
As you may see, in the "init section" I create an object literal of instances of buzz.sound.
Then, in the event handler of the button I map every selected checkbox to the corresponding sound (I changed the value of the input elements so that it is the same as the key in the buzzSounds object).
The new Array in new Array($() ... .toArray()) in your code is not needed. The toArray() method called on the result of the map function is sufficient, otherwise the result would be a nested array, which is not what the buzz.group function needs.
Code
Markup
<ul class="sounds">
<li>
<input type="checkbox" name="loops" value="drumloop01" id="drums01" class="Checkbox" />Drums #1</li>
<li>
<input type="checkbox" name="loops" value="drumloop02" id="drums02" class="Checkbox" />Drums #2</li>
<li>
<input type="checkbox" name="loops" value="guitarloop01" id="guitar01" class="Checkbox" />Guitar #1</li>
</ul>
<button class="button button_type_sound" id="b01">Play
<q class="key" id="key_q">Q</q>
</button>
Javascript
$(document).ready(function() {
// init sounds
var buzzSounds = {};
buzzSounds.drumloop01 = new buzz.sound("drumloop01", {
formats: ["wav"],
preload: true,
autoplay: false,
loop: true
});
buzzSounds.drumloop02 = new buzz.sound("drumloop02", {
formats: ["wav"],
preload: true,
autoplay: false,
loop: true
});
buzzSounds.guitarloop01 = new buzz.sound("guitarloop01", {
formats: ["wav"],
preload: true,
autoplay: false,
loop: true
});
//CLICK EVENT HANDLER
$("#b01").on('click', function(e) {
var sounds, group;
//0) Prevent default
e.preventDefault();
//1) map every selected element to the sound defined in the "buzzSounds" object
toPlay = $(".sounds input:checkbox:checked").map(function() {
return buzzSounds[this.value];
}).toArray();
//2) create a group from the collected buzz.sound instances
myGroup = new buzz.group(toPlay);
//3) play the group
console.log("Try Playing Sounds", toPlay, myGroup);
try {
myGroup.play();
} catch (e) {
console.log('uh-oh', e);
//in this example the sound files have not been loaded, so an error could be raised
}
});
});
Try something like this:
$(document).ready(function () {
var drums01 = new buzz.sound("drumloop01", {
formats: ["wav"],
preload: true,
autoplay: false,
loop: true
});
var drums02 = new buzz.sound("drumloop02", {
formats: ["wav"],
preload: true,
autoplay: false,
loop: true
});
var guitar01 = new buzz.sound("guitarloop01", {
formats: ["wav"],
preload: true,
autoplay: false,
loop: true
});
//ATTEMPT TO CREATE SOUND OBJECT FROM ARRAY AND PLAY IT
$("#b01").click(function (event) {
event.preventDefault();
var arr = new Array();
$('input[type="checkbox"]').each(function () {
arr.push($(this).val());
});
console.log(arr.toString());
console.log("Try Playing Sound");
console.log(arr.toString());
var myGroup = new buzz.group(arr.toString());
myGroup.play();
});
});
Let me know how it works out.
fiddle
as far as I know, to create a buzz.group we should pass the array no the string:
Sounds can be added to a group by passing an array to the constructor.
but you pass string instead, so it should be like this:
var myGroup = new buzz.group([
mySound1,
mySound2,
mySound3
]);
I changes your fiddle example like this:
$(document).ready(function () {
var drums = {};
drums.drums01 = new buzz.sound("drumloop01", {
formats: ["wav"],
preload: true,
autoplay: false,
loop: true
});
drums.drums02 = new buzz.sound("drumloop02", {
formats: ["wav"],
preload: true,
autoplay: false,
loop: true
});
drums.guitar01 = new buzz.sound("guitarloop01", {
formats: ["wav"],
preload: true,
autoplay: false,
loop: true
});
$("#b01").click(function (event) {
event.preventDefault();
var arr = new Array();
$('input[type="checkbox"]:checked').each(function () {
arr.push(drums[$(this).val()]);
});
var myGroup = new buzz.group(arr.toString());
myGroup.play();
});
});
check the new DEMO out.
The Problem in you have in your code is, you are passing the variable names as a string array, whereas you should pass the actual objects. to solve your problem you should make them accessible using a accessible in the context object like var drums = {} which you can use it in your anonymous function.
for mor information check this link out.
I have the following code which I was using to attempt to dynamically add jplayers via a function.
function audio_player(audio, title, type) {
var id = $('.audio').length;
$('#audio').append('<div id="jquery_jplayer_'+id+'" class="audio"></div><div id="jp_container_'+id+'" class="jp-audio"><div class="jp-type-single"><div class="jp-gui jp-interface"><ul class="jp-controls"><li>play</li><li>pause</li><li>stop</li><li>mute</li><li>unmute</li><li>max volume</li></ul><div class="jp-progress"><div class="jp-seek-bar"><div class="jp-play-bar"></div></div></div><div class="jp-volume-bar"><div class="jp-volume-bar-value"></div></div><div class="jp-time-holder"><div class="jp-current-time"></div><div class="jp-duration"></div></div></div><div class="jp-title"><ul><li>'+title+'</li></ul></div><div class="jp-no-solution"><span>Update Required</span>To play the media you will need to either update your browser to a recent version or update your Flash plugin.</div></div></div>');
$("#jquery_jplayer_"+id).jPlayer({
ready: function () {
$(this).jPlayer("setMedia", {
mp3: audio
});
},
play: function() { // To avoid jPlayers playing together.
$(this).jPlayer("pauseOthers");
},
swfPath: "../js",
cssSelectorAncestor:"#jp_container_"+id,
supplied: type,
errorAlerts: true,
warningAlerts: false,
wmode:"window"
});
}
$(document).ready(function() {
audio_player("http://www.jplayer.org/audio/mp3/TSP-01-Cro_magnon_man.mp3", "Test Title", "mp3");
audio_player("http://www.jplayer.org/audio/mp3/TSP-01-Cro_magnon_man.mp3", "Test2 Title", "mp3");
});
With this code I am getting the error
TypeError: $(...).jPlayer is not a function
wmode:"window"
When I use the same code, only set up as they have it in their demos (all the javascript inside document.ready() and statically declared) everything works fine.
Any ideas on what's going wrong/how to fix it?
Ended up solving it by doing this:
$(document).ready(function() {
function audio_player(audio, title, type) {
var id = $('.audio').length;
$('#audio').append('<div id="jquery_jplayer_'+id+'" class="audio" data-file="'+audio+'" data-type="'+type+'"></div><div id="jp_container_'+id+'" class="jp-audio"><div class="jp-type-single"><div class="jp-gui jp-interface"><ul class="jp-controls"><li>play</li><li>pause</li><li>stop</li><li>mute</li><li>unmute</li><li>max volume</li></ul><div class="jp-progress"><div class="jp-seek-bar"><div class="jp-play-bar"></div></div></div><div class="jp-volume-bar"><div class="jp-volume-bar-value"></div></div><div class="jp-time-holder"><div class="jp-current-time"></div><div class="jp-duration"></div></div></div><div class="jp-title"><ul><li>'+title+'</li></ul></div><div class="jp-no-solution"><span>Update Required</span>To play the media you will need to either update your browser to a recent version or update your Flash plugin.</div></div></div>');
$('#jquery_jplayer_'+id).jPlayer({
ready: function(event) {
$(this).jPlayer("setMedia", {
mp3: $(this).attr('data-file')
});
},
play: function() { // To avoid both jPlayers playing together.
$(this).jPlayer("pauseOthers");
},
swfPath: js,
cssSelectorAncestor:'#jp_container_'+id,
supplied: type,
errorAlerts: true,
warningAlerts: false,
wmode:"window"
});
}
audio_player("file.mp3", "Test Title", "mp3");
audio_player("file2.mp3", "Test2 Title", "mp3");
});
This is my imgSelectArea code:
ias = $('#<%=imgMain.ClientID%>').imgAreaSelect({
handles: true,
autoHide: false,
minChars: 0,
autoFill: true,
selectOnly: true,
mustMatch: true,
instance: true,
onInit: function (img, selection) {
$("#tagBox").css('display', 'none');
},
onSelectEnd: function (img, selection) {
$("#tagBox").show();
var x1 = selection.x1;
var y1 = selection.y1;
var x2 = selection.x2;
var y2 = selection.y2;
var position = $('#<%=imgMain.ClientID%>').position();
}
});
This works fine but I want to know when imgSelectArea is closed i.e when you click on overlay area, I want to get notified. I couldn't find this in documentation.
This is the documentation link:
http://odyniec.net/projects/imgareaselect/usage.html#callback-functions
Has anybody got around this issue?
Ok, I haven't got a working dev environment where I am so I can't test this but...
In jquery.imgareaselect.js (I'm using v0.9.8) around line 421:
function cancelSelection() {
$(document).unbind('mousemove', startSelection)
.unbind('mouseup', cancelSelection);
hide($box.add($outer));
setSelection(selX(x1), selY(y1), selX(x1), selY(y1));
if (!this instanceof $.imgAreaSelect) {
options.onSelectChange(img, getSelection());
options.onSelectEnd(img, getSelection());
}
/*ADD THIS LINE*/
options.onCancelSelection(img);
}
Also, around line 461, add a default, empty function:
...
onInit: function () {},
onSelectStart: function () {},
onSelectChange: function () {},
onCancelSelection: function () {}, /* Add This line */
onSelectEnd: function () {}
}, options));
You should then be able to register an event handler as usual...
ias = $('#<%=imgMain.ClientID%>').imgAreaSelect({
...
mustMatch: true,
instance: true,
onInit: function (img, selection) {
$("#tagBox").css('display', 'none');
},
onCancelSelection: function (img) {
/*Do something*/
},
...
});
That's about the best I can do in notepad/ie. If it's still an issue tomorrow, I'll have a go with a dev env.
I want the callingFunction to be able to override the default options provided in the showDivPopUp function.
function calling(){
showDivPopUp("title of pop up box", "message to show",
{
buttons:{
Yes: function () {
$(this).dialog("destroy");
},
No :function () {
$(this).dialog("destroy");
}
}
});
}
function showDivPopUp(title,msg,options){
var mgDiv = $("#msgDiv");
mgDiv.attr("innerHTML", msg);
return mgDiv.dialog({
modal: true,
buttons: {
Ok: function () {
$(this).dialog("destroy");
}
},
resizable: true,
show: "explode",
position: "center",
closeOnEscape: true,
draggable: false,
title : titl,
open: function (event, ui) { $(".ui-dialog-titlebar-close").hide(); }
});
}
So, the above code should show two buttons viz. Yes and No instead of just OK. I don't want to do if check for each option.
UPDATE:
In options parameter there might be options for which default is not applied. So the calling function may specify size option which is not mentioned in the showDivPopUp function.
You want to use the JQuery extend() method to merge the options you pass into the function with the defaults that are specified within it.
See:
http://www.zachstronaut.com/posts/2009/05/14/javascript-default-options-pattern.html
and
http://api.jquery.com/jQuery.extend/
//calling function source excluded, use exactly the same.
function showDivPopUp(title, msg, options) {
//create basic default options
var defaults = {
modal: true,
buttons: {
Ok: function() {
$(this).dialog("destroy");
}
},
resizable: true,
show: "explode",
position: "center",
closeOnEscape: true,
draggable: false,
title: title,
open: function(event, ui) { $(".ui-dialog-titlebar-close").hide(); }
}
//merge the specified options with the defaults.
//in example case, will have the above except with the new buttons specified
if (typeof options == 'object') {
options = $.extend(defaults, options);
} else {
options = defaults;
}
var mgDiv = $("#msgDiv");
mgDiv.attr("innerHTML", msg);
return mgDiv.dialog(options);
}
Looks like 'options' is in JSON format. Try omitting the first {buttons: portion in the 3rd argument to showDivPopUp or set buttons: options.buttons in the showDivPopUp function.
To expand on this, create more json pairs, and test for their existence in the showDivPopUp function. Exists? Override. Doesn't exist? Keep defaults.
{buttons:{
Yes: function () {
$(this).dialog("destroy");
},
No :function () {
$(this).dialog("destroy");
}
},
background:"blue",
fontsize:15
}
Access each via:
options.buttons
options.background
options.fontsize
Test for existence using:
if ( typeof( window[ 'option.fontsize' ] ) != "undefined" ) {override code}
Response to the update in the question:
Use jquery.each to iterate over all elements in the passed option.
In your mgDiv.dialog function, modify the buttons key to have a conditional value. E.g.:
function showDivPopUp(title,msg,options){
var mgDiv = $("#msgDiv");
mgDiv.attr("innerHTML", msg);
return mgDiv.dialog({
modal: true,
buttons: options.buttons || {
Ok: function () {
$(this).dialog("destroy");
}
},
resizable: true,
show: "explode",
position: "center",
closeOnEscape: true,
draggable: false,
title : titl,
open: function (event, ui) { $(".ui-dialog-titlebar-close").hide(); }
});
}