Link to home
Start Free TrialLog in
Avatar of Bruce Gust
Bruce GustFlag for United States of America

asked on

I need to get the video to stop when you close the modal...

I'm working in Laravel 6. I've got a list of videos and I've been able to structure things in a way where when the user clicks on the video's title, a pop up surfaces where you can hit play and video the video.

Perfect.

The problem is that when you close the modal, the video is still playing...

I need to incorporate a function that extends the "close" dynamic to include something that gets the video to stop playing.

One approach that I found seems to replace the video source with a ''. Seems reasonable, but I can't get it to work.

Here's a screenshot of the of the modal...

User generated image
Here's the code I attempted to implement:

@foreach($videos as $video)
	<div class="modal fade" id="video_player-{{ $video->id }}" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
	  <div class="modal-dialog" role="document">
		<div class="modal-content">
		  <div class="modal-header">
			<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
			<h5 class="modal-title" id="myModalLabel">{{ $video->title }}</h4>
		  </div>
		  <div class="modal-body" style="text-align:center;">
			<video width="320" height="240" controls id="video-frame-{{$video->id}}">
				<source src="{{ asset("assets/videos/{$video->filename}") }}" type="video/mp4">
				Your browser does not support the video tag.
			</video><br><br>
			<div style="text-align:left;">{{ $video->description }}</div>
		  </div>
		  <div class="modal-footer" style="text-align:center;"></div>
		</div>
	  </div>
	</div>
		<script>
		$('.close').click(function() {
			$('#video_player-{{$video->id}}').video_frame-{{$video->id}}.attr('src', '');
		});
	</script>
	@endforeach

Open in new window


In theory, I want to believe I'm poised on the threshold of great things, but when I try to run it, I get this error:

Invalid or unexpected token -> $('#video_player-69').video_frame-69.attr('src', '');

It seems to be complaining about the "-" character.

I tried this:

$('#video_player-{{$video->id}}').video_frame-[{{$video->id}}].attr('src', '');

...and that didn't work. It said "[42].attr is not a function."

How can I get this to work?
SOLUTION
Avatar of Chris Stanyon
Chris Stanyon
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
It seems to be complaining about the "-" character.
I think you have run into this monster before - the interpreter sees the '-' in the above context as a minus -

What were your hopes for this statement?
$('#video_player-{{$video->id}}').video_frame-[{{$video->id}}].attr('src', '');

Open in new window

What you are saying here is wrap the video-player-x element in a jQuery object and then access the video-frame-x property on that object. Assuming such a property exists as you have it will fail because you are in code space (not string space) and the dash is now a minus so you are doing this

$('#....').video_frame - 1.attr('src')

Open in new window

Which does not make sense from a code perspective.

If this was what you were wanting to do you would need to do this
$('#video_player-{{$video->id}}')['video_frame-[{{$video->id}}]'].attr('src', '');

Open in new window

But I don't think that is what you wanted to do - just including it for interest

Now for the important bit - when you close the modal you want to pause the vid.

First we tap into the modal close event - we do this on the .modal class so we can hit all modals on your page.
This will trigger when we close the modal using one of the standard BS methods for doing so.
Then we find the <video> element in the modal using the find() method on $(this) [which is the modal the event was triggered on]
Finally we call .pause() on that video.

This should do the trick.
$(function() {
  $('.modal').on('hidden.bs.modal', function (e) {
    var vid = $(this).find('video')[0];
    vid.pause();
  })
});

Open in new window

ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Bruce Gust

ASKER

Gentlemen!

As always, the "A Team" doesn't disappoint!

One thing has me puzzled still, however...

When I do this:

<div class="modal fade" id="video_player-{{ $video->id }}" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
	  <div class="modal-dialog" role="document">
		<div class="modal-content">
		  <div class="modal-header">
			<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
			<h5 class="modal-title" id="myModalLabel">{{ $video->title }}</h4>
		  </div>
		  <div class="modal-body" style="text-align:center;">
			<video width="320" height="240" controls id="video-frame[{{$video->id}}]">
				<source src="{{ asset("assets/videos/{$video->filename}") }}" type="video/mp4">
				Your browser does not support the video tag.
			</video><br><br>
			<div style="text-align:left;">{{ $video->description }}</div>
		  </div>
		  <div class="modal-footer" style="text-align:center;"></div>
		</div>
	  </div>
	</div>
		<script>
		$('.close').click(function() {
			alert("yes");
			//$('#video_player-{{$video->id}}').video_frame-[{{$video->id}}].attr('src', '');
		});
	</script>
	@endforeach

Open in new window


I get the impression that I'm piggy backing on some pre manufactured. code. I say that because I can craft a modal using that framework and the "close" button is going to work without me having to hook up anything.

That said, I tried the script that you see above...

      <script>
            $('.close').click(function() {
                  alert("yes");
                  //$('#video_player-{{$video->id}}').video_frame-[{{$video->id}}].attr('src', '');
            });
      </script>

It didn't work.

That has me concerned in that I'm thinking there's a "close" functionality already written in Bootstrap that I need to edit. First of all, is that even smart and secondly, am I correct?

If so, how's that code going to look if I don't want to craft things in a way where I'm asserting the idea that every modal is going to have a video id to look for?
Hey Bruce,

Yeah - when you use BootStrap for Modals, it comes with some pre-built functionality, including the close button. If you look at the code for the close button, it's the data-dismiss property that allows bootstrap to bind a click event to that button.

<button type="button" class="close" data-dismiss="modal" aria-label="Close">

If you want to hook your own code into the close call, you have a couple of options. Probably the better option is to go with what Julian mentioned - you don't actually hook into the click event of the close button. Instead you hook into the close event of the Modal itself:

$('.modal').on('hidden.bs.modal', function (e) {
    // this get's fired when the Modal closes
});

Open in new window

The other (less optimal) option is to just remove the data-dismiss attribute from the button and carry on with the click event (making sure you manually close the Modal yourself.
That has me concerned in that I'm thinking there's a "close" functionality already written in Bootstrap that I need to edit. First of all, is that even smart and secondly, am I correct?
Firstly you should be able to bind to the .close button - when I copy paste your code above to a test script and add a button - I see the dialog on close.

Secondly, you are correct - if you look at my sample link above you will see I bind to two BS events

$('.modal').on('show.bs.modal', function (e)

Open in new window


and
$('.modal').on('hidden.bs.modal', function (e) 

Open in new window


More info here
https://getbootstrap.com/docs/4.4/components/modal/#events
Done!

Got it!

Just because I'm interested in knowing: What is this:

$('.modal').on('hidden.bs.modal', function(e) {

What is "bs.modal?" I'm trying to tie that into the "close" dynamic, but I don't see the connection.

Thank you!
Outstanding!
The hidden.bs.modal is just the name of an event, like click, change, load. It's just that bootstrap uses a custom name to prevent clashes.

You can create your own events and call them whatever you like:

<button>Click Me</button>

$('button').click(function() {
    $(this).trigger("bruces.funky.event");
}

$('button').on('bruces.funky.event', function() {
    console.log("I'm a custom event!);
});

Open in new window

@Bruce take a look at the bootstrap link I posted. It points to the Events section of the BS Modal page - all the events including the one you are asking about are described there.