Stop video when a modal is closed (videojs) - javascript

I use videojs plugin to customize a video player.
I have 30 modals with one different video in each modal (Youtube, Dailymotion, Vimeo).
I added two buttons next/prev to pass between each modal (modal always open).
All work fine. Each video is well displayed.
But I have two problems :
Each time I switch on a new modal is displayed the video is automatically played.
When I close a modal the video continue to be played.
For the excerpt of my code I used the ID #popin-1 but each modal have a different ID id="popin-1", id="popin-2", id="popin-3", id="popin-4"
The links of each modal look like this :
Open my modal
The HTML code of each modal :
<div id="popin-1" class="popin__item">
<div class="popin__wrapper btn-action">
<div class="popin__inner">
<div class="popin__canva">
<div class="popin__video">
<div class="popin__video-container">
<video
id="vid-1"
class="video-js vjs-default-skin vjs-big-play-centered"
controls
autoplay
width="640" height="264"
data-setup='{ "techOrder": ["youtube"], "autoplay": true, "fluid": true, "sources": [{ "type": "video/youtube", "src": "http://my-video-url.com"}] }'
>
</video>
</div>
</div>
<div class="popin__content">
<p>Some text</p>
</div>
</div>
</div>
</div>
</div>
And finally my js function. I tried
$('.btn-open').each(function(i, el) {
var modal = $('#' + $(el).attr('data-modal'));
var overlay = $('.popin__overlay');
var close = $('.btn-action');
var player = videojs('popin__item');
function removeModal() {
modal.removeClass('show');
overlay.removeClass('show');
$('body').removeClass('no-overflow');
modal.player.pause();
}
function removeModalHandler() {
removeModal();
}
$(el).click(function(e) {
e.preventDefault();
modal.addClass('show');
overlay.addClass('show');
$('body').addClass('no-overflow');
});
close.click(function(e) {
if($(e.target).hasClass('btn-action')) {
e.preventDefault();
removeModalHandler();
}
});
});

If you are using bootstrap modal you should be able to use this code.
$('#myModal').on('hidden.bs.modal', function (e) {
// do something...
})
https://getbootstrap.com/docs/4.0/components/modal/#events

Related

How to add overlay button for each video on the page that play() video on 'mouseover'?

CONTEXT:
The page has multiple videos
Each video on the page is previewed on mouseover (done)
When mouseover on video, the overlay button appears for each video (done)
When mouseover on overlay button, video preview continues to play (or restart) --> can’t figure this one out
I GetElementsByClassName , save into variable and then loop through all videos on the page and adding EventListeners with appropriate play() / pause() functions -> works just fine for 'mouseover' video previews.
The moment I 'mouseover' on the button, video stops and I get "Uncaught TypeError: e.target.play is not a function at HTMLDivElement.videoPlay" error in my console.
When I do a test in my console, I can play each video using the appropriate index in the following:
buttons[0].nextElementSibling.play()
But for some reason, I can't make it work in the function.
Any ideas on how to make it work?
HTML
<div>
<!-- Video segment -->
<div class="vid-segment">
<a class="vid-btn" href="#">
<i class="fa fa-shopping-cart"></i>
<span>Add to cart</span>
</a>
<video class="video-preview" witdh="352" height="198" muted>
<source src="static/videos/video1.mov" type="video/mp4">
</video>
</div>
<!-- Video segment end -->
<!-- Video segment -->
<div class="vid-segment">
<a class="vid-btn" href="#">
<i class="fa fa-shopping-cart"></i>
<span>Add to cart</span>
</a>
<video class="video-preview" witdh="352" height="198" muted>
<source src="static/videos/video1.mov" type="video/mp4">
</video>
</div>
<!-- Video segment end -->
JavaScript
function videoPlay() {
loop = true;
play()
console.log("Video plays")
}
function videoStop() {
currentTime = 0;
pause()
console.log("Video stops")
}
const videos = document.getElementsByClassName('.vid-segment')
const buttons = document.getElementsByClassName('.vid-btn')
for(var i = 0; i < videos.length; i++) {
videos[i].addEventListener('mouseover', videoPlay);
videos[i].addEventListener('mouseout', videoStop);
buttons[i].addEventListener('mouseover', function() {
buttons[i].nextElementSibling.play()
})
}
I figured it out! The answer is as follows:
const videos = document.querySelectorAll('.video-preview')
const buttons = document.querySelectorAll('.vid-btn')
for (let i = 0; i < videos.length; i++) {
videos[i].addEventListener('mouseover', function() {
console.log('play')
videos[i].play()
})
videos[i].addEventListener('mouseout', function() {
console.log('pause')
videos[i].pause()
videos[i].currentTime = 0;
})
buttons[i].addEventListener('mouseover', function() {
console.log('button hover')
videos[i].play();
})
buttons[i].addEventListener('mouseout', function() {
console.log('button hover')
videos[i].pause()
videos[i].currentTime = 0;
})
}

