19

I'm using the following code to add click-to-play functionality to HTML5 video:

$('video').click(function() {
  if ($(this).get(0).paused) {
    $(this).get(0).play();
  }
  else {
    $(this).get(0).pause();
  }
});

It works okay except that it interferes with the browser's native controls: that is, it captures when a user clicks on the pause/play button, immediately reversing their selection and rendering the pause/play button ineffective.

Is there a way to select just the video part in the DOM, or failing that, a way to capture clicks to the controls part of the video container, so that I can ignore/reverse the click-to-play functionality when a user presses the pause/play button?

5 Answers 5

18

You could add a layer on top of the video that catches the click event. Then hide that layer while the video is playing.

The (simplified) markup:

<div id="container">
    <div id="videocover">&nbsp;</div>
    <video id="myvideo" />
</div>

The script:

$("#videocover").click(function() {
    var video = $("#myvideo").get(0);
    video.play();

    $(this).css("visibility", "hidden");
    return false;
});

$("#myvideo").bind("pause ended", function() {
    $("#videocover").css("visibility", "visible");
});

The CSS:

#container {
    position: relative;
}

/*
    covers the whole container
    the video itself will actually stretch
    the container to the desired size
*/
#videocover {
    position: absolute;
    z-index: 1;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
}
4
  • Yeah, that works for the initial play, but not for pausing/playing the video after that.
    – heff
    Commented Aug 9, 2012 at 22:01
  • Yeah, it only works while the video is paused. Otherwise heff's solution is what you are looking for. Commented Aug 9, 2012 at 22:06
  • This is 90% of what I'm looking for (would've liked to have retained the click-to-pause functionality), but close enough. Thanks! One slight change I had to make was to give the cover a z-index value: otherwise, it appears below the video container.
    – user113292
    Commented Aug 10, 2012 at 8:40
  • Yes sorry, I missed that. Or you could just define the cover after the video so it is autmatically above. Elements that appear later in the markup are automatically rendered above elements appearing earlier (unless you mess this up with position: relative or z-index). Commented Aug 10, 2012 at 12:09
4

I know this is an old question but I ran into the same issue and found an other solution! Playing the video on click and also pause it on click. But as the original poster I ran into problems with the controls. Solved the issue with jquery like this:

$("video").click(function (e) {
    if(e.offsetY < ($(this).height() - 36)) // Check to see if controls where clicked
    {
        if(this.paused)
            this.play();
        else
            this.pause();
    }
});

I check the offset in the click and if it is over the controls my play/pause functions doesn't do anything.

1
  • I like it, works well. I'd like to know if anyone encounters issues with this approach
    – JDandChips
    Commented Sep 23, 2014 at 9:34
3

You could try event.stopPropagation and see if that works. Though I think that would either stop the native controls from working, or just not do anything.

$('video').click(function(event) {
  event.stopPropagation();
  if ($(this).get(0).paused) {
    $(this).get(0).play();
  }
  else {
    $(this).get(0).pause();
  }
});

If the browser considers the native controls and video all part of the same element (and I believe they do) you're probably out of luck. jQuery's event.target wouldn't allow you to tell the difference between a click on the video and a click on the controls.

So I think your best option is to build your own controls (old tutorial, still pretty straight forward). Or ask the browser devs to make a click on the video play/pause when controls are enabled. Seems like it should do that by default.

1
  • Unfortunately, event.stopPropagation() does nothing in this case.
    – user113292
    Commented Aug 10, 2012 at 8:43
1

Torsten Walter's solution works well and it's a fairly elegant solution to the problem, and it's probably the best way to handle it, even if it doesn't handle click-to-pause. However, his solution got me thinking about a hacky way to do it, and I came up with this:

Markup

<div id="container">
  <div id="videocover">&nbsp;</div>
  <video id="myvideo" />
</div>

JavaScript

$('#videocover').click(function(event) {
  var video = $('#myvideo')[0];
  if (video.paused) {
    video.play();
  }
  else {
    video.pause();
  }
  return false;
});

CSS

#container {
  position: relative;
}

#videocover {
  position: absolute;
  z-index: 1;
  height: 290px; /* Change to size of video container - 25pxish */
  top: 0;
  right: 0;
  bottom: 0;
  left;
}

Basically, it keeps the clickable cover up all the time to handle the click-to-play/click-to-pause functionality, but makes sure the cover doesn't overlap with the controls at the bottom of the video.

This is, of course a kludge, as it:

  • assumes all browsers place the controls in the same area, and that the controls are the same height
  • requires specifying the height of the video container in CSS
  • prevents the controls from appearing when the mouse hovers over the video

But I figured I'd put it out there.

2
  • The thing is, you can't say that there will only be controls at the bottom of the video. What if a player has some kind of floating controls? Commented Aug 10, 2012 at 12:18
  • @TorstenWalter I mentioned that at the end of my answer.
    – user113292
    Commented Aug 10, 2012 at 13:05
0

Great answers here. Thank you for these. Here's a trick I figured out for making controls clickable, all jQuery.

$('#video_player').click(function(e){

    var y = e.pageY - this.offsetTop;

    //Subtract how much control space you need in y-pixels.
    if(y < $(this).height() - 40) 
    {
        //$(this).get(0).play();
        //... what else?
    }

});