timesheets.js

A declarative approach for HTML Timing using SMIL Timesheets

SMIL Timing can also be seen as a simple but highly extensible slideshow engine:

Slideshows With SMIL Timing

A <seq> time container is a good basis for a slideshow engine:

  • each slide is a child of this main <seq> time container
  • the first|prev|next|last attributes provide a navigation menu "out of the box"
  • setting an ID attribute to each slide allows to use hyperlinks to get a direct access
<html>
  <head> […] </head>
  <body smil:timeContainer="seq"
        smil:first = "first.click"
        smil:prev  = "prev.click"
        smil:next  = "next.click"
        smil:last  = "last.click">

    <div id="slide1"> […] </div>
    <div id="slide2"> […] </div>
    <div id="slide3"> […] </div>
    <div id="slide4"> […] </div>
    […]
    <div id="slideN"> […] </div>

    <p smil:timeAction="none"> 
      <button id="first">    «     </button>
      <button id="prev"> &lt; prev </button>
      <button id="next"> next &gt; </button>
      <button id="last">     »     </button>
    </p>
  </body>
</html>

Progressive Display with <par>

  • On this slide
  • the list items
  • appear one after another
  • at 2s intervals.

The next slide will appear in 10s or if you click on the "Next" button below — whatever comes first.


<div id="slide03" smil:timeContainer="par" smil:dur="20s"> <h2> Progressive Display with &lt;par&gt; </h2> <ul smil:timeContainer="par"> <li smil:begin="0:02"> On this slide </li> <li smil:begin="0:04"> the list items </li> <li smil:begin="0:06"> appear one after another </li> <li smil:begin="0:08"> at 2s intervals. </li> </ul> <p smil:begin="0:10"> The next slide will appear in 10s or if you click on the "Next" button below — whatever comes first. </p> </div>

Incremental Display with <seq>

  • Click on this slide
  • and the list items
  • will appear
  • one after another.

(you still have to click the "next" button to get the next slide)


<div id="slide05" smil:timeContainer="par"> <h2> Incremental Display with &lt;seq&gt; </h2> <ul smil:timeContainer="seq" smil:next="slide05.click"> <li smil:fill="hold"> Click on this slide </li> <li smil:fill="hold"> and the list items </li> <li smil:fill="hold"> will appear </li> <li smil:fill="hold"> one after another. </li> </ul> <p smil:begin="0:10"> (you still have to click the "next" button to get the next slide) </p> </div>

Outlines with event-values

  • hover me
    • this item is collapsed by default
    • this item is expanded when active
  • click me
    • this item is collapsed by default
    • this item is expanded when active
  • click me
    • this item is expanded by default
    • this item is collapsed when active
<div id="slide07" smil:timeContainer="par"> 
  <h2> Outlines with event-values </h2>

  <ul smil:timeContainer="par" smil:timeAction="class:active"
      class="outline">
    <li smil:begin="mouseover" smil:begin="mouseout"> hover me
      <ul>
        <li> this item is collapsed by default </li>
        <li> this item is expanded when active </li>
      </ul>
    </li>
    <li smil:begin="click" smil:end="click"> click me
      <ul> […] </ul>
    </li>
    <li smil:begin="click" smil:end="click"> click me
      <ul class="expand">
        <li> this item is expanded by default   </li>
        <li> this item is collapsed when active </li>
      </ul>
    </li>
  </ul>

</div>


/* outline -- collapsed by default */ #slideshow .outline li ul { display: none; } #slideshow .outline li.active ul { display: block; }
/* outline -- expanded by default */ #slideshow .outline li ul.expand { display: block; } #slideshow .outline li.active ul.expand { display: none; }

And More!

  • define your own transitions with CSS3
  • define user interactions with event-values
  • include audio|video clips in any slide
  • sync your slides with an audio or video track

A slideshow alone doesn’t bring much information, but it can get much more useful when the speaker’s voice is sync’ed!

CSS transition: | | | | |

View this demo in full page.

HTML Markup

The markup is described in the slideshow itself. Nothing really new here (except for the <par> containers, which are described in the timeContainer page): the main trick is to nest several time containers to be able to animate the content of a few slides.

Anchors

The SMIL Timing spec includes a notice about hyperlink implication on SEQ and EXCL time containers. This allows us to use anchors to activate a particular time node in a <seq|excl> container:

  1. Slideshows with SMIL Timing
  2. markup
  3. Progressive Display With <par>
  4. markup
  5. Incremental Display With <seq>
  6. markup
  7. Outlines with event-values
  8. markup
  9. style
  10. And More!

This can be used as well on a full URL and/or with continuous media (audio/video), e.g. for our “Audio Annotations” example:

Section #1 | Section #2 | Section #3 | Section #4 | Section #5 | Section #6

Our timesheet scheduler relies on the hashchange event to activate the requested time node. Again, no particular JavaScript code is applied to these links above (no onclick or whatsoever).

Keyboard Navigation

The SMIL Timing spec does not mention any mechanism to listen to keyboard events. However, it's easy to trigger click events on the prev/next buttons when a specific key is pressed -- in this case, [k/j] for prev/next:

window.addEventListener("DOMContentLoaded", function() {
  var prevKeyCode = 37; // left arrow key
  var nextKeyCode = 39; // right arrow key
  var prevButton = document.getElementById("prev");
  var nextButton = document.getElementById("next");

  var clickEvent = document.createEvent("Event");
  clickEvent.initEvent("click", true, false);

  document.addEventListener("keydown", function(e) {
    switch(e.keyCode) {
      case prevKeyCode:
        prevButton.dispatchEvent(clickEvent);
        break;
      case nextKeyCode:
        nextButton.dispatchEvent(clickEvent);
        break;
    }
  }, true);
}, true);

This JavaScript code will work on all modern browsers, i.e. all browsers supporting addEventListener() and dispatchEvent(), i.e. all browsers except IE6, IE7, IE8. To ensure the compatibility with these (obsolete) browsers, our timesheet scheduler features a window.EVENTS object that can be used as an event management abstraction layer:

EVENTS.onDOMReady(function() {
  var prevKeyCode = 37; // left arrow key
  var nextKeyCode = 39; // right arrow key
  var prevButton = document.getElementById("prev");
  var nextButton = document.getElementById("next");

  EVENTS.bind(document, "keydown", function(e) {
    switch(e.keyCode) {
      case prevKeyCode:
        EVENTS.trigger(prevButton, "click");
        break;
      case nextKeyCode:
        EVENTS.trigger(nextButton, "click");
        break;
    }
  });
});

These two scripts are perfectly equivalent on modern browsers. The first one would raise an error on IE<9, the second one works on all browsers.

Of course, there is a lot of JavaScript frameworks that provide such an abstraction layer. The point in using this built-in one is that it also supports the SMIL-specific onbegin/onend events.