html5 <audio> set border color with javascript when playing

digital store with mp3 files:
html5 'audio' tag is used, with 'controls'; works superb
since there are many audios, user should be visually reminded which one is playing - i want border around audio that is playing (active);
it is django project (python); with bootstrap 4
audio tag does not support styling, but it is possible to render orange border using: 'style="border-color:crimson"' in audio tag.
ok, crimson. lol.
html5 audio tag has 'play' event, it should be triggered when audio is played, by clicking 'play' on player:
play Fires when the audio/video has been started or is no longer paused
html:
<div id="sample-container"
class="col-auto my-auto">
<!-- sample player -->
<!-- style="border-color:crimson" -->
<!-- onplay="player_border();" -->
<audio id="sample-player"
controls
loop
play="player_border();"
class="btn btn-sm my-auto ">
<source src="{{ instance.audio.url }}"
type="audio/mpeg">
</audio>
</div>
audio tag also has 'paused' property:
paused Returns whether the audio/video is paused or not
script:
<!-- scripts -->
<script type="text/javascript">
function player_border()
{
var player = document.getElementById('sample-player'); // <audio>
var playContainer = document.getElementById('sample-container'); // <div>
playContainer.style.borderColor = 'orange'; // ko
player.style.borderColor = 'green'; // ko
var isPlaying = (!player.paused);
//document.getElementById("play_sample").play = function()
// elem = document.getElementById('#play_sample')
// var elem = document.getElementById('play_sample').innerHTML; # for inner text
// var player = document.getElementById('#play_sample');
// var play_container = document.getElementById('#play_container');
// play_container.style.color = 'orange;'
// play_container.style = 'border-color:orange;'
// play_container.style.borderColor = 'color:orange;'
// player.style.borderColor = 'color:green;'
// if (elem.audio.play)
// if (!elem.paused)
// if (!elem.audio.paused)
// if (!player.paused)
// if (player.play)
if (isPlaying)
{
playContainer.style = 'border-color:green';
player.style.borderColor = 'orange';
// player.style = 'borderColor:orange';
// play_container.style = 'border-color:border-warning'
// player.setAttribute('style', 'borderColor:orange;')
// play_container.setAttribute('style', 'color:orange; border: 1px solid blue;')
// elem.style = 'border:orange;'
// elem.setAttribute('style', 'border: 1px solid orange;'
// elem.style = 'border:border-warning'
};
}
</script>
say "i expect" when audio tag control (play audio) is clicked, and audio (mp3) is playing, there should be colored border around audio player, since it is possible to render colored border around audio player;
sad reality, which does not necessary implies a lack of intelligence (lol), is that i am solving this for 8 hours straight; obviously a newbie with js and html5 audio tag.
thx for help,
bow,
s love nia
Event listeners in HTML start with the on prefix
Your code is correct, however, you need to use the attribute onplay not play
<audio onplay="callYourFunc()"></audio>
Another note:
You may want to listen for the pause event via onpause="callYourFunc()" to remove the style when the <audio> element has paused.
this update works, but not correct. i might be missing a function loop, or something, code only works on first element on page.
<div id="sample-container"
class="col-auto my-auto">
<!-- sample player -->
<!-- style="border-color:crimson" -->
<!-- play="player_border();" -->
<!-- style="background:crimson; border-radius:27px;" -->
<audio id="sample-player"
controls
loop
onplay="sample_play();"
onpause="sample_pause()"
class="btn btn-sm my-auto">
<source src="{{ instance.audio.url }}"
type="audio/mpeg">
</audio>
</div>
<div class="col-auto my-auto">
<span class="lead ml-1 my-auto text-warning"><b>{{ instance.title }}</b></span>
</div>
</div>
<!-- song description -->
<div class="row my-auto pb-2 text-justify">
<span class="text my-auto">{{ instance.description }}</span>
</div>
<!-- scripts -->
<script type="text/javascript">
function sample_play()
{
var player = document.getElementById('sample-player'); // <audio>
var playContainer = document.getElementById('sample-container'); // <div>
var isPlaying = (!player.paused);
if (isPlaying)
{
player.style = 'background:crimson; border-radius:27px';
};
}
function sample_pause()
{
var player = document.getElementById('sample-player'); // <audio>
var playContainer = document.getElementById('sample-container'); // <div>
var isPlaying = (!player.paused);
if (!isPlaying)
{
player.style = 'background:none; border-radius:27px';
}
}
</script>
thx for help, i need somebody, help, not just anybody, lol, beatles.
this is the main loop (django/python) that populates items on page, it is in another file:
{% for obj in object_list %}
<div class="row mx-auto my-auto bg-transparent border-bottom border-primary">
<div class="col my-auto ">
{% include 'products/snippets/card.html' with instance=obj %}
</div>
</div>
{% endfor %}
what now?
making slow progress:
audio tag has two events, same function call:
onplay="sample_play()"
onpause="sample_play()"
function sample_play() has been simplified:
<script type="text/javascript">
function sample_play()
{
var player = document.getElementById('sample-player')
if (!player.paused)
{
player.style = 'background:crimson; border-radius:27px'
}
else
{
player.style = 'background:none; border-radius:27px'
}
}
</script>
but, still, it only works on first audio element on page. weird, i say.
thx for help.

