<header class="c-banner" id="top">
    <a class="c-banner__skip" href="#main">Skip to content</a>
    <p class="c-banner__title">
        <a class="c-banner__home" href="/pages/" rel="home">24 ways <span>to impress your friends</span></a>
    </p>
</header>

<div class="c-menu no-transition">
    <button class="c-menu__button" id="menu__button" aria-controls="menu__drawer" aria-expanded="true" aria-label="Menu">
        <svg class="c-menu__icon" width="20" height="20" viewBox="0 0 200 200" focusable="false" aria-hidden="true">
            <rect class="c-menu__line" width="120" height="10" x="40" y="45" />
            <rect class="c-menu__line" width="120" height="10" x="40" y="70" />
            <rect class="c-menu__line" width="120" height="10" x="40" y="95" />
            <rect class="c-menu__line" width="120" height="10" x="40" y="95" />
            <rect class="c-menu__line" width="120" height="10" x="40" y="120" />
            <rect class="c-menu__line" width="120" height="10" x="40" y="145" />
        </svg>

    </button>
    <div class="c-menu__drawer" id="menu__drawer" role="region" aria-label="Menu">
        <form class="c-search" role="search" id="search" action="/pages/search/">
            <fieldset class="c-field">
                <legend class="u-hidden">Search 24 ways</legend>
                <label class="u-hidden" for="q">Keywords</label>
                <input class="c-field__input" type="search" id="q" name="q" placeholder="e.g. CSS, Design, Research&#8230;" />
                <button class="c-field__button" type="submit"><svg class="c-field__icon" width="20" height="20" viewBox="0 0 200 200" focusable="false" role="img" aria-label="Search">
                        <path role="presentation" d="M129 121C136 113 140 102 140 90c0-28-22-50-50-50S40 63 40 90s22 50 50 50c12 0 24-4 32-12L158 164l7-7-36-36zM90 130c-22 0-40-18-40-40s18-40 40-40 40 18 40 40-18 40-40 40z" />
                    </svg>
                </button>
            </fieldset>
        </form>
        <nav class="c-topics-nav" aria-label="Topics">
            <ul class="c-topics-nav__items">
                <li class="c-topics-nav__item">
                    <a class="c-topics-nav__label" href="/topics/business/">
                        <svg width="16" height="16" viewBox="0 0 240 240" focusable="false" aria-hidden="true">
                            <path d="M20 220c-11 0-20-9-20-20V70c0-11 9-20 20-20h60V35c0-10 5-15 15-15h50c10 0 15 5 15 15v15h60c11 0 20 9 20 20v130c0 11-9 20-20 20H20zm0-160c-5.5 0-10 4.5-10 10v130c0 5.5 4.5 10 10 10h200c5.5 0 10-4.5 10-10V70c0-5.5-4.5-10-10-10H20zm130-10V35c0-3-2-5-5-5H95c-3 0-5 2-5 5v15h60zM30 100V90h180v10H30zm0 40v-10h180v10H30zm0 40v-10h180v10H30z" />
                        </svg>

                        Business
                    </a>
                </li>
                <li class="c-topics-nav__item">
                    <a class="c-topics-nav__label" href="/topics/code/">
                        <svg width="16" height="16" viewBox="0 0 240 240" focusable="false" aria-hidden="true">
                            <path transform="rotate(45 120 120)" d="M115 100H70.5C63 85 47.5 75 30 75 8.5 75-9.5 90-14 110h29l10 10-10 10h-29c4.5 20 22.5 35 44 35 17.5 0 33-10 40.5-25h99.5c7.5 15 22.5 25 40.5 25 21.5 0 39.5-15 44-35h-29l-10-10 10-10h29c-4.5-20-22.5-35-44-35-17.5 0-33 10-40.5 25H125V30h10v-50h-30v50h10v70zm123.5 40c-6.5 9-17 15-28.5 15-16 0-29-10.5-33.5-25H63.5C59 144.5 46 155 30 155c-12 0-22.5-6-28.5-15H20l20-20-20-20H1.5C7.5 91 18 85 30 85c16 0 29 10.5 33.5 25h113c4.5-14.5 17.5-25 33.5-25 12 0 23 6 29 15h-19l-20 20 20 20h19zM115-10h10v30h-10v-30zM99.5 240v-50h-10v-10h25v-40h10v40h25v10H140v50c0 10-7.5 20-20 20-12.5 0-20-10-20.5-20zm11 0c0 7.5 5 10 10 10s10-2.5 10-10v-50h-20v50z" />
                        </svg>

                        Code
                    </a>
                </li>
                <li class="c-topics-nav__item">
                    <a class="c-topics-nav__label" href="/topics/content/">
                        <svg width="16" height="16" viewBox="0 0 240 240" focusable="false" aria-hidden="true">
                            <path d="M102.5 240l-1.5-2c-2.5-3.5-61-88-61-128s40.5-64 42.5-65L50 0h140l-32.5 45S200 70 200 110s-58.5 124.5-61 128l-1.5 2h-35zm30-10c9-13 57.5-85.5 57.5-120 0-33-35-56-41.5-60H91.5C85 54 50 77 50 110c0 34.5 48.5 106.5 57.5 120h25zM115 129.5c-11.5-2-20-12.5-20-24.5 0-14 11-25 25-25s25 11 25 25c0 12-8.5 22-20 24.5V230h-10V129.5zm5-39.5c-8 0-15 6.5-15 15s6.5 15 15 15 15-6.5 15-15-6.5-15-15-15zM92.5 40h55L170 10H70l22.5 30z" />
                        </svg>

                        Content
                    </a>
                </li>
                <li class="c-topics-nav__item">
                    <a class="c-topics-nav__label" href="/topics/design/">
                        <svg width="16" height="16" viewBox="0 0 240 240" focusable="false" aria-hidden="true">
                            <path fill-rule="evenodd" d="M140 0h80v240h-80V0zm70 10h-60v30h20v10h-20V70h20v10h-20v20h20v10h-20v20h20v10h-20v20h20v10h-20v20h20v10h-20V230h60V10zM45 230c-14 0-25-11-25-25V60c0-1 35-55 35-55s35 54 35 55v145c0 14-11 25-25 25H45zm-15-25c0 8 7 15 15 15h20c8 0 15-7 15-15v-5H30v5zm0-25v10h50v-10H30zm0-106c0-2 2-4 4-4h2c2 0 4 2 4 4v96H30V74zm20 0c0-2 2-4 4-4h2c2 0 4 2 4 4v96H50V74zm20 0c0-2 2-4 4-4h2c2 0 4 2 4 4v96H70V74zM30.5 60.5S39 58 45 63.5c6-4.5 14-4.5 20 0 6-5.5 14.5-3 14.5-3L69 45H41L30.5 60.5zm24.5-38L47.5 35h15L55 22.5z" />
                        </svg>

                        Design
                    </a>
                </li>
                <li class="c-topics-nav__item">
                    <a class="c-topics-nav__label" href="/topics/process/">
                        <svg width="16" height="16" viewBox="0 0 240 240" focusable="false" aria-hidden="true">
                            <path d="M210 116v4c0 49.5-40.5 90-90 90-29 0-55-14-71.5-35l7-7c14.5 19.5 38 32 64.5 32 44 0 80-36 80-80v-3.5l-15.5 16-7.5-7.5 28.5-28.5L234 125l-7.5 7.5L210 116zm-180 8v-4c0-49.5 40.5-90 90-90 29 0 54.5 13.5 71 35l-7 7C169 52.5 146 40 120 40c-44 0-80 36-80 80v5l17-17 7 7-28.5 28.5L7 115l7-7 16 16z" />
                        </svg>

                        Process
                    </a>
                </li>
                <li class="c-topics-nav__item">
                    <a class="c-topics-nav__label" href="/topics/ux/">
                        <svg width="16" height="16" viewBox="0 0 240 240" focusable="false" aria-hidden="true">
                            <path d="M220 240H20c-11 0-20-9-20-20V20C0 9 9 0 20 0h200c11 0 20 9 20 20v200c0 11-9 20-20 20zM20 10c-5 0-10 4-10 10v200c0 5 4 10 10 10h200c5 0 10-4 10-10V20c0-5-4-10-10-10H20zm150 200c-11 0-20-9-20-20s9-20 20-20 20 9 20 20-9 20-20 20zm0-30c-5 0-10 4-10 10s4 10 10 10 10-4 10-10-4-10-10-10zm-50 30c-11 0-20-9-20-20s9-20 20-20 20 9 20 20-9 20-20 20zm0-30c-5 0-10 4-10 10s4 10 10 10 10-4 10-10-4-10-10-10zm-50 30c-11 0-20-9-20-20s9-20 20-20 20 9 20 20-9 20-20 20zm0-30c-5 0-10 4-10 10s4 10 10 10 10-4 10-10-4-10-10-10zm45-30V80h10v70h-10zm0-100V30h10v20h-10zM65 80V30h10v50H65zm0 70v-40h10v40H65zm100 0v-20h10v20h-10zm0-50V30h10v70h-10zM50 110V80h40v30H50zm10-10h20V90H60v10zm90 30v-30h40v30h-40zm-50-50V50h40v30h-40zm10-10h20V60h-20v10zm50 50h20v-10h-20v10z" />
                        </svg>

                        UX
                    </a>
                </li>
            </ul>
        </nav>
        <nav class="c-site-nav" aria-label="Explore 24 ways">
            <ul class="c-site-nav__items">
                <li class="c-site-nav__item">
                    <a class="c-site-nav__label" href="/archives/">Archives</a>
                </li>
                <li class="c-site-nav__item">
                    <a class="c-site-nav__label" href="/authors/">Authors</a>
                </li>
                <li class="c-site-nav__item">
                    <a class="c-site-nav__label" href="/about/" aria-label="About this website">About</a>
                </li>
            </ul>
        </nav>
    </div>
    <script class="c-menu__onload">
        document.getElementById('menu__drawer').style.display = 'none';
    </script>
