I am using Flickity to create a slider of images and videos. When changing slides, I want to play the video on the current slide (which has a class of .is-selected), and then pause again once I move to the next slide.
The code below manages to find any videos within the slider, but plays them on any slide change, rather than specifically for the slide they are within. Any help would be much appreciated.
// Init Flickity
var $carousel = $('.carousel');
$carousel.flickity();
// On slide change
$carousel.on('change.flickity', function() {
// Find videos
var currentSlide = $(this).find('.is-selected');
var video = $(this).find('video');
// Play videos
video[0].play();
});
What you want to do is pause all videos on every slide change and only play the one on the selected slide. I did something similar (without jQuery):
var carousel = document.querySelector(".carousel");
var flkty = new Flickity(carousel, {
// ..
});
flkty.on("change", function() {
console.log("Flickity active slide: " + flkty.selectedIndex);
flkty.cells.forEach(function(cell, i) {
if (cell.element == flkty.selectedElement) {
// play video if active slide contains one
// use <video playsinline ..> in your html to assure it works on ios devices
var video = cell.element.querySelector("video");
if (video) {
console.log("playing video " + i);
video.play();
}
return;
}
// pause all other videos
var video = cell.element.querySelector("video");
if (video) {
console.log("pausing video " + i);
video.pause();
}
});
});
As I stated in the comment, you might wanna use the "playsinline" attribute for your videos, otherwise you'll run into problems on iOS.
Also: using the "settle" event instead of "change" allows you to start playing once the active slide settled at its end position.
Related
When user clicks on an item, I am dynamically adding a unique audio element like this and playing an audio.
let sound = document.createElement("audio");
sound.id = "audio" + e.target.id;
app.audioBeingPlayed = sound.id;
sound.controls = "controls";
sound.src = selectedVoice[0][1].sample;
sound.type = "audio/mpeg";
sound.play()
Before doing this I am checking if an audio is already being played and want to pause that audio.
I tried doing this
if(app.audioBeingPlayed) {
$('audio #'+ app.audioBeingPlayed).pause()
}
before the code above.
When one item is clicked, it plays an audio. But when another item is clicked it gives an error saying
$(...).pause is not a function
I just want to pause the audio being played and play the new audio as created in the code in the first block.
Any help will be appreciated.
you need to change your code from
if(app.audioBeingPlayed) {
$('audio #'+ app.audioBeingPlayed).pause() // $('audio #'+ app.audioBeingPlayed) is not the audio object.
}
to this
....
....
app.audioBeingPlayed = e.target.id; // set the correct target id.
if(app.audioBeingPlayed) {
$('#'+ app.audioBeingPlayed).pause() // $('#'+ app.audioBeingPlayed) is the audio object so play/pause will work.
//or directly use the id to pause.
$('#'+ e.target.id).pause()
}
I'm making a website for a client using the divi theme. The site has a background video with sound. The customer wants in the video a button to turn the sound on and off.
With the following code I was able to mute but I can not make a button to turn on and off.
Can someone help me?
jQuery (document) .ready (function () {
jQuery (". et_pb_section_video_bg video"). prop ('muted', true);
});
Try with volume level!
Edit
And here are the functions for some volume down/up buttons.
$(document).ready(function(){
// Video element
var myVideo = $(".et_pb_section_video_bg video")[0];
// On load state (muted)
myVideo.volume = 0;
$("#sound_up").on("click",function(){
var actual_volume = myVideo.volume;
if(actual_volume<1){
myVideo.volume += 0.2;
}
});
$("#sound_down").on("click",function(){
var actual_volume = myVideo.volume;
if(actual_volume>0){
myVideo.volume -= 0.2;
}
});
});
Assuming the et_pb_section_video_bg video class is on the video element...
I have designed an i-phone-like screen on a web browser where I am testing this application I am in the process of building. It works great up until the point where I want to call out another set of videos.
What works
The application is structured so that when the user sees the screen she is directed to a channel that has a vertical video.
The buttons on the top left and top right advance to the next and the previous video.
<div id="topVid" class="videoContainer">
<div class="topHorizontalButtonRow">
</div>
<video class="topVid" loop onclick="this.paused? this.play() : this.pause()" >
<source src="videos/ParisisBurning_660x370_I_went_to_a_ball.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
</div>
There is a "channel" button that shows the user a smaller window if pressed, where the user can view other channels by clicking on a second set of buttons next and previous buttons.
<div id="bottomVid" class="videoContainerTwo hiddenElement">
<div class="topHorizontalButtonRow">
<div class="buttonLeftTriangleBlue"></div>
<div class="buttonRightTriangleBlue"></div>
</div>
<video loop onclick="this.paused? this.play() : this.pause()" >
<source src="videos/Politics_Refugee_Sign.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
jquery show/hide smaller window:
$(".buttonTeardropChannelBlue").click( function (){
if( $("#bottomVid").is(':visible') ) {
$("#bottomVid").hide();
} else {
$("#bottomVid").show();
}
});
If the user wants to watch this specific channel, she can click on the smaller window, which hides the current window and advances to the other channel. The video can be clicked on, and once that happens, the user will be directed to the next channel.
Below is the code that works perfectly to advance the video of the current selection, and it contains the videos in arranged in an array.
var Vids = (function() {
var _currentId = -1;
var _urls =
["videos/ParisisBurning_370x660_Get_Into_The_Suits_Vert.mp4","videos/ParisisBurning_370x660_School_Vert.mp4","videos/ParisisBurning_660x370_I_came_I_saw_Vert.mp4", "videos/ParisisBurning_660x370_I_went_to_a_ball.mp4"]; // literal array
return {
next: function() {
if (++_currentId >= _urls.length)
_currentId = 0;
return this.play(_currentId);
},
prev: function() {
if (--_currentId < 0)
_currentId = _urls.length - 1;
return this.play(_currentId);
},
play: function(id) {
var myVideo = document.getElementsByTagName('video')[0];
myVideo.src = _urls[id];
myVideo.load();
myVideo.play();
return false;
}
}
})();
What does not work
The issue: showing and hiding multiple video lists
However, the problem starts when I want to select a different class of videos, which has the exact same code except for different videos. I have changed the name of the function to say, VidsTwo but the problem remains.
var VidsTwo = (function() {
var _currentId = -1;
var _urls = ["videos/Politics_Atl_We_are_the_people.mp4","videos/Politics_Atlanta_Whose_Streets.mp4", "videos/Politics_Womens_March_Washington_CBS_VERT.mp4",
"videos/Politics_No_bans_no_walls_America_is_home_to_all_VERT.mp4",
"videos/Politics_Let_them_in_VERT.mp4",
"videos/Politics_Tear it Down_JFK_VERT.mp4",
"videos/Politics_This_is_What_America_Looks_Like_embrace.mp4",
"videos/Politics_This_land_was_made_VERT.mp4", "videos/Politics_We_need_an_independent_investigation_town_hall.mp4",
"videos/Politics_Just say no_town_hall_VERT.mp4", ]; // literal array
return {
next: function() {
if (++_currentId >= _urls.length)
_currentId = 0;
return this.play(_currentId);
},
prev: function() {
if (--_currentId < 0)
_currentId = _urls.length - 1;
return this.play(_currentId);
},
play: function(id) {
var myVideo = document.getElementsByTagName('video')[0];
myVideo.src = _urls[id];
myVideo.load();
myVideo.play();
return false;
}
}
})();
The issue remains: the buttons will continue to play the videos of the current channel in addition to the ones of the new channel, and it will not hide the current video. I understand it happens because in the javascript code, it uses the select element by tag which is "video". and all the array lists have "video" so it is playing all of them.
What is the best solution to this problem, given that I want to be able to separate the videos into categories "channels" that will have similar thematic content, and that this categories will be called by users as they look at a second smaller window of videos?
Core questions
Is there a way to have it NOT play a selection of arrays? What can I change in the Javascript code that will indicate that these separate video arrays do not belong to the same class? How can I make it clear in the code that these videos, although they are all videos, belong to different categories and therefore can only be played if their specific category is called?
Brainstorming solutions:
I am thinking I would probably need a second div that will have a
second row of buttons that call out the second function, since the
prev and next indicate a separate variable that was declared for each
class of videos...but this is getting a bit complicated for my newbie
skills:)
Or perhaps each video on a parent class should be saved on the
html itself as a hidden div and should be called by using "show
next child of parent div", as opposed to being saved as an array on
the javascript code?
The next step is adding marquee text to each video so maybe having
separate hidden divs on the html itself is a better solution than
having the videos stored as javascript arrays?
This is basically a prototype/beta for something that will become an
app so there is no database yet, (which will make it easier to
store this info eventually once I begin more in-depth user tests).
This complication is for testing only:)
UPDATE: I am still curious as to what the best solution would be, however I have decided, in this case, to add divs directly to the html and use jquery's next sibling selectors. Because I will have some text specific to some videos, they won't be properly connected to the javascript arrays anyway. I find the javascript array solution "cooler" but it is perhaps not the best in the end.
make Vids like this:
var Vids = function(vidArray=[]) {
var _currentId = -1;
var _urls = vidArray;
return {
next: function() {
if (++_currentId >= _urls.length)
_currentId = 0;
return this.play(_currentId);
},
prev: function() {
if (--_currentId < 0)
_currentId = _urls.length - 1;
return this.play(_currentId);
},
play: function(id) {
var myVideo = document.getElementsByTagName('video')[0];
myVideo.src = _urls[id];
myVideo.load();
myVideo.play();
return false;
}
}
};
then prepare your url array and call Vids:
var urls =["videos/ParisisBurning_370x660_Get_Into_The_Suits_Vert.mp4","videos/ParisisBurning_370x660_School_Vert.mp4","videos/ParisisBurning_660x370_I_came_I_saw_Vert.mp4", "videos/ParisisBurning_660x370_I_went_to_a_ball.mp4"];
Vids(urlf).play(3); //Replace 3 with any id
I have a video carousel created using the flickity carousel library, seen here on codepen. What I want to happen is that when a user slides the carousel, the selected slide stops playing, then the slide that takes the selected, middle position starts to play. Right now, using jQuery, I get the selected slide to initially play:
$(document).ready(function () {
var $partnerSlides = $('.partner-slides').flickity();
function onLoadeddata(event) {
var cell = $partnerSlides.flickity('getParentCell', event.target);
$partnerSlides.flickity('cellSizeChange', cell && cell.element);
}
$partnerSlides.find('.slide video').each(function (i, video) {
video.pause();
$(video).on('durationchange', onLoadeddata);
});
$partnerSlides.find('.slide.is-selected video').each(function (i, video) {
video.play();
$(video).on('durationchange', onLoadeddata);
});
});
But when the slides switch position, the selected slide just moves position and keeps playing, while the new slide takes the middle position and doesn't play.
Is there a way to update those functions each time the carousel slides?
I actually figured out what I thought is the best way to do this. There is an event for the carousel, 'settle.flickity', which fires each time the carousel settles after being slid or autoplayed (More can be read about the flickity events here on flickity. Therefore, this code:
var $gallery = $('.partner-slides').flickity(); //this is the carousel
$gallery.on('settle.flickity', function () {
console.log('Flickity settled at ' + flkty.selectedIndex);
$gallery.find('.slide video').each(function (i, video) {
video.pause();
$(video).on('loadeddata', onLoadeddata);
});
$gallery.find('.slide.is-selected video').each(function (i, video) {
video.play();
$(video).on('loadeddata', onLoadeddata);
});
});
Will play the selected video and pause any video that is not selected.
I have a little html5 application where you can play a sound by clicking a button.
I have a function that adds an <audio> tag to a <div> with an id "playing." The sound removes itself when it is done.
function sound(track){
$("#playing").append("<audio src=\"" + track + "\" autoplay onended=\"$(this).remove()\"></audio>");
}
For the button I have:
<button onclick="sound('sounds/tada.mp3')">Tada</button>
When I click the button, an <audio> briefly appears in the element inspector and disappears when it is finished, just the way I want it, but after triggering it two times, it just stops working in Chrome, at least. There are no errors in the console either.
What is going on?
Get rid of the onclick/onend in your HTML and reference the button in your js:
HTML
<button id='tada' sound_url='sounds/tada.mp3'>Tada</button>
And the JS
var sound = function(track){
$("#playing").append("<audio id='played_audio' src='\" + track + \"' autoplay='true'></audio>");
}
$('#tada').on('click', function () {
var sound_url = $(this).attr('sound_url');
sound(sound_url);
});
$('#playing').on('end', 'played_audio', function() {
$(this).remove();
});
Okay, lets see..
var audioURL = "http://soundbible.com/mp3/Canadian Geese-SoundBible.com-56609871.mp3";
var audioEl = null;
function removeAudio() {
if (audioEl && audioEl.parentNode)
audioEl.parentNode.removeChild(audioEl);
}
function sound() {
removeAudio();
audioEl = document.createElement("audio");
audioEl.src = audioURL;
audioEl.controls = true;
audioEl.addEventListener("ended", removeAudio); // <-- Note it's ended, not end!
document.getElementById("playing").appendChild(audioEl);
audioEl.play();
}
document.getElementById("tada").addEventListener("click", sound);
<div id="playing">
</div>
<button id="tada">Tada</button>
I'm not seeing any problems with this script.
Decide audioURL, set audioEl to null as it will be used later
When the element with ID "tada" is clicked, run our sound function.
Remove the audio.
Create the audio element.
When the audio is finished, remove the audio.
Append the audio to the element with ID "playing".
Play the audio.
One thing to note is that I use the ended event, not the end event.
(This answer is here because Andrew really wants us to answer it.)