2

I made animation in which, all the loaded comments appears and disappear when next comment comes.

I made DEMO so please, check it!

The problem is that timeupdate is working about 10 times per second.
So animation is being fired for 10 times for every comment:(
Please see DEMO, and you'll notice that it looks weird move.

How can I handle that? Can anyone modify my code in JSfiddle, please.

These are my code.

javascript

jQuery(document).ready(function () {
    $('#video').on('timeupdate',function(e){
            showComments(this.currentTime);  
    });

}); 
var comments = [{'time':'10','message':'hello! 10 secs has past'},{'time':'15','message':'hello! 15 secs has past'},{'time':'5','message':'hello! 5 secs has past'},{'time':'20','message':'hello! 20 secs has past'}];


function showComments(time){
    var comments = findComments(time);
    $.each(comments,function(i,comment){
        $('.newsticker p').animate({"marginLeft":"400px","opacity":".0"}, 600).fadeOut(100);
        $('.newsticker').append("<p style='margin-left:400px;opacity:0'>"+comment.message+"</p>");
        $('.newsticker p').animate({"marginLeft":"0px","opacity":"1"}, 600);
    });
}

function findComments(time){
    return $.grep(comments, function(item){
      return item.time == time.toFixed();
    });
}

HTML

<body>
    <div class="newsticker"> 
    </div>
    <br />
    <br />
    <video id="video" controls="controls" autoplay="autoplay" name="media"><source src="http://media.w3.org/2010/05/sintel/trailer.mp4" type="video/mp4"></video>
</body>

CSS

div.newsticker{
    border:1px solid #666666;
    width:100%;
    height:50px;
}

.newsticker p{
    height:20px;
    width:150px;
    float:left;
    position:absolute;
}
MKK
  • 2,713
  • 5
  • 31
  • 51
  • 1
    I'll up you one: the firing interval for timeupdated depends on the browser. In chrome it's about every 250ms, in FF it's for every frame. Isn't it better to mark a comment as displayed once you display it and change findComments so it won't find displayed comments? – MrP Aug 23 '13 at 10:19
  • 2
    Oooh, to busy watching the totally irrelevant video to actually change any code ! – adeneo Aug 23 '13 at 10:22
  • @MrP Something like `if(comments != last_comments){ transaction; last_comments = comments;}`? – MKK Aug 23 '13 at 10:22
  • check this also http://stackoverflow.com/questions/9678177/how-often-does-the-timeupdate-event-fire-for-an-html5-video – Nicolae Olariu Aug 23 '13 at 10:24

2 Answers2

3

Add a shown flag into the comments, and check for that, update where appropriate.

Note, I've also renamed some local variables to prevent clashes with parent scope ones (doesn't impact the code, but firebug got a bit funny about showing me the correct thing)

Updated

Converted it into a jquery plugin, for cleanliness, also put the check around the time as @BMH's answer (so feel free to mark his as the accepted). Stopped it showing all the comments for a timestamp if there's more than one, and will re-show a comment if re-wound to a previous time:

http://jsfiddle.net/9zqhF/12/

jQuery.fn.videoComments = function(options){
    var defaults = {
        "comments" : [
            {'time':'10','message':'hello! 10 secs has past'},
            {'time':'15','message':'hello! 15 secs has past'},
            {'time':'5','message':'hello! 5 secs has past'},
            {'time':'20','message':'hello! 20 secs has past'}
        ],
    };

    var options = $.extend(defaults, options);

    if(!options.commentHolder){
        throw "videoComments requires a commentHolder to put the comments in";
    }

    function setComment(message){
            $commentContainer.css({
                "marginLeft" : "400px",
                "opacity": "0"
            }).html(message);
    };

    var $commentContainer = $("<p></p>");
    setComment("");

    $(options.commentHolder).append($commentContainer);

    function showComments(time){
        var foundComments = findComments(time);
        $.each(foundComments,function(i,comment){
            $commentContainer.animate({"marginLeft":"400px","opacity":".0"}, 600);
            setComment(comment.message);
            $commentContainer.animate({"marginLeft":"0px","opacity":"1"}, 600);
        });
    };

    function findComments(timeToFind){
        var matchingComments = $.grep(options.comments, function(item){
          return (item.time == timeToFind);
        });

        return matchingComments;
    };

    return $(this).each(function(){
        var currentTime = -1;
        $(this).on("timeupdate", function(e) {
            var localTime = this.currentTime.toFixed();
            if(currentTime != localTime){
                currentTime = localTime;
                showComments(currentTime); 
            }
        });
    });
};