</div>

<main class="c-main" id="main">

    <article class="c-article  h-entry">
        <header class="c-article__header">
            <h1 class="c-article__title  p-name">Starting Your HTML5 Project on the Right Foot (and Keeping It There)</h1>
            <p class="c-article__byline  p-author h-card">
                <a class="u-url" href="#author">
                    <img class="c-avatar  u-photo" src="https://cloud.24ways.org/authors/drewmclellan280.jpg" width="280" height="280" alt="Drew McLellan" />

                    <span class="p-name">Drew McLellan</span>
                </a>
            </p>
        </header>

        <footer class="c-article__footer">
            <ul class="c-meta">
                <li class="c-meta__item"><time class="dt-published" datetime="2012-12-01T00:00:00-00:00">1 Dec<span>ember</span> 2012</time></li>
                <li class="c-meta__item">Published in <a href="/topics/code/">Code</a></li>
                <li class="c-meta__item"><a href="#comments">8 comments</a></li>
            </ul>

        </footer>

        <div class="c-article__main e-content">
            <div class="s-note">
                <p><strong>A note from the editors:</strong> While brilliant for its time, this article no longer reflects modern best practices.</p>

            </div>

            <div class="s-prose s-prose--article">
                <p class="lede">Video is a bigger part of the web experience than ever before. With native browser support for <span class="caps">HTML5</span> video elements freeing us from the tyranny of plugins, and the availability of faster <strong>internet</strong> connections to the workplace, home and mobile networks, it’s now pretty straightforward to publish video in a way that can be consumed in all sorts of ways on all sorts of different web devices.</p>
                <p>I recently worked on a project where the client had shot some dedicated video shorts to publish on their site. They also had some <strong>five-second</strong> motion graphics produced to top and tail the videos with context and branding. This pretty common requirement is a great idea on the web, where a user might land at your video having followed a link and be viewing a page without much context.</p>
                <blockquote>
                    <p>[I]t appears probable that the progenitors of man, either the males or females or both sexes, before acquiring the power of expressing their mutual love in articulate language, endeavoured to charm each other with musical notes and rhythm.</p>
                    <footer>—Charles <span class="caps">DARWIN</span>, <cite>The Descent of Man, and Selection in Relation to Sex</cite>, 1871</footer>
                </blockquote>
                <p>Known as <em>bumpers</em>, these short introduction clips help brand a video and make it look a lot more professional.</p>
                <figure>
                    <img src="https://media.24ways.org/2013/baxter/indexcards.jpg" alt="Index cards">
                    <figcaption>Index cards represent each feature the rental property software would launch with.</figcaption>
                </figure>
                <figure>
                    <div class="s-gallery">
                        <img src="https://media.24ways.org/2013/baxter/indexcards.jpg" alt="Index cards">
                        <img src="https://media.24ways.org/2013/baxter/indexcards.jpg" alt="Index cards">
                    </div>
                    <figcaption>Index cards represent each feature the rental property software would launch with.</figcaption>
                </figure>
                <figure>
                    <div class="s-gallery">
                        <img src="https://media.24ways.org/2013/baxter/indexcards.jpg" alt="Index cards">
                        <img src="https://media.24ways.org/2013/baxter/indexcards.jpg" alt="Index cards">
                        <img src="https://media.24ways.org/2013/baxter/indexcards.jpg" alt="Index cards">
                    </div>
                    <figcaption>Index cards represent each feature the rental property software would launch with.</figcaption>
                </figure>
                <figure>
                    <div class="s-gallery">
                        <img src="https://media.24ways.org/2013/baxter/indexcards.jpg" alt="Index cards">
                        <img src="https://media.24ways.org/2013/baxter/indexcards.jpg" alt="Index cards">
                        <img src="https://media.24ways.org/2013/baxter/indexcards.jpg" alt="Index cards">
                        <img src="https://media.24ways.org/2013/baxter/indexcards.jpg" alt="Index cards">
                    </div>
                    <figcaption>Index cards represent each feature the rental property software would launch with.</figcaption>
                </figure>
                <h2>Heading 2</h2>
                <p>The simplest way to add bumpers to a video would be to edit them on to the start and end of the video file itself. Cooking the bumpers into the video file is easy, but should you ever want to update them it can become a real headache. If the branding needs updating, for example, you’d need to re-edit and re-encode all your videos. Not a fun task.</p>
                <p>Save the document by pressing <kbd><kbd>Ctrl</kbd> + <kbd>S</kbd></kbd></p>
                <p>There are many, many options for recording your screen, including QuickTime Player on Mac OS X (<kbd><kbd><samp>File</samp></kbd><kbd><samp>New Screen Recording</samp></kbd></kbd>), <a href="http://www.gifgrabber.com/">GifGrabber</a>, or <a href="http://giffingtool.com">Giffing Tool</a> on Windows.</p>
                <p>Just <samp>sample</samp> text.</p>
                <h2>Heading 2…</h2>
                <h3>…followed by a heading 3</h3>
                <p>What if the bumpers could be added dynamically? That would enable you to use the same bumper for multiple videos (decreasing download time for users who might watch more than one) and to update the bumpers whenever you wanted. You could change them seasonally, update them for special promotions, run different advertising slots, perform multivariate testing, or even target different bumpers to different users.</p>
                <p><a href="#">View an example</a></p>
                <blockquote>
                    <p>The responsive projects I’ve worked on have had a lot of success combining design and development into one hybrid phase, bringing the two teams into one highly collaborative group.</p>
                    <ul>
                        <li>A list inside a blockquote</li>
                        <li>Is a very fine thing</li>
                    </ul>
                    <p>A lot of success combining design and development into one hybrid phase, bringing the two teams into one highly collaborative group.</p>
                    <ol>
                        <li>How about an ordered list</li>
                        <li>Inside a blockquote, too?</li>
                    </ol>
                </blockquote>
                <h3>Heading 3</h3>
                <p>The trade-off, of course, is that if you dynamically add your bumpers, there’s a chance that a user in a given circumstance might not see the bumper. For example, if the main video feature was uploaded to YouTube, you’d have no way to control the playback. As always, you need to weigh up the pros and cons and make your choice.</p>
                <h4>Heading 4</h4>
                <p>If you wanted to dynamically add bumpers to your <abbr title="Hyper Text Markup Language 5">HTML5</abbr> video, how would you go about it? That was the question I found myself needing to answer for this particular client project.</p>
                <h5>Heading 5</h5>
                <p>My initial thought was to treat it just like an image slideshow. If I were building a slideshow that moved between images, I’d use <abbr title="Cascading Style Sheets">CSS</abbr> absolute positioning with <code>z-index</code> to stack the images up on top of each other in a pile, with the first image on top. To transition to the second image, I’d use JavaScript to fade the top image out, revealing the second image beneath it.</p>
                <figure>
                    <div class="s-embed s-embed--widescreen">
                        <iframe src="https://www.youtube.com/embed/QILiHiTD3uc" allowfullscreen></iframe>
                    </div>
                    <figcaption>Example of responsive video embed.</figcaption>
                </figure>
                <p>Now that video is just a native object in the <span class="caps">DOM</span>, just like an image, why not do the same? Stack the videos up with the opening bumper on top, listen for the video’s <code>onended</code> event, and fade it out to reveal the main feature behind. Good idea, right?</p>
                <table>
                    <thead>
                        <tr>
                            <th>The Very Best <code>Eggnog</code></th>
                            <th>Serves 12</th>
                            <th>Serves 24</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr>
                            <td>Milk</td>
                            <td>1 quart</td>
                            <td>2 quart</td>
                        </tr>
                        <tr>
                            <td>Cinnamon Sticks</td>
                            <td>1</td>
                            <td>2</td>
                        </tr>
                        <tr>
                            <td>Vanilla Bean, Split</td>
                            <td>1</td>
                            <td>2</td>
                        </tr>
                        <tr>
                            <td>Cloves</td>
                            <td>5</td>
                            <td>10</td>
                        </tr>
                        <tr>
                            <td>Mace</td>
                            <td>10</td>
                            <td>20</td>
                        </tr>
                        <tr>
                            <td>Egg Yolks</td>
                            <td>12</td>
                            <td>24</td>
                        </tr>
                        <tr>
                            <td>Cups Sugar</td>
                            <td>1 ½ cups</td>
                            <td>3 cups</td>
                        </tr>
                        <tr>
                            <td>Dark Rum</td>
                            <td>1 ½ cups</td>
                            <td>3 cups</td>
                        </tr>
                        <tr>
                            <td>Brandy</td>
                            <td>1 ½ cups</td>
                            <td>3 cups</td>
                        </tr>
                        <tr>
                            <td>Vanilla</td>
                            <td>1 tbsp</td>
                            <td>2 tbsp</td>
                        </tr>
                        <tr>
                            <td>
                                <ul>
                                    <li>Light Cream</li>
                                    <li>Double Cream</li>
                                </ul>
                            </td>
                            <td>1 quart</td>
                            <td>2 quart</td>
                        </tr>
                    </tbody>
                </table>
                <p>Remember that this is the web. It’s never going to be that easy. The problem here is that many non-desktop devices use native, dedicated video players. Think about watching a video on a mobile phone – when you play the video, the phone often goes full-screen in its native player, leaving the web page behind. There’s no opportunity to fade or switch <code>z-index</code>, as the video isn’t being viewed in the page. Your page is left powerless. Powerless!</p>
                <img src="https://media.24ways.org/2012/mclellan/media-player.jpg" alt="iOS full-screen media player" />
                <p>So what can we do? What can we control?</p>
                <hr />
                <p>Those of us with particularly long memories might recall a time before <abbr title="Cascading Style Sheets">CSS</abbr>, when we’d have to use JavaScript to perform image rollovers. As <abbr title="Cascading Style Sheets">CSS</abbr> background images weren’t a practical reality, we would use lots of <code>&lt;img&gt;</code> elements, and perform a rollover by modifying the <code>src</code> attribute of the image.</p>
                <figure class="pull-right">
                    <img src="https://media.24ways.org/2013/baxter/indexcards.jpg" alt="Index cards">
                    <figcaption>Index cards represent each feature the rental property software would launch with.</figcaption>
                </figure>
                <p>Turns out, this old trick of modifying the source can help us out with video, too. In most cases, modifying the <code>src</code> attribute of a <code>&lt;video&gt;</code> element, or perhaps more likely the <code>src</code> attribute of a <code>source</code> element, will swap from one video to another.</p>
                <h2>Swappin’ it</h2>
                <p>Let’s take a deliberately simple example of a super-basic video tag:</p>
                <pre><code class="language-html">&lt;video src=&quot;mycat.webm&quot; controls&gt;no fallback coz i is lame, innit.&lt;/video&gt;
