JSFiddle - React, Tailwind, and code Playground

by rich_harris

HTML

<main></main>

<script id='template' type='text/ractive'>
    <button on-click='loadVideo()'>change source</button>
    
    <div class='video-container'>
        {{#if src}}
            <video decorator='myVideoDecorator:{{src}}' controls>
                <source type='video/mp4' src='{{src}}.mp4'/> 
                <source type='video/webm' src='{{src}}.webm'/> 
            </video>
        {{else}}
            <div class='loading'><span>loading</span></div>
        {{/if}}
    </div>
</script>

CSS

body {
    font-family: 'Helvetica Neue', arial, sans-serif;
    font-weight: 200;
    color: #353535;
}

h1, h2, h3, h4, h5, h6 {
    font-weight: 200;
}

.error {
    color: #d00;
    font-family: monospace;
}

.video-container {
    position: relative;
    width: 100%;
    padding: 0 0 56.25% 0;
    text-align: center;
}

button {
    margin: 0 0 1em 0;
}

video, .loading {
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
}

.loading {
    background-color: #eee;
    text-align: center;
}

.loading span {
    position: absolute;
    width: 100%;
    left: 0;
    top: 50%;
    transform: translate(0,-50%);
}

JavaScript

var sources = [
    'http://clips.vorwaerts-gmbh.de/big_buck_bunny',
    'http://media.sublimevideo.net/v/midnight-sun-short-edit-360p'  
];

var i = 0;

var ractive = new Ractive({
    el: 'main',
    template: '#template',
    data: {
        src: null
    },
    loadVideo: function () {
        this.set( 'src', null );
        this.set( 'src', sources[ i++ ] );
        i %= sources.length;
    },
    decorators: {
        myVideoDecorator: function ( node, src ) {
            console.log( 'video source', src );
            node.play();
            
            return {
                update: function ( src ) {
                    console.log( 'video source changed to ', src );
                },
                teardown: function () {
                    console.log( 'tearing down' );
                }
            };
        }
    }
});