$("#video").videoComments({
    "commentHolder" : $(".newsticker")    
})
Psytronic
  • 6,043
  • 5
  • 37
  • 56
  • Hey but what if a user rewind the video? the comments that are already shown won't appear anymore. Please cover this problem! – MKK Aug 23 '13 at 10:29
  • True, okay, I'll tweak – Psytronic Aug 23 '13 at 10:30
  • @Psytronic what if calling from jwplayer onTime? `jwplayer("myElement").onTime(function(time){showComments(Math.round(time.position));})` – MKK Aug 23 '13 at 11:13
  • 1
    Can't say I've ever used jwplayer (or heard of it until now). I would think that you could do something like: `$(jwplayer("myElement")).videoComments(); jwplayer("myElement").onTime(function(time) { this.trigger("timeupdate"); });` ? – Psytronic Aug 23 '13 at 11:24
  • @Psytronic Your code made it perfect but one more thing. How can you show comment right in the middle of vertical align? For example, if the comment is too long, and and it becomes two lines, it looks kinda positioning in the middle of vertical align. But if it's one line, it looks that the comment is shown a little bit above than middle position. Can you fix this? – MKK Aug 26 '13 at 06:10
2

I would put flag in the ready function:

http://jsfiddle.net/b_m_h/9zqhF/11/

    jQuery(document).ready(function () {
    var fixedTime = 0;
    $('#video').on('timeupdate',function(e){
        if(this.currentTime.toFixed() != fixedTime){
            showComments(fixedTime);
            fixedTime = this.currentTime.toFixed()
        }  
    });

}); 
var comments = [{'time':'10','message':'hello! 10 secs has past'},{'time':'10','message':'hello! part-2 10 secs has past'},{'time':'15','message':'hello! 15 secs has past'},{'time':'5','message':'hello! 5 secs has past'},{'time':'20','message':'hello! 20 secs has past'}];


function showComments(time){
    var coms = findComments(time);
    if(coms[0]){
            $('.newsticker p').animate({"marginLeft":"400px","opacity":".0"}, 600).fadeOut(100);
            $('.newsticker').append("<p style='margin-left:400px;opacity:0'>"+coms[0].message+"</p>");
            $('.newsticker p').animate({"marginLeft":"0px","opacity":"1"}, 600);
    }
}

function findComments(time){
    return $.grep(comments, function(item){
      return item.time == time;
    });
}
BMH
  • 4,280
  • 1
  • 18
  • 18
  • Thanks for an answer. If there were two comments in 10 secs, it looks weird(Please check http://jsfiddle.net/9zqhF/6/) How can you disable `part2` at 10 seconds? If there were more than 2 comments at the same second, I want to ignore second and all the comments after that. – MKK Aug 23 '13 at 10:53
  • So you only want the first comment for any given second? – Psytronic Aug 23 '13 at 10:55
  • @Psytronic Please check my demo on JSfiddle http://jsfiddle.net/9zqhF/6/ Do you see there are two comments at 10 seconds? I want to ignore 2nd comment if there are more than 2 comments at the same second. I'd precede 1st comment to show. – MKK Aug 23 '13 at 10:58
  • 1
    if so you don't need to use `each` function. I have update my answer, just for reference. – BMH Aug 23 '13 at 11:13