</code></pre>
                <p>We could very simply write a script to find all video tags and give them a new <code>src</code> to show our bumper.</p>
                <pre><code class="language-html">&lt;script&gt;
  var videos, i, l;
  videos = document.getElementsByTagName('video');

  for(i=0, l=videos.length; i&lt;l; i++) {
    videos[i].setAttribute('src', 'bumper-in.webm');
  }
&lt;/script&gt;
</code></pre>
                <p><a href="https://media.24ways.org/2012/mclellan/examples/1.html">View the example</a> in a browser with WebM support. You’ll see that the video is swapped out for the opening bumper. Great!</p>
                <h2>Beefing it up</h2>
                <p>Of course, we can’t just publish video in one format. In practical use, you need a <code>&lt;video&gt;</code> element with multiple <code>&lt;source&gt;</code> elements containing your different source formats.</p>
                <pre><code class="language-html">&lt;video controls&gt;
  &lt;source src=&quot;mycat.mp4&quot; type=&quot;video/mp4&quot; /&gt;
  &lt;source src=&quot;mycat.webm&quot; type=&quot;video/webm&quot; /&gt;
  &lt;source src=&quot;mycat.ogv&quot; type=&quot;video/ogg&quot; /&gt;
&lt;/video&gt;
</code></pre>
                <p>This time, our script needs to loop through the sources, not the videos. We’ll use a regular expression replacement to swap out the file name while maintaining the correct file extension.</p>
                <pre><code class="language-html">&lt;script&gt;
  var sources, i, l, orig;
  sources = document.getElementsByTagName('source');

  for(i=0, l=sources.length; i&lt;l; i++) {
    orig = sources[i].getAttribute('src');
    sources[i].setAttribute('src', orig.replace(/(w+).(w+)/, 'bumper-in.$2'));

    // Reload the video
    sources[i].parentNode.load();
  }
