JSFiddle - React, Tailwind, and code Playground

by Sahil Kashyap

HTML

<link rel="stylesheet" href="http://vjs.zencdn.net/4.9.1/video-js.css">
<script src="http://vjs.zencdn.net/4.9.1/video.js"></script>
<video id="example_video" class="video-js vjs-default-skin" controls preload="none" width="640" height="264" poster="http://video-js.zencoder.com/oceans-clip.png" data-setup='{}'>
    <source data-res="480" src="http://video-js.zencoder.com/oceans-clip.mp4" type='video/mp4' />
    <source data-res="240" src="http://video-js.zencoder.com/oceans-clip.mp4" type='video/mp4' />
    <source data-res="720" src="http://video-js.zencoder.com/oceans-clip.mp4" type='video/mp4' />
    <track kind="captions" src="demo.captions.vtt" srclang="en" label="English"></track>
    <!-- Tracks need an ending tag thanks to IE9 -->
    <track kind="subtitles" src="demo.captions.vtt" srclang="en" label="English"></track>
    <!-- Tracks need an ending tag thanks to IE9 -->
    <p class="vjs-no-js">To view this video please enable JavaScript, and consider upgrading to a web browser that <a href="http://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
    </p>
</video>

CSS

.vjs-dl-button.vjs-menu-button.vjs-control {
    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAACXBIWXMAAAsTAAALEwEAmpwYAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAA80lEQVR42rSUsUoDQRCGP+WKCHkFX0AsLewOE9DYp0lnYXtPY+MLpRB7X0BSCDFGBA+L87PZQmFn767wh4FlZ+bbhf1nUcnEVL1Xd+o+xS7tTXM9BKCVsVa5nkPyOiZWNheBugKoGwMarX8HfRV6srnq1/oMOAdaoC6A6lRzBDwAj8Cf56/VD4frU51FPpqr2wGQN/W6z5DzVBjpXV0MdfaF+pqB7NXLaEQmahXAtgMglTpBXavL4GYz9SUBr4KapbomndYERagn6mkh36hWaXbagm+eekzdAl0FbIDbZM6xI/MN3ACbA3UB3PV8HSU9A83PAANeN+uxqxQHAAAAAElFTkSuQmCC);
    background-repeat: no-repeat;
    background-position: 10px 4px;
}

JavaScript

/*
 * Videojs Plugin for download
 * By: tutorialspots.com
 * Base on Video.js Resolution Selector (https://github.com/dominic-p/videojs-resolution-selector)
 * Thanks for Dominic P
*/

(function (_V_) {

    var methods = {
        res_label: function (res) {
            return (/^\d+$/.test(res)) ? res + 'p' : res;
        }
    };

    _V_.DownloadMenuItem = _V_.MenuItem.extend({
        call_count: 0,
        init: function (player, options) {
            var touchstart = false;
            // Modify options for parent MenuItem class's init.
            options.label = methods.res_label(options.res);
            // Call the parent constructor
            _V_.MenuItem.call(this, player, options);
            // Store the resolution as a property
            this.resolution = options.res;
            // Register our click and tap handlers
            this.on(['click', 'tap'], this.onClick);
        }
    });

    // Handle clicks on the menu items
    _V_.DownloadMenuItem.prototype.onClick = function () {
        // Check if this has already been called
        if (this.call_count > 0) {
            return;
        }
        // Call the player.changeDl method
        this.player().changeDl(this.resolution);
        // Increment the call counter
        this.call_count++;
    };


    _V_.DownloadTitleMenuItem = _V_.MenuItem.extend({
        init: function (player, options) {
            // Call the parent constructor
            _V_.MenuItem.call(this, player, options);
            // No click handler for the menu title
            this.off('click');
        }
    });

    _V_.DownloadSelector = _V_.MenuButton.extend({

        init: function (player, options) {
            // Add our list of available resolutions to the player object
            player.availableRes = options.available_res;
            // Call the parent constructor
            _V_.MenuButton.call(this, player, options);
            // Set the button text based on the option provided
          ...