6

I'm new with AngularJS. I must create customs controls for a video player (HTML5 <video>). Basically, I would use getElementById('myvideotag'), listen clicks on the video for play/pause. How I can do this with AngularJS ? Binding the click with ng-click="videoPlayPause()" but then, how I play or pause the video. How I use the classic methods of <video> ?

I guess it's really simple... I didn't get all the AngularJS concepts yet !

Thank you :)

Oh, the code... in the view:

<video autoplay="autoplay" preload="auto" ng-click="video()">
    <source src="{{ current.url }}" type="video/mp4" />
</video>

In the right controller:

$scope.video = function() {
    this.pause(); // ???
}
  • The question is clear and I express myself wrong? –  Jul 28 '13 at 22:38
  • It looks like a decent question now. Before, without code or formatting it looked like a downvote. Somebody might be able to help, I'm not very experienced with Angular either. – elclanrs Jul 28 '13 at 22:40
  • Of course. Ok, thanks. In AngularJS, I dont really understand the philosophy about managing the DOM (yet... hard to forget jQuery habits !) –  Jul 28 '13 at 22:44
  • @Scofred Checkout the directives of Angularjs. – zs2020 Jul 28 '13 at 22:55
  • @sza ok, how can I use directives in this specific problem ? Have you a little example ? –  Jul 28 '13 at 22:59

4 Answers4

8

For full control, like behaviour and look&feel, I'm using videoJS in angular. I have a ui-video directive that wraps the video HTML5 element. This is necessary to overcome a problem of integration with AngularJS:

m.directive('uiVideo', function () {
    var vp; // video player object to overcome one of the angularjs issues in #1352 (https://github.com/angular/angular.js/issues/1352). when the videojs player is removed from the dom, the player object is not destroyed and can't be reused.
    var videoId = Math.floor((Math.random() * 1000) + 100); // in random we trust. you can use a hash of the video uri

    return {
        template: '<div class="video">' +
            '<video ng-src="{{ properties.src }}" id="video-' + videoId + '" class="video-js vjs-default-skin" controls preload="auto" >' +
                //'<source  type="video/mp4"> '+     /* seems not yet supported in angular */
                'Your browser does not support the video tag. ' +
            '</video></div>',
        link: function (scope, element, attrs) {
            scope.properties = 'whatever url';
            if (vp) vp.dispose();
            vp = videojs('video-' + videoId, {width: 640, height: 480 });
        }
    };
});
Eduard Gamonal
  • 8,023
  • 5
  • 41
  • 46
3

How about this:

In your HTML, set ng-click="video($event)" (don't forget the $event argument), which calls the following function:

$scope.video = function(e) {
    var videoElements = angular.element(e.srcElement);
    videoElements[0].pause();
}

I believe this is the simplest method.

Documentation for angular.element

Also, this might help you get used to Angular: How do I “think in AngularJS/EmberJS(or other client MVC framework)” if I have a jQuery background?

Community
  • 1
  • 1
sushain97
  • 2,752
  • 1
  • 25
  • 36
  • 1
    Thanks ! Now I understand how to manipulate the DOM. But, this code work only if in the ng-click method, I add "$event" in parameter and videoElement[0].pause();. –  Jul 29 '13 at 10:22
  • Oh, sorry. I edited my answer a little, does it look right now? – sushain97 Jul 29 '13 at 15:48
  • 3
    Shouldn't you use a directive to manipulate the DOM? https://docs.angularjs.org/guide/directive – WrksOnMyMachine Jul 09 '14 at 16:18
3

You could also take a look to my project Videogular.

https://github.com/2fdevs/videogular

It's a video player written in AngularJS, so you will have all the benefits of bindings and scope variables. Also you could write your own themes and plugins.

elecash
  • 925
  • 7
  • 11
1

I also used videojs

bower install videojs --save

I wanted to use my directive in a ng-repeat and with a scope object, so... here's my version of it with props to Eduard above. I didn't seem to have a problem with the video player disposal, but the source tag issue referenced was an actual problem.

I also decided to write this up as an answer, so that I could give an example of how one might want to handle the videojs events.

IMPORTANT! Please note I am using Angular.js with Jinja2 templates, so I had to change my Angular HTML interpolation markers to {[ ]} from {{ }} in case anyone notices that as weird. I'll include that code too, so it's not weird for anyone.

Interpolation tweak

app.config(['$interpolateProvider', function($interpolateProvider) {
  $interpolateProvider.startSymbol('{[');
  $interpolateProvider.endSymbol(']}');
}]);

Directive

angular.module('myModule').directive('uiVideo', function () {

  // Function for logging videojs events, possibly to server
  function playLog(player, videoId, action, logToDb) {
    action = action || 'view';
    var time = player.currentTime().toFixed(3);

    if (logToDb) {
      // Implement your own server logging here
    }

    // Paused
    if (player.paused()) {
      console.log('playLog: ', action + " at " + time + " " + videoId);

    // Playing
    } else {
      console.log('playLog: ', action + ", while playing at " + time + " " + videoId);
      if (action === 'play') {
        var wrapFn = function () {
          playLog(player, videoId, action, logToDb);
        };
        setTimeout(wrapFn, 1000);
      }
    }
  }

  return {
    template: [
      '<div class="video">',
        '<video id="video-{[ video.id ]}" class="video-js vjs-default-skin img-responsive" controls preload="none"',
          ' ng-src="{[ video.mp4 ]}"',
          ' poster="{[ video.jpg ]}"',
          ' width="240" height="120">',
        '</video>',
      '</div>'
    ].join(''),
    scope: {
      video: '=video',
      logToDb: '=logToDb'
    },
    link: function (scope, element, attrs) {
      scope.logToDb = scope.logToDb || false;

      var videoEl = element[0].children[0].children[0];
      var vp = videojs(videoEl, {},
        function(){
          this.on("firstplay", function(){
            playLog(vp, scope.video.id, 'firstplay', scope.logToDb);
          });
          this.on("play", function(){
            playLog(vp, scope.video.id, 'play', scope.logToDb);
          });
          this.on("pause", function(){
            playLog(vp, scope.video.id, 'pause', scope.logToDb);
          });
          this.on("seeking", function(){
            playLog(vp, scope.video.id, 'seeking', scope.logToDb);
          });
          this.on("seeked", function(){
            playLog(vp, scope.video.id, 'seeked', scope.logToDb);
          });
          this.on("ended", function(){
            playLog(vp, scope.video.id, 'ended', scope.logToDb);
          });
        }
      );

    }
  };
});

Directive HTML usage

  <div ng-repeat="row in videos">
        <ui-video video="row"></ui-video>
  </div>
treejanitor
  • 1,249
  • 14
  • 17