&lt;/script&gt;
</code></pre>
                <p>The difference this time is that when changing the <code>src</code> of a <code>&lt;source&gt;</code> we need to call the <code>.load()</code> method on the video to get it to acknowledge the change.</p>
                <p><a href="https://media.24ways.org/2012/mclellan/examples/2.html">See the code in action</a>, this time in a wider range of browsers.</p>
                <h2>But, my video!</h2>
                <ul>
                    <li>Store the original <code>src</code> in a <code>data-</code> attribute so we can access it later</li>
                    <li>Add an event listener so we can detect the end of the bumper playing, and load the original video back in</li>
                </ul>
                <p>I guess we should get the original video playing again. Keeping the same markup, we need to modify the script to do two things:</p>
                <ul>
                    <li>Store the original <code>src</code> in a <code>data-</code> attribute so we can access it later</li>
                    <li>Add an event listener so we can detect the end of the bumper playing, and load the original video back in</li>
                </ul>
                <p>As we need to loop through the videos this time to add the event listener, I’ve moved the <code>.load()</code> call into that loop. It’s a bit more efficient to call it only once after modifying all the video’s sources.</p>
                <ul>
                    <li><strong>Raspberry Pi</strong> any of the following models :
                        <ul>
                            <li>Zero (will need straight male header pins soldered2 and Micro USB OTG adaptor),
                                <ul>
                                    <li>A+, B+, 2 or 3</li>
                                </ul>
                            </li>
                        </ul>
                    </li>
                    <li><strong>Micro SD card</strong> at least 4Gb Class 10 speed3</li>
                    <li><strong>Micro USB power supply</strong> at least 2A</li>
                    <li><strong>USB Wifi dongle</strong> (unless you have a Pi 3 - that has wifi built in).</li>
                </ul>
                <pre><code class="language-html">&lt;script&gt;
  var videos, sources, i, l, orig;
  sources = document.getElementsByTagName('source');

  for(i=0, l=sources.length; i&lt;l; i++) {
    orig = sources[i].getAttribute('src');
    sources[i].setAttribute('data-orig', orig);
    sources[i].setAttribute('src', orig.replace(/(w+).(w+)/, 'bumper-in.$2'));
  }

  videos = document.getElementsByTagName('video');

  for(i=0, l=videos.length; i&lt;l; i++) {
    videos[i].load();
    videos[i].addEventListener('ended', function(){
      sources = this.getElementsByTagName('source');
      for(i=0, l=sources.length; i&lt;l; i++) {
        orig = sources[i].getAttribute('data-orig');
        if (orig) {
          sources[i].setAttribute('src', orig);
        }
        sources[i].setAttribute('data-orig','');
      }
      this.load();
      this.play();
    });
  }