Uncaught TypeError cannot set property 'src' of null onclick

I am trying to have a light box pop up for videos. it works fine with one video. When trying with multiple videos the 2nd video link dont work. When clicked I get Uncaught TypeError cannot set property 'src' of null.
Nothing happens when clicked but video1 starts in the background you cant see it only her the sound. Any help is appreciated.
here goes JS
// Function to reveal lightbox and adding YouTube autoplay
function revealVideo(div,video_id) {
var video = document.getElementById(video_id).src;
document.getElementById(video_id).src = video+'&autoplay=1'; // adding autoplay to the URL
document.getElementById(div).style.display = 'block';
}
// Hiding the lightbox and removing YouTube autoplay
function hideVideo(div,video_id) {
var video = document.getElementById(video_id).src;
var cleaned = video.replace('&autoplay=1',''); // removing autoplay form url
document.getElementById(video_id).src = cleaned;
document.getElementById(div).style.display = 'none';
}
here goes html
<a id="playme" onclick="revealVideo('video','youtube')" title="Read more"><img alt="The Boys & Girls Club" src="./content/uploads/2017/02/myimage.jpg" style="max-width:100%;max-height:100%"></a>
<a id="playme" onclick="revealVideo('video','youtube')" title="Read more"><img alt="The Boys & Girls Club 2" src="./content/uploads/2017/02/myimage2.jpg" style="max-width:100%;max-height:100%"></a>
<div class="lightbox" id="video" onclick="hideVideo('video','youtube')">
<div class="lightbox-container">
<div class="lightbox-content">
<button class="lightbox-close" onclick="hideVideo('video','youtube')">Close | X</button>
<div class="video-container">
<iframe allowfullscreen height="720" id="youtube" name="youtube" src="https://www.youtube.com/embed/xxxxxx?rel=0&controls=1&showinfo=0%20frameborder=0" width="1280"></iframe>
</div>
</div>
</div>
</div>
<div class="lightbox" id="video" onclick="hideVideo('video','youtube')">
<div class="lightbox-container">
<div class="lightbox-content">
<button class="lightbox-close" onclick="hideVideo('video','youtube')">Close | X</button>
<div class="video-container">
<iframe allowfullscreen height="720" id="youtube" name="youtube" src="https://www.youtube.com/embed/xxxxxx?rel=0&showinfo=0%20frameborder=0" width="1280"></iframe>
</div>
</div>
</div>
</div>
I think your problem here is that you're using IDs multiple times.
You got id="playme" on both anchor-tags and id="video" on both lightbox-divs.
So yeah. First, you should really only need a single video player -- simply change the src of that player and it should do what you want. The following is messy and ugly and really not the way i'd necessarily do this, but it works. Rather than having multiple lightbox/player elements, there's one. When you click the link, the onClick passes an id, which is matched against an array of objects. If a match is found, it changes the src of a SINGLE video-player element to the matched src and displays it.
From what I'm reading, this may be closer to what you're looking for.
var arrayOfVideos = [{
id: 'youtube',
src: "https://www.youtube.com/embed/xxxxxx?rel=0&controls=1&showinfo=0%20frameborder=0"
}, {
id: 'youtube2',
src: "https://www.youtube.com/embed/xxxxxx?rel=0&controls=1&showinfo=0%20frameborder=0"
}];
// Function to reveal lightbox and adding YouTube autoplay
revealVideo = function revealVideo(div, video_id) {
// This just shows what we're displaying, purely for debugging.
console.log("Showing the video "+video_id);
// We have a single videoplayer div. We'll simply toggle its src.
var video = document.getElementById("video-player");
// All possible links have been saved as an array of ids and src properties.
// Here, we simply get the first element with the matching id
var videoObject = arrayOfVideos.filter(function(obj) {
return obj.id === video_id;
})
video.src = videoObject[0].src+'&autoplay=1'; // Adding autoplay to the URL
document.getElementById(div).style.display = 'block';
}
// Hiding the lightbox and removing YouTube autoplay
hideVideo = function hideVideo(div, video_id) {
var video = document.getElementById("video-player");
var cleaned = video.src.replace('&autoplay=1', ''); // removing autoplay form url
video.src = cleaned;
document.getElementById(div).style.display = 'none';
}
<a id="playme" onclick="revealVideo('video','youtube')" title="Read more"><img alt="The Boys & Girls Club" src="./content/uploads/2017/02/myimage.jpg" style="max-width:100%;max-height:100%"></a>
<a id="playme" onclick="revealVideo('video','youtube2')" title="Read more"><img alt="The Boys & Girls Club 2" src="./content/uploads/2017/02/myimage2.jpg"></a>
<div class="lightbox" id="video" onclick="hideVideo('video','youtube')">
<div class="lightbox-container">
<div class="lightbox-content">
<button class="lightbox-close" onclick="hideVideo('video','youtube')">Close | X</button>
<div class="video-container">
<iframe allowfullscreen height="720" id="video-player" src="" width="1280"></iframe>
</div>
</div>
</div>
</div>

