Simple HTML5 Custom Video Player Using jQuery (tuPlayer.js)

A few years back if we want to play media(video, audio) on our web page we had to rely on third party tools like flash or java. Especially most of the web sites using flash for their video streaming.
But Flash have some limitation. The client must have the flash plug-in installed. We can not access flash embedded media via JavaScript. We need to know action script to design and add functionality to the player.
But with the arrival of HTML Media API, everything is changed. We can do lots of operations on media using simple JavaScript code. We can control media with our own JavaScript code.


demo download

github

HTML5 Video

If we want to display video we use below code.

<video>  
    <source src="sample_x264.mp4" type="video/mp4" />
    <suorce src="sample_VP8.webm" type="video/webm" />
    <source src="sample_x264_libtheora.ogv" type="video/ogg" />
    <p>Your Browser Does not support</p>
</video>  

Here is a simple video tag with sources. Because all browsers do not support the same format. For example Chrome support MP4,OGG Firefox, Opera support MEBM formats.
Sometimes if the source tags are not in proper ordering the video may not work. For example, even mebm,ogg support by opera above code won't work on Opera.(I will solve this problem in next version)
The second problem is default HTML5 media controls look different in different browsers. They are not consistent. See the below screen shots.

Chrome

FireFox

So, Today I'm gonna create HTML5 video player plug-in using jquery. This plug-in will provide a stranded look an feel across all browsers.
Present version(v1.1) I will create custom controls. My goal is this plugin should work with single line of code.

How to use

<script type="text/javascript" src="jquery-1.9.1.js"></script>  
<script type="text/javascript" src="jquery.tuPlayer.js"></script>  
<script type="text/javascript">  
$(function() { 
  $("video").tuPlayer(); 
}); 
</script> 

Ya that's it you don't need to include any code, not even CSS. The plug-in will take care of player control CSS.

Plug-in code(tuPlayer.js)