&lt;/script&gt;
</code></pre>
                <p>Again, <a href="https://media.24ways.org/2012/mclellan/examples/3.html">view the example</a> to see the bumper play, followed by our spectacular main feature. (That’s my cat, Widget. His interests include sleeping and internet marketing.)</p>
                <h2>Tidying things up</h2>
                <p>The final thing to do is add our closing bumper after the main video has played. This involves the following changes:</p>
                <ol>
                    <li>We need to keep track of whether the <code>src</code> has been changed, so we only play the video if it’s changed. I’ve added the <code>modified</code> variable to track this, and it stops us getting into a situation where the video just loops forever.</li>
                    <li>Add an <code>else</code> to the event listener, for when the <code>orig</code> is false (so the main feature has been playing) to load in the end bumper. We also check that we’re not already playing the end bumper. Because looping.</li>
                </ol>
                <pre><code class="language-html">&lt;script&gt;
  var videos, sources, i, l, orig, current, modified;
  sources = document.getElementsByTagName('source');

  for(i=0, l=sources.length; i&lt;l; i++) {
    orig = sources[i].getAttribute('src');
    sources[i].setAttribute('data-orig', orig);
    sources[i].setAttribute('src', orig.replace(/(w+).(w+)/, 'bumper-in.$2'));
  }

  videos = document.getElementsByTagName('video');

  for(i=0, l=videos.length; i&lt;l; i++) {
    videos[i].load();
    modified = false;

    videos[i].addEventListener('ended', function(){
      sources = this.getElementsByTagName('source');

      for(i=0, l=sources.length; i&lt;l; i++) {
        orig = sources[i].getAttribute('data-orig');
        if (orig) {
          sources[i].setAttribute('src', orig);
          modified = true;
        } else {
          current = sources[i].getAttribute('src');
          if (current.indexOf('bumper-out')==-1) {
            sources[i].setAttribute('src', current.replace(/([w]+).(w+)/, 'bumper-out.$2'));
            modified = true;
          } else {
            this.pause();
            modified = false;
          }
        }
        sources[i].setAttribute('data-orig','');
      }

      if (modified) {
        this.load();
        this.play();
      }
    });
  }
&lt;/script&gt;
</code></pre>
                <p>Yo ho ho, that’s a lot of JavaScript. <a href="https://media.24ways.org/2012/mclellan/examples/4.html">See it in action</a> – you should get a bumper, the cat video, and an end bumper.</p>
                <p>Of course, this code works fine for demonstrating the principle, but it’s very procedural. Nothing wrong with that, but to do something similar in production, you’d probably want to make the code more modular to ease maintainability. Besides, you may want to use a framework, rather than basic JavaScript.</p>
                <h2>The end credits</h2>
                <p>One really important principle here is that of <strong>progressive enhancement</strong>. If the browser doesn’t support JavaScript, the user won’t see your bumper, but they will get the main video. If the browser supports JavaScript but doesn’t allow you to modify the <code>src</code> (as was the case with older versions of iOS), the user won’t see your bumper, but they will get the main video.</p>
                <p>At Twitter, <em>every commit</em> gets a code review. We do a lot of reviewing, so small efficiency and effectiveness improvements make a big difference. Over time we’ve learnt a few things:</p>
                <ul>
                    <li>Don’t review for <em>more than hour</em><sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup></li>
                    <li>Keep reviews <em>smaller than ~400 lines</em><sup class="footnote-ref"><a href="#fn2" id="fnref2">[2]</a></sup></li>
                </ul>
                <p>If a search engine or social media bot grabs your page and looks for content, they won’t see your bumper, but they will get the main video – which is absolutely what you want.</p>
                <p>This means that if the bumper is absolutely crucial, you may still need to cook it into the video. However, for many applications, running it dynamically can work quite well.</p>
                <p>As always, it comes down to three things:</p>
                <ol>
                    <li>Measure your audience: know how people access your site</li>
                    <li>Test the solution: make sure it works for your audience</li>
                    <li>Plan for failure: it’s the web and that’s how things work 'round these parts</li>
                </ol>
                <p>But most of all <strong>play around with it, have fun and build something awesome</strong>.</p>
                <hr class="footnotes-sep" />
                <section class="footnotes">
                    <ol class="footnotes-list">
                        <li id="fn1" class="footnote-item">
                            <p>Dunsmore et al. 2000. Object-Oriented Inspection in the Face of Delocalisation. Beverly, MA: SmartBear Software. <a href="#fnref1" class="footnote-backref">↩︎</a></p>
                        </li>
                        <li id="fn2" class="footnote-item">
                            <p>Cohen, Jason. 2006. Best Kept Secrets of Peer Code Review. <em>Proceedings of the 22nd ICSE 2000</em>: 467-476. <a href="#fnref2" class="footnote-backref">↩︎</a></p>
                        </li>
                    </ol>
                </section>

            </div>

        </div>

        <section class="c-section" id="author">
            <header class="c-section__header">
                <h2 class="c-section__title">About the author</h2>
            </header>
            <div class="c-section__main">
                <div class="s-prose">
                    <p>Drew McLellan is lead developer on your favourite content management systems, <a href="https://grabaperch.com/">Perch and Perch Runway</a>. He is Director and Senior Developer at edgeofmyseat.com in Bristol, England, and is formerly Group Lead at the Web Standards Project. When not publishing 24 ways, Drew keeps a <a href="http://allinthehead.com/">personal site</a> covering web development issues and themes, <a href="https://flickr.com/drewm/">takes photos</a>, <a href="https://twitter.com/drewm">tweets a lot</a> and tries to stay upright on his bicycle.</p>
                    <p><span class="caption">Photo: <a href="http://duncandavidson.com/">James Duncan Davidson</a></span></p>
                    <p><a class="c-continue" href="/authors/drewmclellan/">More articles by Drew</a></p>

                </div>
            </div>
        </section>

        <section class="c-section c-section--sponsor" id="sponsor">
            <header class="c-section__header">
                <h2 class="c-section__title">Brought to you by</h2>
            </header>
            <div class="c-section__main"><a class="c-promo" href="https://grabaperch.com/?ref=24w01">
                    <img class="c-promo__image" src="/assets/images/logo-perch.png" alt="Perch - A really little CMS" width="152" height="64" />
                    <p class="c-promo__message">The easiest way to publish <strong>fast, flexible HTML5 websites</strong> your clients will love.</p>
                    <p class="c-promo__url">grabaperch.com</p>
                </a>
            </div>
        </section>

        <section class="c-section c-section--related" id="related">
            <header class="c-section__header">
                <h2 class="c-section__title">Related articles</h2>
            </header>
            <div class="c-section__main">
                <ol class="c-listing c-listing--summaries">
                    <li>
                        <article class="c-summary h-entry day-15">
                            <header class="c-summary__header">
                                <h3 class="c-summary__title  p-name"><a class="u-url" rel="bookmark" href="/2015/grid-flexbox-box-alignment-our-new-system-for-layout/">Grid, Flexbox, Box Alignment: Our New System for Layout</a></h3>
                                <p class="c-summary__author  p-author h-card">
                                    <a class="c-summary__author-url  u-url" href="/authors/rachelandrew/">
                                        <img class="u-photo" src="https://cloud.24ways.org/authors/rachelandrew160.jpg" width="72" height="72" alt="" />
                                        <span class="p-name">Rachel Andrew</span>
                                    </a>
                                </p>
                            </header>
                            <div class="c-summary__main">
                                <p class="p-summary"><a href="https://rachelandrew.co.uk/">Rachel Andrew</a> unwraps the new paradigms of web layout, comparing their features and showing how they can free us from grid-based, <code>div</code>-infested frameworks. Beautifully wrapped boxes look lovely under the Christmas tree, but we need to think and break out of them.
                                </p>
                            </div>
                            <footer class="c-summary__footer">
                                <p class="c-summary__meta">
                                    <time class="dt-published" datetime="2010-12-15T00:00:00-00:00">
                                        15 <span>December 2010</span>
                                    </time>
                                </p>
                            </footer>
                        </article>
                    </li>
                    <li>
                        <article class="c-summary h-entry day-15">
                            <header class="c-summary__header">
                                <h3 class="c-summary__title  p-name"><a class="u-url" rel="bookmark" href="/2015/grid-flexbox-box-alignment-our-new-system-for-layout/">Grid, Flexbox, Box Alignment: Our New System for Layout</a></h3>
                                <p class="c-summary__author  p-author h-card">
                                    <a class="c-summary__author-url  u-url" href="/authors/rachelandrew/">
                                        <img class="u-photo" src="https://cloud.24ways.org/authors/rachelandrew160.jpg" width="72" height="72" alt="" />
                                        <span class="p-name">Rachel Andrew</span>
                                    </a>
                                </p>
                            </header>
                            <div class="c-summary__main">
                                <p class="p-summary"><a href="https://rachelandrew.co.uk/">Rachel Andrew</a> unwraps the new paradigms of web layout, comparing their features and showing how they can free us from grid-based, <code>div</code>-infested frameworks. Beautifully wrapped boxes look lovely under the Christmas tree, but we need to think and break out of them.
                                </p>
                            </div>
                            <footer class="c-summary__footer">
                                <p class="c-summary__meta">
                                    <time class="dt-published" datetime="2010-12-15T00:00:00-00:00">
                                        15 <span>December 2010</span>
                                    </time>
                                </p>
                            </footer>
                        </article>
                    </li>
                    <li>
                        <article class="c-summary h-entry day-15">
                            <header class="c-summary__header">
                                <h3 class="c-summary__title  p-name"><a class="u-url" rel="bookmark" href="/2015/grid-flexbox-box-alignment-our-new-system-for-layout/">Grid, Flexbox, Box Alignment: Our New System for Layout</a></h3>
                                <p class="c-summary__author  p-author h-card">
                                    <a class="c-summary__author-url  u-url" href="/authors/rachelandrew/">
                                        <img class="u-photo" src="https://cloud.24ways.org/authors/rachelandrew160.jpg" width="72" height="72" alt="" />
                                        <span class="p-name">Rachel Andrew</span>
                                    </a>
                                </p>
                            </header>
                            <div class="c-summary__main">
                                <p class="p-summary"><a href="https://rachelandrew.co.uk/">Rachel Andrew</a> unwraps the new paradigms of web layout, comparing their features and showing how they can free us from grid-based, <code>div</code>-infested frameworks. Beautifully wrapped boxes look lovely under the Christmas tree, but we need to think and break out of them.
                                </p>
                            </div>
                            <footer class="c-summary__footer">
                                <p class="c-summary__meta">
                                    <time class="dt-published" datetime="2010-12-15T00:00:00-00:00">
                                        15 <span>December 2010</span>
                                    </time>
                                </p>
                            </footer>
                        </article>
                    </li>
                    <li>
                        <article class="c-summary h-entry day-15">
                            <header class="c-summary__header">
                                <h3 class="c-summary__title  p-name"><a class="u-url" rel="bookmark" href="/2015/grid-flexbox-box-alignment-our-new-system-for-layout/">Grid, Flexbox, Box Alignment: Our New System for Layout</a></h3>
                                <p class="c-summary__author  p-author h-card">
                                    <a class="c-summary__author-url  u-url" href="/authors/rachelandrew/">
                                        <img class="u-photo" src="https://cloud.24ways.org/authors/rachelandrew160.jpg" width="72" height="72" alt="" />
                                        <span class="p-name">Rachel Andrew</span>
                                    </a>
                                </p>
                            </header>
                            <div class="c-summary__main">
                                <p class="p-summary"><a href="https://rachelandrew.co.uk/">Rachel Andrew</a> unwraps the new paradigms of web layout, comparing their features and showing how they can free us from grid-based, <code>div</code>-infested frameworks. Beautifully wrapped boxes look lovely under the Christmas tree, but we need to think and break out of them.
                                </p>
                            </div>
                            <footer class="c-summary__footer">
                                <p class="c-summary__meta">
                                    <time class="dt-published" datetime="2010-12-15T00:00:00-00:00">
                                        15 <span>December 2010</span>
                                    </time>
                                </p>
                            </footer>
                        </article>
                    </li>
                </ol>
            </div>
        </section>

        <section class="c-section" id="comments">
            <header class="c-section__header">
                <h2 class="c-section__title">2 Comments</h2>
            </header>
            <div class="c-section__main">
                <div class="s-prose">
                    <p>Comments are ordered by helpfulness, as indicated by you. Help us pick out the gems and discourage asshattery by voting on notable comments.</p>
                    <p><a class="c-continue" href="#comment-form">Got something to add? Leave a comment below</a></p>

                </div>
                <article class="c-comment h-entry" id="c0001">
                    <header class="c-comment__header">
                        <h3 class="c-comment__title  p-name h-card">
                            <a class="p-author u-url" href="https://adactio.com/">
                                <img class="c-avatar  u-photo" src="https://www.gravatar.com/avatar/5ad82c5ba0264363974af89deb743c20?s=96" width="64" height="64" alt="" />

                                Jeremy Keith
                            </a>
                        </h3>
                        <p class="c-comment__meta">
                            <a class="c-comment__permalink" rel="bookmark" href="#c0001" title="Permalink to this comment"><time class="dt-published" datetime="2012-12-01T12:24:48-00:00">1 December 2012</time></a>
                        </p>
                    </header>
                    <div class="c-comment__main s-prose  e-content">
                        <p>This is great stuff! I’m terrible at regular expressions—my brain just doesn’t seem to want to remember any of it—but this article contains the clearest description of regular expressions I’ve come across.</p>
                        <p>I thought I’d share a useful little rewrite rule that I use for cache-busting JavaScript and CSS files. You know the story: you make a change in your JavaScript or CSS and you want to let the browser know that it should grab the new version instead of using what it’s got in its cache.</p>
                        <p>Now, I could potentially just use a query string when I point to my JS and CSS files ( e.g. /js/myscript.js?20131201 ) …but that can cause issues with proxy servers.</p>
                        <p>Instead what I what I do is point to files like this: <code>/js/myscript.20131201.js</code></p>
                        <p>Then I need to tell the server to look for the <strong>actual</strong> file in <code>/js/myscript.js</code></p>
                        <p>Here’s the rewrite rule I’m using:</p>
                        <pre><code>RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.).(d).(js|css)$ $1.$3 [L]