How to get a value of href in modal window when we click the href?

I am trying to get a value in my pop up window when we click the a href.
I use magnificPopup JavaScript
Below code is my a href tag and I want the "data-stream" value to be get in the pop up window.
<a class="popup-with-zoom-anim wiplay" id="<?=$entry->id?>" href="#small-dialog" data-detail-id ="<?=$entry->id?>" data-stream="<?=$demo_streamurl;?>">hello</a>
I need to value to be inserted in the src of the below code which comes in the pop up window.
<div id="small-dialog" class="zoom-anim-dialog mfp-hide">
<div class="popup-container">
<div class="container">
<div class="col-md-8 col-center popup-cont-container">
<video id="vid1" class="video-js vjs-default-skin" controls autoplay
width="640" height="364"
data-setup='{ "techOrder": ["youtube"], "sources": [{ "type":
"video/youtube", "src":"https://www.youtube.com/watch?v=A7XdOyZIkko"}] }'>
</video>
<div class="video-info">
<div id="wiVideoInfo">
<div class="info-left">
<div id="wiPlayerChannel" class="main-tag"></div>
<div id="wiPlayerDate" class="datenTime"></div>
<div id="wiPlayerInfo" class="video-info-main">
<br>
<span class="at"> </span></div><div id="wiPlayerhandler" class="at"></div>
</div>
<div class="info-right">
<span><img src="<?=theme_url()?>images/eyeico.png">
<a id="wiPlayerLives"> </a> Live viewers</span>
<span><img src="<?=theme_url()?>images/heart.png"><a id="wiPlayerLikes">
</a> Likes</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
How can I do it either using JavaScript or using PHP?
You need to use a code like below, as given in the docs § Varying modal content based on trigger button:
$('#exampleModal').on('show.bs.modal', function (event) {
var button = $(event.relatedTarget); // Button that triggered the modal
var stream = button.data('stream'); // Extract info from data-* attributes
var modal = $(this);
modal.find(".video-js").attr("data-setup", '{ "techOrder": ["youtube"], "sources": [{ "type": "video/youtube", "src": "' + stream + '"}] }');
});
So the stream inside the function will have the data-stream's value. You need to set whatever you wanna set. Let me know if this works. :)
get the data-stream value from id $entry->id?
replace the data-stream value by data-stream
var data_stream = $('#vid1').attr('data-setup');
dt.val(dt.val().replace("**data-stream**",
$('#'<?=$entry->id?).attr('data-stream').val()));

Youtube video slideshow stop video on click

I have a youtube video slideshow which gets populated with the use of a template:
<script id="tFlowplayer" type="text/html">
<div class="rv" id="{{name}}">
<iframe class="{{id_v}}" width="575" height="323" src="{{id_v}}" frameborder="0" allowfullscreen></iframe>
</div>
</script>
when I click on next or prev I need to stop the current youtube embedded video playing:
<nav class="arrows">
<button data-goto="prev" class="arrow arrow-left" rel="prev">Prev</button>
<button data-goto="next" class="arrow arrow-right" rel="next">Next</button>
</nav>
The following is the click event for the navigation, I guess this where the action will be happening:
$('[data-goto]').on('click', function (evt) {
var $this = $(this),
where = $this.attr('data-goto'),
video_id = $('[data-play]').attr('data-id');
if (where === 'prev') {
swiper.prev();
} else {
swiper.next();
}
});

Categories