Skip to content

Instantly share code, notes, and snippets.

@bollwyvl
Last active August 7, 2023 08:33
Show Gist options
  • Select an option

  • Save bollwyvl/fe1d2806449487cdf88a to your computer and use it in GitHub Desktop.

Select an option

Save bollwyvl/fe1d2806449487cdf88a to your computer and use it in GitHub Desktop.

Revisions

  1. @nrbgt nrbgt revised this gist May 16, 2014. 1 changed file with 15 additions and 5 deletions.
    20 changes: 15 additions & 5 deletions reveal-svg-fragment.js
    Original file line number Diff line number Diff line change
    @@ -26,17 +26,18 @@ THE SOFTWARE.
    document = window.document,
    proto = window.location.protocol,
    local = proto === "file:",
    d3 = window.d3,
    defaults = {
    d3: (local ? "http:" : proto) + "//cdn.jsdelivr.net/d3js/latest/d3.min.js",
    selector: "title"
    };

    // the main function, to be called when d3 is available
    function api(){
    var d3 = window.d3,
    container = d3.selectAll("[data-svg-fragment]"),
    d3 = d3 || window.d3;
    var container = d3.selectAll("[data-svg-fragment]"),
    slides = d3.select(".slides");

    container.data(function(){
    return container[0].map(function(d){
    var $ = d3.select(d);
    @@ -131,8 +132,17 @@ THE SOFTWARE.
    // preflight, call immediately it d3 is available, otherwise load the script
    api.init = function(){
    var options = Reveal.getConfig().svgFragment || {};

    return window.api ? api() : api.load(api.cfg("d3"), api);
    if(window.d3){
    api();
    }else if(window.require){
    require([api.cfg("d3")], function(_d3){
    d3 = _d3;
    api();
    });
    }else{
    api.load(api.cfg("d3"), api);
    }
    return api;
    };


  2. bollwyvl revised this gist May 3, 2014. 1 changed file with 13 additions and 30 deletions.
    43 changes: 13 additions & 30 deletions reveal-svg-fragment.js
    Original file line number Diff line number Diff line change
    @@ -49,7 +49,7 @@ THE SOFTWARE.

    container.append("iframe")
    .attr({
    src: "about:blank",
    src: function(item){ return item.url; },
    // TODO: make this an option?
    scrolling: "no"
    })
    @@ -94,37 +94,20 @@ THE SOFTWARE.
    api.iframed = function(item){
    item.iframe = d3.select(this);
    item.idoc = d3.select(this.contentDocument);
    d3.xml(item.url, "image/svg+xml", function(xml){
    if(!xml){
    return console.warn("Could not load" + item.url);
    }
    item.idoc.select("body")
    .append("div")
    .attr({width: "100%", height: "100%"})
    .style({position: "relative"})
    .node()
    .appendChild(document.adoptNode(xml.documentElement));

    item.svg = item.idoc.select("svg");

    item.dims = {
    width: item.svg.attr("width") || 100,
    height: item.svg.attr("height") || 100
    };

    item.iframe.attr(item.dims);

    // see https://groups.google.com/forum/#!topic/d3-js/mTBxTLi0q1o
    item.svg.attr({
    width: "100%",
    height: "100%",
    viewBox: "0 0 "+ item.dims.width + " " + item.dims.height
    });

    api.clean(item);
    item.svg = item.idoc.select("svg");
    item.dims = {
    width: item.svg.attr("width") || 100,
    height: item.svg.attr("height") || 100
    };
    item.iframe.attr(item.dims);
    // see https://groups.google.com/forum/#!topic/d3-js/mTBxTLi0q1o
    item.svg.attr({
    width: "100%",
    height: "100%",
    viewBox: "0 0 "+ item.dims.width + " " + item.dims.height
    });

    return api;
    return api.clean(item);
    };

    // prepare
  3. @nrbgt nrbgt revised this gist May 2, 2014. 5 changed files with 1050 additions and 23 deletions.
    257 changes: 257 additions & 0 deletions d3.svg
    Loading
    Sorry, something went wrong. Reload?
    Sorry, we cannot display this file.
    Sorry, this file is invalid so it cannot be displayed.
    17 changes: 17 additions & 0 deletions github.svg
    Loading
    Sorry, something went wrong. Reload?
    Sorry, we cannot display this file.
    Sorry, this file is invalid so it cannot be displayed.
    47 changes: 39 additions & 8 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -4,10 +4,10 @@
    <head>
    <meta charset="utf-8">

    <title>reveal.js - The HTML Presentation Framework</title>
    <title>reveal.js svg fragments</title>

    <meta name="description" content="A framework for easily creating beautiful presentations using HTML">
    <meta name="author" content="Hakim El Hattab">
    <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" />
    @@ -30,6 +30,9 @@
    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>
    @@ -43,21 +46,49 @@
    <!-- Any section element inside of this container is displayed as a slide -->
    <div class="slides">
    <section>
    <h1>Reveal.js</h1>
    <h3>HTML Presentations Made Easy</h3>
    <h1>Reveal.js SVG Fragments</h1>
    <h3>
    <div class="column">
    Built with <a href="http://d3js.org">d3</a>
    <div data-svg-fragment="d3.svg"></div>
    </div>
    <div class="column">
    Works with <a href="http://inkscape.org">Inkscape</a>
    <div data-svg-fragment="inkscape.svg" href="http://inkscape.org"></div>
    </div>
    </h3>
    <p>
    <small>Created by <a href="http://hakim.se">Hakim El Hattab</a> / <a href="http://twitter.com/hakimel">@hakimel</a></small>
    <small>Created by <a href="http://github.com/bollwyvl">@bollwyvl</a></small>
    </p>
    </section>

    <section>
    <h2>Ugly Test SVG</h2>
    <h1>Basic HTML Test</h1>
    <div data-svg-fragment="test.svg#[*|label=base]">
    <a class="fragment" title="[*|label=fragment1]"></a>
    <a class="fragment" title="[*|label=fragment2]"></a>
    </div>
    </section>

    <section data-markdown>
    <script type="text/template">
    # Using Markdown
    <div data-svg-fragment="test.svg#[*|label=fragment1]">
    <a class="fragment" title="[*|label=base]"></a>
    <a class="fragment" title="[*|label=fragment2]"></a>
    </div>
    </script>
    </section>
    <section>
    <h1>Questions / Feedback</h1>
    <h3>
    Comment/fork on
    <a href="https://gist.github.com/bollwyvl/fe1d2806449487cdf88a">
    GitHub
    </a>

    <div data-svg-fragment="github.svg"></div>
    </h3>
    </section>
    </div>

    </div>
    726 changes: 726 additions & 0 deletions inkscape.svg
    Loading
    Sorry, something went wrong. Reload?
    Sorry, we cannot display this file.
    Sorry, this file is invalid so it cannot be displayed.
    26 changes: 11 additions & 15 deletions reveal-svg-fragment.js
    Original file line number Diff line number Diff line change
    @@ -80,6 +80,7 @@ THE SOFTWARE.
    // toggle a fragment
    // TODO: add hide
    api.toggle = function(fragment, item, show){
    if(!item.svg){ return; }
    var selector = fragment.attr(api.cfg("selector"));
    item.svg.selectAll(selector)
    .transition()
    @@ -94,17 +95,21 @@ THE SOFTWARE.
    item.iframe = d3.select(this);
    item.idoc = d3.select(this.contentDocument);
    d3.xml(item.url, "image/svg+xml", function(xml){
    if(!xml){
    return console.warn("Could not load" + item.url);
    }
    item.idoc.select("body")
    .append("div")
    .attr({width: "100%", height: "100%"})
    .attr({width: "100%", height: "100%"})
    .style({position: "relative"})
    .node()
    .appendChild(xml.documentElement);
    .appendChild(document.adoptNode(xml.documentElement));

    item.svg = item.idoc.select("svg");

    item.dims = {
    width: item.svg.attr("width"),
    height: item.svg.attr("height")
    width: item.svg.attr("width") || 100,
    height: item.svg.attr("height") || 100
    };

    item.iframe.attr(item.dims);
    @@ -113,24 +118,15 @@ THE SOFTWARE.
    item.svg.attr({
    width: "100%",
    height: "100%",
    viewBox: "0 0 "+ item.dims.width + " "+ item.dims.height,
    preserveAspectRatio: "none"
    viewBox: "0 0 "+ item.dims.width + " " + item.dims.height
    });

    api.svged(item);
    api.clean(item);
    });

    return api;
    };


    // the svg was loaded for this item
    api.svged = function(item){

    return api.clean(item);
    };


    // prepare
    // TODO: smarter initialization?
    api.clean = function(item){
  4. @nrbgt nrbgt revised this gist May 1, 2014. 2 changed files with 48 additions and 22 deletions.
    30 changes: 24 additions & 6 deletions reveal-svg-fragment.js
    Original file line number Diff line number Diff line change
    @@ -34,7 +34,8 @@ THE SOFTWARE.
    // the main function, to be called when d3 is available
    function api(){
    var d3 = window.d3,
    container = d3.selectAll("[data-svg-fragment]");
    container = d3.selectAll("[data-svg-fragment]"),
    slides = d3.select(".slides");

    container.data(function(){
    return container[0].map(function(d){
    @@ -93,8 +94,29 @@ THE SOFTWARE.
    item.iframe = d3.select(this);
    item.idoc = d3.select(this.contentDocument);
    d3.xml(item.url, "image/svg+xml", function(xml){
    item.idoc.node().body.appendChild(xml.documentElement);
    item.idoc.select("body")
    .append("div")
    .attr({width: "100%", height: "100%"})
    .node()
    .appendChild(xml.documentElement);

    item.svg = item.idoc.select("svg");

    item.dims = {
    width: item.svg.attr("width"),
    height: item.svg.attr("height")
    };

    item.iframe.attr(item.dims);

    // see https://groups.google.com/forum/#!topic/d3-js/mTBxTLi0q1o
    item.svg.attr({
    width: "100%",
    height: "100%",
    viewBox: "0 0 "+ item.dims.width + " "+ item.dims.height,
    preserveAspectRatio: "none"
    });

    api.svged(item);
    });

    @@ -104,10 +126,6 @@ THE SOFTWARE.

    // the svg was loaded for this item
    api.svged = function(item){
    item.iframe.attr({
    width: item.svg.attr("width"),
    height: item.svg.attr("height")
    });

    return api.clean(item);
    };
    40 changes: 24 additions & 16 deletions test.svg
    Loading
    Sorry, something went wrong. Reload?
    Sorry, we cannot display this file.
    Sorry, this file is invalid so it cannot be displayed.
  5. bollwyvl revised this gist May 1, 2014. 2 changed files with 24 additions and 70 deletions.
    6 changes: 3 additions & 3 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,7 @@
    # SVG fragment builds for reveal.js
    # SVG fragment builds for [reveal.js](https://github.com/hakimel/reveal.js)

    ## Basic use case
    - make an SVG (maybe in inkscape)
    - make an SVG (maybe in [inkscape](http://www.inkscape.org/en/))
    - save it someplace reveal.js can find it (maybe next to your presentation)
    - figure out how to identify them (maybe use named layers)
    - in reveal.js/index.html
    @@ -13,7 +13,7 @@
    - add `title="<a selector>"` to those things
    - `[*|label=<a label>]` is good
    - for more about selectors, check out the
    [w3c](http://www.w3.org/TR/css3-selectors/)
    [W3C page](http://www.w3.org/TR/css3-selectors/)

    ## Example
    Let's assume I made an SVG in Inkscape, and saved it next to my `index.html`.
    88 changes: 21 additions & 67 deletions reveal-svg-fragment.js
    Original file line number Diff line number Diff line change
    @@ -1,71 +1,25 @@
    /*
    # SVG fragment builds for reveal.js
    ## LIMITATIONS
    - won't work in Chrome against `file://`
    - workarounds:
    - dropbox
    - sharepoint
    - confluence
    - gist
    - `python -m SimpleHTTPServer`
    - probably won't work in IE
    - wontfix
    ## Basic use case
    - build an SVG (maybe in inkscape)
    - save it someplace reveal.js can find it (maybe next to your presentation)
    - figure out how to identify them (maybe use named layers)
    - in reveal.js/index.html
    - add `svg-fragment.js` as a dependency
    - in a `<section>` of reveal.js markup
    - add `data-svg-fragment="<url of the someplace>"` to something, e.g.
    a `div`
    - add some things with `class="fragment"` inside that thing
    - add `title="<a selector>"` to those things
    - `[*|label=<a label>]` is good
    - for more about selectors, check out the
    [w3c](http://www.w3.org/TR/css3-selectors/)
    ## Example
    Let's assume I made an SVG in Inkscape, and saved it next to my `index.html`.
    It has three layers: `base`, `fragment1` and `fragment2`
    <html>
    ...
    <section>
    <div data-svg-fragment="figure.svg#[*|label=base]">
    <a class="fragment" href="[*|label=fragment1]"></a>
    <a class="fragment" href="[*|label=fragment2]"></a>
    </div>
    </section>
    ...
    <script>
    ...
    Reveal.initialize({
    dependencies: [
    ...
    {
    src: 'plugin/svg-fragment/svg-fragment.js',
    condition: function(){
    return !!document.querySelector( '[data-svg-fragment]' );
    }
    // Additional options
    // defaults to using already-loaded version, or CDN
    //d3: "./d3.min.js",
    // use a different attribute for your fragment selector
    //selector: "title",
    }
    ...
    ]
    ...
    }
    ...
    </script>
    ...
    </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,
  6. bollwyvl revised this gist May 1, 2014. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion index.html
    Original file line number Diff line number Diff line change
    @@ -51,7 +51,8 @@ <h3>HTML Presentations Made Easy</h3>
    </section>

    <section>
    <div data-svg-fragment="test.svg">
    <h2>Ugly Test SVG</h2>
    <div data-svg-fragment="test.svg#[*|label=base]">
    <a class="fragment" title="[*|label=fragment1]"></a>
    <a class="fragment" title="[*|label=fragment2]"></a>
    </div>
  7. bollwyvl revised this gist May 1, 2014. 1 changed file with 109 additions and 0 deletions.
    109 changes: 109 additions & 0 deletions test.svg
    Loading
    Sorry, something went wrong. Reload?
    Sorry, we cannot display this file.
    Sorry, this file is invalid so it cannot be displayed.
  8. bollwyvl created this gist May 1, 2014.
    66 changes: 66 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,66 @@
    # SVG fragment builds for reveal.js

    ## Basic use case
    - make an SVG (maybe in inkscape)
    - save it someplace reveal.js can find it (maybe next to your presentation)
    - figure out how to identify them (maybe use named layers)
    - in reveal.js/index.html
    - add `reveal-svg-fragment.js` as a dependency
    - in a `<section>` of reveal.js markup
    - add `data-svg-fragment="<url of the someplace>"` to something, e.g.
    a `div`
    - add some things with `class="fragment"` inside that thing
    - add `title="<a selector>"` to those things
    - `[*|label=<a label>]` is good
    - for more about selectors, check out the
    [w3c](http://www.w3.org/TR/css3-selectors/)

    ## Example
    Let's assume I made an SVG in Inkscape, and saved it next to my `index.html`.
    It has three layers: `base`, `fragment1` and `fragment2`.

    <html>
    ...
    <section>
    <div data-svg-fragment="figure.svg#[*|label=base]">
    <a class="fragment" href="[*|label=fragment1]"></a>
    <a class="fragment" href="[*|label=fragment2]"></a>
    </div>
    </section>
    ...
    <script>
    ...
    Reveal.initialize({
    dependencies: [
    ...
    {
    // maybe you put this in `plugins`
    src: 'reveal-svg-fragment.js',
    condition: function(){
    return !!document.querySelector( '[data-svg-fragment]' );
    }
    // Additional options
    // defaults to using already-loaded version, or CDN
    //d3: "./d3.min.js",
    // use a different attribute for your fragment selector
    //selector: "title",
    }
    ...
    ]
    ...
    }
    ...
    </script>
    ...
    </html>

    ## LIMITATIONS
    - won't work in Chrome against `file://`
    - workarounds:
    - dropbox
    - sharepoint
    - confluence
    - gist
    - `python -m SimpleHTTPServer`
    - probably won't work in IE
    - wontfix
    99 changes: 99 additions & 0 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,99 @@
    <!doctype html>
    <html lang="en">

    <head>
    <meta charset="utf-8">

    <title>reveal.js - The HTML Presentation Framework</title>

    <meta name="description" content="A framework for easily creating beautiful presentations using HTML">
    <meta name="author" content="Hakim El Hattab">

    <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>

    <!--[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</h1>
    <h3>HTML Presentations Made Easy</h3>
    <p>
    <small>Created by <a href="http://hakim.se">Hakim El Hattab</a> / <a href="http://twitter.com/hakimel">@hakimel</a></small>
    </p>
    </section>

    <section>
    <div data-svg-fragment="test.svg">
    <a class="fragment" title="[*|label=fragment1]"></a>
    <a class="fragment" title="[*|label=fragment2]"></a>
    </div>
    </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; } },
    { src: 'reveal-svg-fragment.js', condition: function() { return !!document.querySelector( '[data-svg-fragment]' ); } }
    ]
    });

    </script>

    </body>
    </html>
    229 changes: 229 additions & 0 deletions reveal-svg-fragment.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,229 @@
    /*
    # SVG fragment builds for reveal.js
    ## LIMITATIONS
    - won't work in Chrome against `file://`
    - workarounds:
    - dropbox
    - sharepoint
    - confluence
    - gist
    - `python -m SimpleHTTPServer`
    - probably won't work in IE
    - wontfix
    ## Basic use case
    - build an SVG (maybe in inkscape)
    - save it someplace reveal.js can find it (maybe next to your presentation)
    - figure out how to identify them (maybe use named layers)
    - in reveal.js/index.html
    - add `svg-fragment.js` as a dependency
    - in a `<section>` of reveal.js markup
    - add `data-svg-fragment="<url of the someplace>"` to something, e.g.
    a `div`
    - add some things with `class="fragment"` inside that thing
    - add `title="<a selector>"` to those things
    - `[*|label=<a label>]` is good
    - for more about selectors, check out the
    [w3c](http://www.w3.org/TR/css3-selectors/)
    ## Example
    Let's assume I made an SVG in Inkscape, and saved it next to my `index.html`.
    It has three layers: `base`, `fragment1` and `fragment2`
    <html>
    ...
    <section>
    <div data-svg-fragment="figure.svg#[*|label=base]">
    <a class="fragment" href="[*|label=fragment1]"></a>
    <a class="fragment" href="[*|label=fragment2]"></a>
    </div>
    </section>
    ...
    <script>
    ...
    Reveal.initialize({
    dependencies: [
    ...
    {
    src: 'plugin/svg-fragment/svg-fragment.js',
    condition: function(){
    return !!document.querySelector( '[data-svg-fragment]' );
    }
    // Additional options
    // defaults to using already-loaded version, or CDN
    //d3: "./d3.min.js",
    // use a different attribute for your fragment selector
    //selector: "title",
    }
    ...
    ]
    ...
    }
    ...
    </script>
    ...
    </html>
    */
    ;Reveal.SvgFragment = (function(Reveal){
    "use strict";
    var window = this,
    document = window.document,
    proto = window.location.protocol,
    local = proto === "file:",
    defaults = {
    d3: (local ? "http:" : proto) + "//cdn.jsdelivr.net/d3js/latest/d3.min.js",
    selector: "title"
    };

    // the main function, to be called when d3 is available
    function api(){
    var d3 = window.d3,
    container = d3.selectAll("[data-svg-fragment]");

    container.data(function(){
    return container[0].map(function(d){
    var $ = d3.select(d);
    return {
    container: $,
    url: $.attr("data-svg-fragment")
    };
    });
    });

    container.append("iframe")
    .attr({
    src: "about:blank",
    // TODO: make this an option?
    scrolling: "no"
    })
    .on("load", api.iframed);

    Reveal.addEventListener("fragmentshown", api.listen(container, true));
    Reveal.addEventListener("fragmenthidden", api.listen(container));

    return api;
    };


    // generate listeners for reveal events
    api.listen = function(container, show){
    return function(event){
    var fragment = d3.select(event.fragment);
    container.filter(function(){
    return this === event.fragment.parentNode;
    }).each(function(item){
    api.toggle(fragment, item, show);
    });

    return api;
    };
    };


    // toggle a fragment
    // TODO: add hide
    api.toggle = function(fragment, item, show){
    var selector = fragment.attr(api.cfg("selector"));
    item.svg.selectAll(selector)
    .transition()
    .style({opacity: show ? 1 : 0});

    return api;
    };


    // the iframe was created for this item
    api.iframed = function(item){
    item.iframe = d3.select(this);
    item.idoc = d3.select(this.contentDocument);
    d3.xml(item.url, "image/svg+xml", function(xml){
    item.idoc.node().body.appendChild(xml.documentElement);
    item.svg = item.idoc.select("svg");
    api.svged(item);
    });

    return api;
    };


    // the svg was loaded for this item
    api.svged = function(item){
    item.iframe.attr({
    width: item.svg.attr("width"),
    height: item.svg.attr("height")
    });

    return api.clean(item);
    };


    // prepare
    // TODO: smarter initialization?
    api.clean = function(item){
    var base;
    item.container.selectAll(".fragment").each(function(){
    item.svg.selectAll(d3.select(this).attr(api.cfg("selector")))
    .style({opacity: 0});
    });

    if(base = item.url.match(/(?:#)(.*)$/)){
    item.svg.selectAll(base[1])
    .style({opacity: 1});
    }

    return api;
    };


    // preflight, call immediately it d3 is available, otherwise load the script
    api.init = function(){
    var options = Reveal.getConfig().svgFragment || {};

    return window.api ? api() : api.load(api.cfg("d3"), api);
    };


    // get configuration values (or defaults)
    api.cfg = function(opt){
    var cfg = Reveal.getConfig().svgFragment || {};

    return cfg.hasOwnProperty(opt) ? cfg[opt] :
    defaults.hasOwnProperty(opt) ? defaults[opt] :
    function(){ throw new Error("Unknown property: "+ opt); };
    };


    // load a script, jacked from search, i think
    api.load = function(url, callback){
    var head = document.querySelector('head'),
    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);