</code></pre>
                        <p>It’s basically telling the server that, if the JS or CSS file doesn’t actually exist and it matches the pattern of having two dots before the file extension (with only numbers after the first dot), to look at the bit before the first dot, and look at the bit after the second dot, but to ignore the bit in between (the numbers).</p>
                        <p>The server serves up the right file, but browsers fetch the new version because, as far as they’re concerned, this looks like a brand new file that they haven’t got in their cache.</p>
                        <p>That was a terrible explanation, wasn’t it? I now have even more appreciation for how clearly and concise this article is.</p>

                    </div>
                    <footer class="c-comment__footer">
                        <p>This comment was <a href="/vote/up/c0001/">helpful</a> / <a href="/vote/down/c0001/">unhelpful</a></p>
                    </footer>
                </article>
                <article class="c-comment c-comment--unhelpful h-entry" id="c0002">
                    <header class="c-comment__header">
                        <h3 class="c-comment__title  p-name h-card">
                            <a class="p-author u-url" href="https://paulrobertlloyd.com/">
                                <img class="c-avatar  u-photo" src="https://www.gravatar.com/avatar/15091a37bacfa4bdd011282627eaca2b?s=96" width="64" height="64" alt="" />

                                Paul Robert Lloyd
                            </a>
                        </h3>
                        <p class="c-comment__meta">
                            <a class="c-comment__permalink" rel="bookmark" href="#c0002" title="Permalink to this comment"><time class="dt-published" datetime="2012-12-12T12:24:48-00:00">12 December 2012</time></a>
                        </p>
                    </header>
                    <div class="c-comment__main s-prose  e-content">
                        <p>You fool! Everything you’ve written here is wrong!</p>

                    </div>
                    <footer class="c-comment__footer">
                        <p>This comment was <a href="/vote/up/c0002/">helpful</a> / <a href="/vote/down/c0002/">unhelpful</a></p>
                    </footer>
                </article>
            </div>
        </section>

        <form id="comment-form" method="post">
            <fieldset>
                <div class="c-section">
                    <legend class="c-section__header">
                        <span class="c-section__title">Impress us</span>
                    </legend>
                    <div class="c-section__main">
                        <div class="s-prose">
                            <p id="commentHTMLNote">Be friendly / use <a href="http://www.textism.com/tools/textile/">Textile</a></p>
                        </div>
                        <p class="c-field">
                            <label class="c-field__label" for="commentName">Name</label>
                            <input class="c-field__input" id="commentName" name="commentName" type="text" autocorrect="off" required="required" />
                        </p>
                        <p class="c-field">
                            <label class="c-field__label" for="commentEmail">Email</label>
                            <input class="c-field__input" id="commentEmail" name="commentEmail" type="email" autocorrect="off" required="required" />
                        </p>
                        <p class="c-field">
                            <label class="c-field__label" for="commentURL">Website</label>
                            <input class="c-field__input" id="commentURL" name="commentURL" type="url" autocorrect="off" placeholder="http://" />
                        </p>
                        <p class="c-field">
                            <label class="c-field__label" for="commentHTML">Message</label>
                            <textarea class="c-field__input" id="commentHTML" name="commentHTML" cols="25" rows="12" required="required" aria-describedby="commentHTMLNote"></textarea>
                        </p>
                        <p class="c-field">
                            <input type="hidden" name="parentID" id="parentID" value="289" />
                            <input type="hidden" name="parentTitle" id="parentTitle" value="HTML5 Video Bumpers" />
                            <input class="c-button" type="submit" name="submitComment" id="submitComment" value="Submit" />
                        </p>
                    </div>
                </div>
            </fieldset>
        </form>

    </article>

</main>

<nav class="c-traverse-nav" aria-label="Article"><a class="c-traverse-nav__item" rel="prev" href="/2015/how-tabs-should-work/" aria-label="Previous: How Tabs Should Work">
        <svg class="c-traverse-nav__icon" width="20" height="20" viewBox="0 0 200 200" focusable="false" aria-hidden="true">
            <path d="M50 100l85 85 7-7-78-78 78-78-7-7" />
        </svg>

    </a><a class="c-traverse-nav__item" rel="next" href="/2015/solve-the-hard-problems/" aria-label="Next: Solve the Hard Problems">
        <svg class="c-traverse-nav__icon" width="20" height="20" viewBox="0 0 200 200" focusable="false" aria-hidden="true">
            <path d="M150 100l-85 85-7-7 78-78-78-78 7-7" />
        </svg>

    </a></nav>

