<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="content-type"
content="text/html;charset=iso-8859-1">
<meta name="generator" content="Adobe GoLive">
<title>Untitled Page</title>
</head>
<body bgcolor="#ffffff">
<h1>Time Ranges</h1>
<h2>Discussion</h2>
<p>In the current HTML5 draft cue ranges are
available using a DOM API.</p>
<p>This way of doing ranges is less than ideal. </p>
<p>First of all, it is hard to use. The ranges must
be added by script, can't be supplied with the media, and the
callbacks are awkward to handle. The only way to identify the range a
received callback applies to is by creating not one but two separate
functions for each range: one for enter, one for exit. While creating
functions on-demand is easy in JavaScript it does fall under advanced
techniques that most authors will be unfamiliar with. This
kind of feature is also not available in all languages that might
provide access to the DOM API.</p>
<p>Secondly this mechanism is not very powerful. You
can't do anything else with the ranges besides receiving callbacks
and removing them. You can't modify them. They are not visible
to scripts or CSS. You can't link to them. You can't link out from
them. </p>
<p>Thirdly, a script is somewhat strange place to
define the ranges. A set of ranges usually relates closely to some
particular piece of media content. The same set of ranges rarely
makes much sense in the context of some other content. It seems that
ranges should be defined or supplied along with the media content.</p>
<p>Fourth, this kind of callback API is pretty
strange creature in the HTML specification. The only other callback
APIs are things like setTimeout() and the new SQL API which don't
have associated elements. Events are the callback mechanism for
everything else.</p>
<p>In SMIL the equivalent concept is the <area>
element which is used like this: </p>
<p><video
src="http://www.example.org/CoolStuff"><br>
<area id="area1" begin="0s"
end="5s"/><br>
<area id="area2" begin="5s"
end="10s"/><br>
</video></p>
<p>This kind of approach has several advantages. </p>
<ul>
<li type="disc">Ranges are defined as part of
the document, in the context of a particular media stream.
<li type="disc">This uses events, a more
flexible and more appropriate callback mechanism.<li type="disc">The
callbacks have a JavaScript object associated with them, namely a DOM
element, which carries information about the range.
</ul>
<p>The main disadvantage is the relative difficulty
of creating ranges from JavaScript since it requires creating
elements and giving them attributes. Some sort of shortcut interface
could be provided, of course, perhaps similar to the existing API.</p>
<p>The SMIL definition is perhaps a little broad and
also the name is not ideal, if the element is primarily used for
generating events vs. linking.</p>
<p>We would like to suggest a <timerange>
element that can be used as a child of the <video> and
<audio> elements. </p>
<h2>The timerange element</h2>
<p><a href="#media7" title="media element">Media
elements</a> may have <dfn id="cue-ranges0" title="cue
range">timeranges as child elements</dfn>. A timerange represents an
interval for which events will fire when the current playback time
enters or leaves the interval.</p><p><strong>Contexts</strong> in
which this element may be used:</p>
<blockquote>
<p>As a child of a media element, after
all source elements, and before any other content.</p>
</blockquote>
<p><strong>Content model</strong>:</p>
<blockquote>
<p>Empty.</p>
</blockquote>
<p>Element-specific <strong>attributes</strong>:</p>
<ul>
<blockquote>
<li type="disc">start
<li type="disc">end
<li type="disc">pauseonexit
<li type="disc">ontimeenter
<li type="disc">ontimeexit
</blockquote>
</ul>
<p><strong>DOM interface</strong>:</p>
<blockquote>
<p>interface HTMLTimetimeElement :
HTMLElement {<br>
attribute float
start; <br> attribute
float
end;<br> attribute
boolean pauseOnExit;<br>
readonly attribute
boolean active;<br>
};</p>
</blockquote>
<p>The start and end attributes of each timerange are
'clipped' to the effective start and effective end of the media
resource. If the value of the end attribute is less than the value
of the start attribute, it is automatically set to be equal to the
start attribute. </p>
<p>If start is not supplied, its default value is
negative infinity, which means it gets assigned the effective start
of the media resource.</p>
<p>If end is not supplied, its default value is
positive infinity, which means it gets assigned the effective end of
the media resource.</p>
<p>The timerange elements may be in any order (they
might not be sorted) and may overlap.</p>
<p>The "active" attribute of a time range
is true when the currentTime of associated media element is greater
to or equal to start and less than end. Otherwise it is false. Before
any events fire, the active value of all timeranges is false, and it
is also false when the current placyback position is at the effective
end of the media resource.</p>
<p>The ontimeenter and ontimeexit attributes are a
convenient way to supply a handler for the corresponding events.</p>
<h2>Behavior</h2>
<p>When the active attribute of a timerange changes
value from false to true a simple event "timeEnter" is
fired. When the active attribute changes value from true to false a
simple event "timeExit" is fired. (These two names are
deliberately similar to the spatial mouse events, but there is no
timeMoved as it would fire continuously).</p>
<p>If the same time value represents the end of one
timerange and the start of another, then the timeExit event will fire
before the timeEnter event. The "active" attribute of all
ranges is set <em>before</em> all events are dispatched, for any time
instant (so interrogating the DOM tree reveals the state that
corresponds to the current playback position).</p>
<p>When the <a href="#current0">current playback
position</a> of a <a href="#media7">media element</a> changes (e.g.
due to playback or
seeking), the user agent must run the following steps. If the <a
href="#current0">current playback position</a> changes while the
steps are running, then the user agent must wait for the steps to
complete, and then must immediately rerun the steps. These steps must
also be run when a timerange element is added as a child of the media
element, after all scripts have finished executing. If a timerange
is removed as a child of the media element while it is active, the
timerange is set inactive, its timeExit event is fired, and then it
is removed.</p>
<p>(These steps are thus run as often as possible or
needed if one iteration takes a long time, this can cause
certain ranges to be skipped over as the user agent rushes ahead to
"catch up". Effectively time is "sampled" as
often as both possible and necessary. This means that events for
timeranges in which start equals end might never fire, but such
timeranges are legal and user agents should attempt to fire their
events.)</p>
<ol>
<li>Let <var title="">current ranges</var> be
an unordered list of <a href="#cue-ranges0" title="cue
range">timeranges</a>, initialised to contain all the <a
href="#cue-ranges0" title="cue range">timeranges</a> of the <a
href="#media7">media element</a> whose start times are less than or
equal to the <a href="#current0">current playback position</a> and
whose end times are greater than the <a href="#current0">current
playback position</a>.
<li type="1">Let <var title="">other
ranges</var> be an unordered list of <a href="#cue-ranges0"
title="cue range">timeranges</a>, initialised to contain all the <a
href="#cue-ranges0" title="cue range">timeranges</a> of the <a
href="#media7">media element</a> that are not present in <var
title="">current ranges</var>.
<li type="1">Divide the ranges into four sets:
<ol>
<li type="1">the <em>passive
set</em>: <var title="">other ranges</var> which have their
"active" boolean set to "false" (inactive).<li
type="1">the <em>active set</em>: <var title="">current ranges</var>
which have their "active" boolean set to "true"
(active).<li type="1">the <em>entry set</em>: <var title="">current
ranges</var> which have their "active" boolean set to
"false" (inactive).<li type="1">the <em>exit set</em>: <var
title="">other ranges</var> which have their "active"
boolean set to "true" (active).</ol>
<li type="1">Set the "active"
boolean of all the <a href="#cue-ranges0" title="cue
range">timeranges</a> in the <var title="">entry set</var> to
"true" (active), and the "active" boolean of all
the <a href="#cue-ranges0" title="cue range">timeranges</a> in the
<var title="">exit set</var> to "false" (inactive).
<li type="1">If the <em>entry set</em> and
<em>exit set</em> are both empty, then abort these steps.
<li type="1">If the time was reached through
the usual monotonic increase of the current playback position during
normal playback, the user agent must then <a href="#firing2">fire a
simple event</a> called <code title=event-timeupdate><a
href="#timeupdate">timeupdate</a></code> at the media element. (In
the other cases, such as explicit seeks, relevant events get fired as
part of the overall process of changing the current playback
position.)
<li type="1">If the time was reached through
the usual monotonic increase of the current playback position during
normal playback, and there are <a href="#cue-ranges0" title="cue
range">timeranges</a> in the <em>exit set</em> that have their
"pauseonexit" boolean set to "true", then
immediately act as if the element's <code title="dom-media-pause"><a
href="#pause0">pause()</a></code> method had been invoked. (In the
other cases, such as explicit seeks, playback is not paused by
exiting a timerange, even if that timerange has its
"pauseonexit" boolean set to "true".)
<li type="1">Fire all the
"timeExit" events for all of the <a href="#cue-ranges0"
title="cue range">timeranges</a> in the <em>exit set</em>, in any
order.
<li type="1">Fire all the
"timeEnter" events for all of the <a href="#cue-ranges0"
title="cue range">timeranges</a> in the <em>entry set</em>, in any
order.
</ol>
<p>(Note that immediately before playback starts, and
when the current playback position reaches the end of the media,
there are no active timeranges.)</p>
<p><strong>Constructor</strong>:</p>
<blockquote>
<p>TimeRange(in float start, in float end); <br>
TimeRange(in float start, in float
end, in boolean pauseOnExit); </p>
</blockquote>
<h2>Example</h2>
<p><video
src="http://www.example.org/CoolStuff"><br>
<timerange id=r1
end=10s></timerange><br>
<timerange id=r2
end=20s></timerange><br>
<timerange id=r3 start=30s ></timerange><br>
</video></p>
<p>video.addEventListener("timeEnter",
function (event) {<br>
switch (event.target.id) {<br>
case r1: <br>
//
do stuff<br>
case r2: <br>
//
do more stuff<br>
}<br>
}, true);</p>
<h1>Notes and Future Work</h1>
<p>Note that there is an existing concept called
timeranges in the HTML5 specification; a new name needs to be found
for one or the other. </p>
<p>The event listeners should probably be added to
HTMLElement where other listener attributes are. (You should be able
to capture events everywhere, not just on target.)</p>
<p>It's possible that the identifiers of the
time-ranges could be used as 'anchor points' within the media, so
that activating them as a URL would cause the user agent to seek to
the beginning of that range. This is related to the <a
href="http://www.w3.org/2008/01/media-fragments-wg.html">Media
Fragments</a> working group.</p>
<p>Similarly, it's possible that href URLs could be
added to timeranges, such that if the user clicked on the media
during the range, the href URL would be dispatched. (This could also
be integrated with a usemap). </p>
<p>Both of these have scoping and other implications
and we think can be left to further study.</p>
<p>The existing API for adding a timerange to the DOM
could be retained as a convenient shortcut, but we don't think it is
needed.</p>
<p>There could be a timemoved event fired at
timeranges that want it, but there would need to be some sort of
movement granularity attribute, or other control, or else it would
effectively have to be run at every change of value of the current
placyback position, up to and including saturating the CPU.</p>
</body>
</html>