/*----------------------------------------------- 
Project: Techumber Custom HTML5 Video Player  
URL: http://techumber.com  
Version: 1.1  
Creator: Aravind Buddha  
Last changed: 05/April/13  
-------------------------------------------------*/
;
(function($, window, document, undefined) {
    var pluginName = "tuPlayer",
        defaults = { //default settings 
            width: "500px",
            autoplay: false,
            preload: true,
            loop: false
        };

    function Plugin(element, options) {
        this.element = element;
        this.options = $.extend({}, defaults, options);
        this._defaults = defaults;
        this._name = pluginName;
        this._video = "";
        this._tuPlayer = "";
        this._contorls = "";
        this._play = "";
        this._progress = "";
        this._progressBar = "";
        this._progressBtn = "";
        this._time = "";
        this._vol = "";
        this._volBar = "";
        this._volBtn = "";
        this._flag = "";
        this._dur = "";
        this.init();
    }

    Plugin.prototype = {
        init: function() {
            //setting Global attribute 
            var self = this;
            _video = $(this.element)[0];
            _video.removeAttribute("controls");
            _dur = $(this.element)[0].duration;
            _flag = 0;

            this.createPlayer();
            this.getControls();
            this.setCSS();
            //to show total time 
            this.showTotalTime();
            //HTML5 Video event to update time 
            _video.addEventListener('timeupdate', function() {
                self.showTime();
            });
            _play.click(function() {
                self.clicktoggle()
            });
            //for seek contorl dragging 
            _progress.bind('mousedown', function(e) {
                self.progSeek(e);
            });
            //for volume contorl dragging 
            _vol.bind('mousedown', function(e) {
                self.volSeek(e);
            });

        },

        //Jquery default toggle function depricated in 1.9.1, 
        //this is custom toggle function for 1.9.1 
        clicktoggle: function() {
            if (_flag) {
                this.pause();
                _flag = 0;
            } else {
                _flag = 1;
                this.play();
            }

        },
        //creating dom for player 
        createPlayer: function() {
            $(this.element).wrap('<div class="tu-player" />');
            _tuPlayer = $(".tu-player");
            _tuPlayer.append('<div class="contrl">' +
                '<div class="play">&#9658;</div>' +
                '<div class="progress"><div class="bar"></div><div class="button"></div></div>' +
                '<div class="time">0:00</div>' +
                '<div class="vlume">' +
                '<div class="bar" style="width: 50px;"></div>' +
                '<div class="button"> </div>' +
                '</div>');
        },
        //getting contorl variables for future usage. 
        getControls: function() {
            _contorls = $(".tu-player .contrl");
            _play = _contorls.find(".play");
            _progress = $(".tu-player .progress");
            _progressBar = _progress.find(".bar");
            _progressBtn = $(".tu-player .progress .button");
            _time = $(".tu-player .time");
            _vol = $(".tu-player .vlume");
            _volBar = $(".tu-player .vlume .bar");
            _volBtn = $(".tu-player .vlume .button");
        },
        //setting css rules on custom contorls 
        setCSS: function() {
            _tuPlayer.css({
                "width": this.options.width
            });
            _tuPlayer.find('video').css({
                "width": "100%"
            });
            _contorls.css({
                'height': '30px',
                'color': '#fff',
                'border': '1px solid #404040',
                'background': '#2a2a2a',
                'opacity': '0.75',
                'width': '98%',
                'margin': '0 auto 20px',
                'border-radius': '5px',
                'position': 'relative',
                'top': '-42px'
            });

            _play.css({
                'width': '15px',
                'cursor': 'pointer',
                'float': 'left',
                'margin-left': '10px',
                'line-height': '30px'
            });
            _progress.css({
                'height': '5px',
                'border-bottom': '1px solid #1f1f1f',
                'border-top': '1px solid #222',
                'width': '60%',
                'border-radius': '5px',
                'background': '#676767',
                'box-shadow': 'inset 0 -5px 10px rgba(0,0,0,0.1)',
                'cursor': 'pointer',
                'margin': '12px 0 0 10px',
                'float': 'left',
                'margin-left': '10px',
                'line-height': '30px'
            });
            _progressBar.css({
                'background': '#33b5d5',
                'height': '5px',
                'width': '0',
                'float': 'left'

            });
            _progressBtn.css({
                'border-radius': '5px',
                'width': '19px',
                'height': '11px',
                'background': '#fff',
                'margin': '-3px 0 0 0',
                'float': 'left',
                'line-height': '30px'
            });
            _time.css({
                'float': 'left',
                'margin-left': '10px',
                'line-height': '30px'
            });
            _vol.css({
                'width': '20%',
                'height': '5px',
                'margin': '12px 0 0 0',
                'border-bottom': '1px solid #333',
                'border-radius': '3px',
                'background': '#111',
                'float': 'left',
                'margin-left': '10px',
                'line-height': '30px'
            });
            _volBar.css({
                'background': '#c61003',
                'height': '5px',
                'border-radius': '3px 0 0 3px',
                'cursor': 'pointer',
                'float': 'left'
            });
            _volBtn.css({
                'width': '5px',
                'height': '15px',
                'background': '#696969',
                'border-radius': '3px',
                'margin-top': '-5px',
                'cursor': 'pointer',
                'float': 'left'
            });
        },
        //on play 
        play: function() {
            _video.play();
            _play.html("&#2405;");
        },
        //on pause 
        pause: function() {
            _video.pause();
            _play.html("&#9658;");
        },
        //display video time 
        showTime: function() {
            var time, min = 0,
                sec = 00;
            time = Math.round(_video.currentTime);
            min = Math.floor(time / 60);
            if (time) {
                sec = Math.round(time) - (60 * min);
                if (sec > 59) {
                    sec = Math.round(time) - (60 * min);
                    if (sec == 60) {
                        min = Math.round(time / 60);
                        sec = 0;
                    }
                }
            }
            _time.html(("0" + min).slice(-2) + ':' + ("0" + sec).slice(-2));
        },
        //display total video time 
        showTotalTime: function() {
            var time, min = 0,
                sec = 00;
            time = Math.round(_dur);
            min = Math.floor(time / 60);
            if (time) {
                sec = Math.round(time) - (60 * min);
                if (sec > 59) {
                    sec = Math.round(time) - (60 * min);
                    if (sec == 60) {
                        min = Math.round(time / 60);
                        sec = 0;
                    }
                }
            }
            _time.html(("0" + min).slice(-2) + ':' + ("0" + sec).slice(-2));
        },
        //progress seek 
        progSeek: function(e) {
            var x = e.pageX - _progress.offset().left;
            _progressBar.css({
                'max-width': _progress.width() - 20
            });
            _progressBar.css({
                'width': x
            });
            _video.currentTime = (x / _progress.width()) * _dur;
        },
        //volume seek 
        volSeek: function(e) {
            var x = e.pageX - _vol.offset().left;
            _volBar.css({
                'max-width': _vol.width() - 6
            })
            _volBar.css({
                'width': x
            });
            _video.volume = x / _vol.width();
        }
    };

    // preventing against multiple instantiations 
    $.fn[pluginName] = function(options) {
        return this.each(function() {
            if (!$.data(this, "plugin_" + pluginName)) {
                $.data(this, "plugin_" + pluginName, new Plugin(this, options));
            }
        });
    };

})(jQuery, window, document);

Get posts by email

Like what you're reading? Get these posts delivered to your inbox.