<footer class="c-contentinfo">
    <p class="c-contentinfo__social">
        <a href="https://feeds.feedburner.com/24ways" rel="alternate">Grab our RSS feed</a>
        <a href="https://twitter.com/24ways" rel="me">Follow us on Twitter</a>
        <a href="https://github.com/24ways" rel="me">Contribute on GitHub</a>
    </p>
    <p class="c-contentinfo__copyright">
        <small>&#169; 2005-2016 24 ways and our authors</small>
    </p>
</footer>
{% extends "@page" %}
{% block main %}
  {% include "@article" %}
{% endblock %}
{
  "site": {
    "title": "24 ways",
    "handle": "24ways",
    "description": "24 ways is the advent calendar for web geeks. Each day throughout December we publish a daily dose of web design and development goodness to bring you all a little Christmas cheer.",
    "url": "https://24ways.org",
    "feed": "https://feeds.feedburner.com/24ways",
    "theme_color": "#f04"
  },
  "theme": "year-2013",
  "prism": true,
  "title": "Starting Your HTML5 Project on the Right Foot (and Keeping It There)",
  "description": "Drew McLellan brings our 2015 calendar to a motivational close with some encouragement for the year ahead. Year’s end is a time for reflection and finding new purpose and enthusiasm for what we do. By tackling the thorniest design and development problems, we can make the greatest impact – and have the most fun. Merry Christmas and a happy New Year!",
  "url": "https://24ways.org/2015/starting-on-the-right-foot/",
  "author": "Drew McLellan",
  "handle": "drewm",
  "avatar": {
    "size": 160,
    "src": "https://cloud.24ways.org/authors/drewmclellan280.jpg"
  },
  "section": "article",
  "traverse": {
    "type": "article",
    "prev": {
      "url": "/2015/how-tabs-should-work/",
      "title": "How Tabs Should Work"
    },
    "next": {
      "url": "/2015/solve-the-hard-problems/",
      "title": "Solve the Hard Problems"
    }
  },
  "related": true,
  "comments": [
    {
      "site": {
        "title": "24 ways",
        "handle": "24ways",
        "description": "24 ways is the advent calendar for web geeks. Each day throughout December we publish a daily dose of web design and development goodness to bring you all a little Christmas cheer.",
        "url": "https://24ways.org",
        "feed": "https://feeds.feedburner.com/24ways",
        "theme_color": "#f04"
      },
      "theme": {
        "year": [
          348,
          344,
          340,
          336,
          332,
          328,
          324,
          320,
          316,
          312,
          308,
          304,
          300,
          296,
          292,
          288
        ],
        "day": [
          360,
          353,
          346,
          339,
          332,
          325,
          318,
          311,
          304,
          297,
          290,
          283,
          276,
          269,
          262,
          255,
          248,
          241,
          234,
          227,
          220,
          213,
          206,
          199
        ]
      },
      "id": "c0001",
      "href": "https://adactio.com/",
      "author": "Jeremy Keith",
      "datetime": "2012-12-01T12:24:48-00:00",
      "avatar": {
        "src": "https://www.gravatar.com/avatar/5ad82c5ba0264363974af89deb743c20?s=96",
        "size": 64
      },
      "content": "This is great stuff! I'm terrible at regular expressions—my brain just doesn't seem to want to remember any of it—but this article contains the clearest description of regular expressions I've come across.\n\nI thought I'd share a useful little rewrite rule that I use for cache-busting JavaScript and CSS files. You know the story: you make a change in your JavaScript or CSS and you want to let the browser know that it should grab the new version instead of using what it's got in its cache.\n\nNow, I could potentially just use a query string when I point to my JS and CSS files ( e.g. /js/myscript.js?20131201 ) …but that can cause issues with proxy servers.\n\nInstead what I what I do is point to files like this: `/js/myscript.20131201.js`\n\nThen I need to tell the server to look for the **actual** file in `/js/myscript.js`\n\nHere's the rewrite rule I'm using:\n\n```\nRewriteCond %{REQUEST_FILENAME} !-f\nRewriteRule ^(.).(d).(js|css)$ $1.$3 [L]\n```\n\nIt's basically telling the server that, if the JS or CSS file doesn't actually exist and it matches the pattern of having two dots before the file extension (with only numbers after the first dot), to look at the bit before the first dot, and look at the bit after the second dot, but to ignore the bit in between (the numbers).\n\nThe server serves up the right file, but browsers fetch the new version because, as far as they're concerned, this looks like a brand new file that they haven't got in their cache.\n\nThat was a terrible explanation, wasn't it? I now have even more appreciation for how clearly and concise this article is.\n"
    },
    {
      "site": {
        "title": "24 ways",
        "handle": "24ways",
        "description": "24 ways is the advent calendar for web geeks. Each day throughout December we publish a daily dose of web design and development goodness to bring you all a little Christmas cheer.",
        "url": "https://24ways.org",
        "feed": "https://feeds.feedburner.com/24ways",
        "theme_color": "#f04"
      },
      "theme": {
        "year": [
          348,
          344,
          340,
          336,
          332,
          328,
          324,
          320,
          316,
          312,
          308,
          304,
          300,
          296,
          292,
          288
        ],
        "day": [
          360,
          353,
          346,
          339,
          332,
          325,
          318,
          311,
          304,
          297,
          290,
          283,
          276,
          269,
          262,
          255,
          248,
          241,
          234,
          227,
          220,
          213,
          206,
          199
        ]
      },
      "id": "c0002",
      "href": "https://paulrobertlloyd.com/",
      "author": "Paul Robert Lloyd",
      "datetime": "2012-12-12T12:24:48-00:00",
      "mods": [
        "unhelpful"
      ],
      "avatar": {
        "src": "https://www.gravatar.com/avatar/15091a37bacfa4bdd011282627eaca2b?s=96",
        "size": 64
      },
      "content": "You fool! Everything you've written here is wrong!\n"
    }
  ]
}

There are no notes for this item.