Skip to content

Instantly share code, notes, and snippets.

@bollwyvl
Last active February 24, 2023 21:47
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save bollwyvl/88b0cb67d45a817ea474 to your computer and use it in GitHub Desktop.
Save bollwyvl/88b0cb67d45a817ea474 to your computer and use it in GitHub Desktop.
RevealJS TimelineJS

Basic use case

  • make a timeline (video)
    • save it someplace reveal.js can find it (maybe next to your presentation, or on Google Docs)
  • in reveal.js/index.html
    • add reveal-timeline.js as a dependency
    • in a <section> of reveal.js markup
      • add data-timeline="<url of the someplace>" to something, e.g. a div

Example

Let's assume I made an Timeline in JSON, and saved it next to my index.html.

<html>
  ...
  <section>
    <h1>Basic JSON Test</h1>
    <div data-timeline="welcome.json"></div>
  </section>
  ...
  <script>
    ...
    Reveal.initialize({
      dependencies: [
        ...
        {
          // maybe you put this in `plugins`
          src: 'reveal-timeline.js',
          condition: function(){
            return !!document.querySelector( '[data-timeline]' );
          }
          // Additional options
          // defaults to using already-loaded version, or CDN
          //js: "./js/timeline-min.js",
          // use a different attribute for your fragment selector
          //css: "./css/timeline.css",
          // use a different font
          //font: "Bevan-PotanoSans",
        
        }
        ...
      ]
    ...
    }
    ...
  </script>
  ...
</html>

LIMITATIONS

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>reveal.js timeline</title>
<meta name="description" content="An SVG Plugin for reveal.js">
<meta name="author" content="Nicholas Bollweg">
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link rel="stylesheet" href="//cdn.jsdelivr.net/reveal.js/latest/css/reveal.min.css">
<link rel="stylesheet" href="//cdn.jsdelivr.net/reveal.js/latest/css/theme/default.css" id="theme">
<!-- For syntax highlighting -->
<link rel="stylesheet" href="//cdn.jsdelivr.net/reveal.js/latest/lib/css/zenburn.css">
<!-- If the query includes 'print-pdf', include the PDF print sheet -->
<script>
if( window.location.search.match( /print-pdf/gi ) ) {
var link = document.createElement( 'link' );
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = '//cdn.jsdelivr.net/reveal.js/latest/css/print/pdf.css';
document.getElementsByTagName( 'head' )[0].appendChild( link );
}
</script>
<style>
.column{ width: 50%; float:left;}
</style>
<!--[if lt IE 9]>
<script src="lib/js/html5shiv.js"></script>
<![endif]-->
</head>
<body>
<div class="reveal">
<!-- Any section element inside of this container is displayed as a slide -->
<div class="slides">
<section>
<h1>Reveal.js Timeline</h1>
</section>
<section>
<h1>Basic JSON Test</h1>
<div data-timeline="welcome.json"></div>
</section>
<section data-markdown="README.md" data-separator="^\s*---\s*$" data-charset="iso-8859-15">
</section>
</div>
</div>
<script src="//cdn.jsdelivr.net/reveal.js/latest/lib/js/head.min.js"></script>
<script src="//cdn.jsdelivr.net/reveal.js/latest/js/reveal.min.js"></script>
<script>
var cdn = "//cdn.jsdelivr.net/reveal.js/latest/";
// Full list of configuration options available here:
// https://github.com/hakimel/reveal.js#configuration
Reveal.initialize({
controls: true,
progress: true,
history: true,
center: true,
theme: Reveal.getQueryHash().theme, // available themes are in /css/theme
transition: Reveal.getQueryHash().transition || 'default', // default/cube/page/concave/zoom/linear/fade/none
// Parallax scrolling
// parallaxBackgroundImage: 'https://s3.amazonaws.com/hakim-static/reveal-js/reveal-parallax-1.jpg',
// parallaxBackgroundSize: '2100px 900px',
// Optional libraries used to extend on reveal.js
dependencies: [
{ src: cdn + 'lib/js/classList.js', condition: function() { return !document.body.classList; } },
{ src: cdn + 'plugin/markdown/marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
{ src: cdn + 'plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
{ src: cdn + 'plugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } },
{ src: cdn + 'plugin/zoom-js/zoom.js', async: true, condition: function() { return !!document.body.classList; } },
{ src: cdn + 'plugin/notes/notes.js', async: true, condition: function() { return !!document.body.classList; } },
// NOTE! if you only use external markdown, make `condition: function(){ return 1; }`!
{ src: 'reveal-timeline.js', async: true, condition: function() { return !!document.querySelector( '[data-timeline]' ); } }
]
});
</script>
</body>
</html>
/*
Copyright (C) 2014 Nicholas Bollweg
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
;Reveal.SvgFragment = (function(Reveal){
"use strict";
var window = this,
document = window.document,
proto = window.location.protocol,
local = proto === "file:",
cdn = (local ? "http:" : proto) + "//cdnjs.cloudflare.com/ajax/libs/",
timeline_cdn = cdn + "timelinejs/2.30.1/",
defaults = {
jQuery: cdn + "jquery/2.1.1/jquery.min.js",
createStoryJS: timeline_cdn + "js/storyjs-embed.js",
js: timeline_cdn + "js/timeline-min.js",
css: timeline_cdn + "/css/timeline.css",
width: Reveal.getConfig().width
},
$ = function(sel){
var nodes = document.querySelectorAll(sel),
len = nodes.length,
result = [],
i = 0;
for(i; i < len ; i++){ result.push(nodes[i]); }
return result;
};
$.data = function(node, key){
return node.getAttribute("data-" + key);
};
// the main function, to be called when `createStoryJS` is available
function api(){
var createStoryJS = window.createStoryJS,
container = $("[data-timeline]"),
slides = $(".slides");
container.map(function(node){
var cfg = {
// TODO: Support other formats?
source: $.data(node, "timeline"),
embed_id: node.id ? node.id : node.id = api.id(),
width: $.data(node, "width") || api.cfg("width"),
height: $.data(node, "height") || (Reveal.getConfig().height - node.parentNode.clientHeight),
js: api.cfg("js"),
css: api.cfg("css")
};
createStoryJS(cfg);
});
return api;
};
api.id = function(){
return "reveal-timeline-" + (""+ Math.random()).replace(/0\./, "");
};
// preflight, call immediately it jquery/createStoryJS is available, otherwise load the script
api.init = function(){
var options = Reveal.getConfig().svgFragment || {};
return !window.jQuery ? api.load(api.cfg("jQuery"), api.init) :
!window.createStoryJS ? api.load(api.cfg("createStoryJS"), api.init) :
api();
};
// get configuration values (or defaults)
api.cfg = function(opt){
var cfg = Reveal.getConfig().svgFragment || {};
return opt in cfg ? cfg[opt] :
opt in defaults ? defaults[opt] :
function(){ throw new Error("Unknown property: "+ opt); };
};
// load a script, jacked from search, i think
api.load = function(url, callback){
var head = $('head')[0],
script = document.createElement('script');
// Wrapper for callback to make sure it only fires once
var finish = function(){
if(typeof callback === 'function') {
callback.call();
callback = null;
}
};
// IE
script.onreadystatechange = function() {
if (this.readyState === 'loaded') {
finish();
}
};
script.type = 'text/javascript';
script.src = url;
script.onload = finish;
// Normal browsers
head.appendChild(script);
return api;
};
return api.init();
}).call(this, Reveal);
{
"timeline":
{
"headline":"Welcome to TimelineJS",
"type":"default",
"startDate":"1888",
"text": "<p>TimelineJS is an open-source tool that enables you to build visually-rich interactive timelines and is available in 40 languages.</p><p>You're looking at an example of one right now.</p><p>Click on the arrow to the right to learn more.</p>",
"asset": {
"media":"http://2.bp.blogspot.com/-dxJbW0CG8Zs/TmkoMA5-cPI/AAAAAAAAAqw/fQpsz9GpFdo/s1600/voyage-dans-la-lune-1902-02-g.jpg",
"credit":"",
"caption":""
},
"date": [
{
"startDate":"1851",
"headline":"It's Easy to Make Your Own Timeline",
"text":"The TimelineJS Embed Generator makes it easy to add a timeline to your own site. Just copy our Google Spreadsheet template, add your events as rows in the spreadsheet, and use our <a href='#make'>generator tool</a> to generate the HTML you need to add to your site.",
"asset":
{
"media":"/static/welcome/step3.png",
"credit":"",
"caption":"Screenshot from TimelineJS Embed Generator tool (see below)"
}
},
{
"startDate":"1871",
"headline":"Illustrate your Timeline with photos, videos, tweets and more.",
"text":"Timeline can automatically pull in photos, videos from YouTube or Vimeo, tweets, wikipedia entries, and many other media types to help tell your story.",
"asset":
{
"media":"",
"credit":"",
"caption":"Screenshot from TimelineJS Embed Generator tool (see below)"
}
},
{
"startDate":"1899",
"headline":"YouTube video",
"text":"To add a YouTube video, just add a link to it in the media field. No embedding necessary. http://youtu.be/lIvftGgps24",
"asset":
{
"media":"http://youtu.be/lIvftGgps24",
"credit":"Georges Méliès",
"caption":"Le portrait mystérieux"
}
},
{
"startDate":"1902",
"headline":"YouTube with no text",
"text":"",
"asset":
{
"media":"http://youtu.be/7JDaOOw0MEE",
"credit":"Georges Méliès",
"caption":"A Trip to the Moon / Le Voyage dans la lune"
}
},
{
"startDate":"1902",
"headline":"Wikipedia",
"text":"Add a link to a <a href='http://en.wikipedia.org/wiki/A_Trip_to_the_Moon' target='_blank'>Wikipedia entry</a> in the media field to show an excerpt alongside your text.",
"asset":
{
"media":"http://en.wikipedia.org/wiki/A_Trip_to_the_Moon",
"credit":"",
"caption":""
}
},
{
"startDate":"1950,2,7",
"headline":"Blockquote",
"text":"This is an example of a blockquote. <br/>&lt;blockquote&gt;&ldquo;Just use html blockquotes in the media field.&rdquo;&lt;/blockquote&gt;",
"asset":
{
"media":"<blockquote>“You have brains in your head. You have feet in your shoes. You can steer yourself in any direction you choose. You're on your own, and you know what you know. And you are the guy who'll decide where to go.”</blockquote>",
"credit":"Dr. Seuss",
"caption":""
}
},
{
"startDate":"1960,2,7",
"headline":"Website",
"text":"This is an example of a website. Just paste a link to the site in the media field.",
"asset":
{
"media":"http://www.w3schools.com/",
"credit":"w3schools",
"caption":"http://w3schools.com"
}
},
{
"startDate":"1979,1,18",
"headline":"Google Map",
"text":"Google Maps are easy too. Just add the link to the map in the media field.",
"asset":
{
"media":"http://maps.google.com/maps?hl=en&sll=42.05083,-87.674194&sspn=0.020170947570668576,0.036220713642592585&z=15",
"credit":"",
"caption":""
}
},
{
"startDate":"1980,1,18",
"headline":"Google Map with no text",
"text":"",
"asset":
{
"media":"http://maps.google.com/maps?q=chicago&hl=en&sll=41.874961,-87.619054&sspn=0.159263,0.351906&t=t&hnear=Chicago,+Cook,+Illinois&z=11",
"credit":"",
"caption":""
}
},
{
"startDate":"1985,2,7",
"headline":"Flickr",
"text":"To add a Flickr photo, just paste a link to the photo page in the media field. Example: http://www.flickr.com/photos/zachwise/7074630607/",
"asset":
{
"media":"http://www.flickr.com/photos/zachwise/7074630607/in/photostream/",
"credit":"Zach Wise",
"caption":""
}
},
{
"startDate":"1990,2,7",
"headline":"Flickr with no text",
"text":"",
"asset":
{
"media":"http://www.flickr.com/photos/zachwise/7050589957/in/photostream/",
"credit":"Zach Wise",
"caption":"March to work."
}
},
{
"startDate":"2001,2,10",
"headline":"A Tweet",
"text":"To add a tweet, just paste a link to the tweet stats in the media field. Example: http://twitter.com/alykat/status/164184609519697920",
"asset":
{
"media":"http://twitter.com/alykat/status/164184609519697920",
"credit":"",
"caption":""
}
},
{
"startDate":"2002,12,10",
"headline":"Yet Another Tweet",
"asset":
{
"media":"http://twitter.com/ArjunaSoriano/status/164181156147900416",
"credit":"",
"caption":""
}
},
{
"startDate":"2011,8,23",
"headline":"Vimeo",
"text":"<p>Just add a link to the video in the media field. Example: https://vimeo.com/33211636</p>",
"asset":
{
"media":"https://vimeo.com/33211636",
"credit":"Denis Chapon",
"caption":""
}
},
{
"startDate":"2012,1,18",
"headline":"SoundCloud ",
"text":"Just add a link to the track in the media field.",
"asset":
{
"media":"http://soundcloud.com/beastieboys/make-some-noise",
"credit":"",
"caption":"R.I.P. MCA."
}
},
{
"startDate":"2013,10,01",
"headline":"Get started!",
"text":"Use the <a href='#make'>generator form</a> to make your first timeline now.",
"asset":
{
"media":"",
"credit":"",
"caption":""
}
}
]
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment