summaryrefslogtreecommitdiff
path: root/deck.js/extensions
diff options
context:
space:
mode:
Diffstat (limited to 'deck.js/extensions')
-rw-r--r--deck.js/extensions/anim/deck.anim.js176
-rw-r--r--deck.js/extensions/bundle-maker/README.txt24
-rwxr-xr-xdeck.js/extensions/bundle-maker/make-bundle.sh26
-rw-r--r--deck.js/extensions/bundle-maker/presentation.html140
-rw-r--r--deck.js/extensions/clone/deck.clone.js127
-rw-r--r--deck.js/extensions/events/README.md64
-rw-r--r--deck.js/extensions/events/deck.events.js23
-rw-r--r--deck.js/extensions/fit/deck.fit-fs.css14
-rw-r--r--deck.js/extensions/fit/deck.fit.js171
-rw-r--r--deck.js/extensions/goto/deck.goto.css41
-rw-r--r--deck.js/extensions/goto/deck.goto.html7
-rw-r--r--deck.js/extensions/goto/deck.goto.js170
-rwxr-xr-xdeck.js/extensions/goto/deck.goto.scss46
-rw-r--r--deck.js/extensions/hash/deck.hash.css13
-rw-r--r--deck.js/extensions/hash/deck.hash.html2
-rw-r--r--deck.js/extensions/hash/deck.hash.js142
-rw-r--r--deck.js/extensions/hash/deck.hash.scss15
-rw-r--r--deck.js/extensions/menu/deck.menu.css47
-rw-r--r--deck.js/extensions/menu/deck.menu.js187
-rwxr-xr-xdeck.js/extensions/menu/deck.menu.scss58
-rw-r--r--deck.js/extensions/navigation/deck.navigation.css43
-rw-r--r--deck.js/extensions/navigation/deck.navigation.html3
-rw-r--r--deck.js/extensions/navigation/deck.navigation.js92
-rwxr-xr-xdeck.js/extensions/navigation/deck.navigation.scss56
-rw-r--r--deck.js/extensions/scale/deck.scale.css28
-rw-r--r--deck.js/extensions/scale/deck.scale.js170
-rw-r--r--deck.js/extensions/scale/deck.scale.scss31
-rw-r--r--deck.js/extensions/simplemath/deck.simplemath.js25
-rw-r--r--deck.js/extensions/smartsyntax/deck.smartsyntax.js226
-rw-r--r--deck.js/extensions/status/deck.status.css25
-rw-r--r--deck.js/extensions/status/deck.status.html6
-rw-r--r--deck.js/extensions/status/deck.status.js120
-rwxr-xr-xdeck.js/extensions/status/deck.status.scss22
-rw-r--r--deck.js/extensions/step/deck.step.js119
-rw-r--r--deck.js/extensions/svg/deck.svg.js115
35 files changed, 2574 insertions, 0 deletions
diff --git a/deck.js/extensions/anim/deck.anim.js b/deck.js/extensions/anim/deck.anim.js
new file mode 100644
index 0000000..8cf9e08
--- /dev/null
+++ b/deck.js/extensions/anim/deck.anim.js
@@ -0,0 +1,176 @@
+
+(function($, deck, undefined) {
+ // This next line is the color plugin from jquery
+ (function(d){d.each(["backgroundColor","borderBottomColor","borderLeftColor","borderRightColor","borderTopColor","color","outlineColor"],function(f,e){d.fx.step[e]=function(g){if(!g.colorInit){g.start=c(g.elem,e);g.end=b(g.end);g.colorInit=true}g.elem.style[e]="rgb("+[Math.max(Math.min(parseInt((g.pos*(g.end[0]-g.start[0]))+g.start[0]),255),0),Math.max(Math.min(parseInt((g.pos*(g.end[1]-g.start[1]))+g.start[1]),255),0),Math.max(Math.min(parseInt((g.pos*(g.end[2]-g.start[2]))+g.start[2]),255),0)].join(",")+")"}});function b(f){var e;if(f&&f.constructor==Array&&f.length==3){return f}if(e=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(f)){return[parseInt(e[1]),parseInt(e[2]),parseInt(e[3])]}if(e=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(f)){return[parseFloat(e[1])*2.55,parseFloat(e[2])*2.55,parseFloat(e[3])*2.55]}if(e=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(f)){return[parseInt(e[1],16),parseInt(e[2],16),parseInt(e[3],16)]}if(e=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(f)){return[parseInt(e[1]+e[1],16),parseInt(e[2]+e[2],16),parseInt(e[3]+e[3],16)]}if(e=/rgba\(0, 0, 0, 0\)/.exec(f)){return a.transparent}return a[d.trim(f).toLowerCase()]}function c(g,e){var f;do{f=d.curCSS(g,e);if(f!=""&&f!="transparent"||d.nodeName(g,"body")){break}e="backgroundColor"}while(g=g.parentNode);return b(f)}var a={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0],transparent:[255,255,255]}})(jQuery);
+
+ var $d = $(document);
+ var may = function(o,f) {return f ? f.bind(o) : function() {}};
+
+ $.extend(true, $[deck].defaults, {
+ selectors: {
+ animShow: ".anim-show",
+ animHide: ".anim-hide",
+ animAddClass: ".anim-addclass",
+ animRemoveClass: ".anim-removeclass",
+ animAttribute: ".anim-attribute",
+ // specific ones
+ animPlay: ".anim-play",
+ animPause: ".anim-pause",
+ animViewboxAs: ".anim-viewboxas",
+ //
+ animContinue: ".anim-continue"
+ },
+ anim: {
+ duration: 400
+ }
+ });
+
+ var waitFor = 0
+ $[deck]('extend', 'animWaitMore', function(){ waitFor++ });
+ $[deck]('extend', 'animWaitLess', function(){ waitFor-- });
+
+ var doInitIfReady = function hoho() {
+ if (waitFor>0) {
+ setTimeout(doInitIfReady, 10) // retry until all is loaded
+ return;
+ }
+ // first we define some tools and grab some info from deck.js
+ var o = $[deck]('getOptions');
+ var context = function(el) {
+ return {
+ what: function() {return $(el).attr("data-what")},
+ dur: function() {return $(el).attr("data-dur")*1 || o.anim.duration},
+ classs: function() {return $(el).attr("data-class")},
+ attribute: function() {return $(el).attr("data-attr").split(':')[0]},
+ as: function() {return $(el).attr("data-as")},
+ value: function() {return $(el).attr("data-attr").split(':')[1]},
+ toplevel: function() {return $[deck]('getToplevelSlideOf', el).node},
+ all: function() {return $(this.what(),this.toplevel())}
+ }
+ };
+ var classical = function(selector, methods) {
+ $(selector).each(function(i, el) {
+ var c = context(el);
+ may(methods, methods.create)(c);
+ $(el).bind('deck.toplevelBecameCurrent', function(_, direction) {
+ may(methods, methods.init)(c);
+ }).bind('deck.afterToplevelBecameCurrent', function(_, direction) {
+ may(methods, methods.fast)(c);
+ }).bind('deck.lostCurrent', function(_, direction, from, to) {
+ if (direction == 'forward' || Math.abs(from - to)>1 ) return; // if a big step, let the "step" extension do its job
+ may(methods, methods.undo)(c);
+ }).bind('deck.becameCurrent', function(_, direction, from, to) {
+ if (direction == 'reverse' || Math.abs(from - to)>1 ) return; // if a big step, let the "step" extension do its job
+ may(methods, methods.doit)(c);
+ });
+ });
+ };
+
+ // here come the real animations
+ classical(o.selectors.animShow, {
+ init: function(c) {c.all().animate({'opacity': 0.}, 0)},
+ undo: function(c) {c.all().animate({'opacity': 0.}, c.dur()/100)},
+ doit: function(c) {c.all().animate({'opacity': 1.}, c.dur())},
+ fast: function(c) {c.all().animate({'opacity': 1.}, 0)}
+ });
+ classical(o.selectors.animHide, {
+ init: function(c) {c.all().animate({'opacity': 1.}, 0)},
+ undo: function(c) {c.all().animate({'opacity': 1.}, c.dur()/100)},
+ doit: function(c) {c.all().animate({'opacity': 0.}, c.dur())},
+ fast: function(c) {c.all().animate({'opacity': 0.}, 0)}
+ });
+ classical(o.selectors.animAddClass, {
+ init: function(c) {c.all().removeClass(c.classs())},
+ undo: function(c) {c.all().removeClass(c.classs())},
+ doit: function(c) {c.all().addClass(c.classs())},
+ fast: function(c) {c.all().addClass(c.classs())}
+ });
+ classical(o.selectors.animRemoveClass, {
+ init: function(c) {c.all().addClass(c.classs())},
+ undo: function(c) {c.all().addClass(c.classs())},
+ doit: function(c) {c.all().removeClass(c.classs())},
+ fast: function(c) {c.all().removeClass(c.classs())}
+ });
+ classical(o.selectors.animAttribute, {
+ init: function(c) {
+ c.previousElement = [];
+ c.all().css(c.attribute(), '') // for the jquery anim to work the css attribute should not be defined in the element (in the html) so we suppose it is empty by default (and thus, if it is not empty, it means it has been set by jquery)
+ },
+ undo: function(c) {
+ var k = c.attribute()
+ for (i in c.previousElement) { // use the saved list of elements and values
+ var whatTo = {}
+ whatTo[k] = c.previousCss[i]
+ $(c.previousElement[i]).animate(whatTo, 0)
+ }
+ },
+ doit: function(c, factor) {
+ if (factor === undefined) factor = 1
+ var k = c.attribute()
+ c.previousCss = []
+ c.previousElement = []
+ c.all().each( function(){c.previousElement.push(this); c.previousCss.push($(this).css(k))}) // save a list of elements and values
+ var whatTo = {}
+ whatTo[c.attribute()] = c.value()
+ c.all().animate(whatTo, c.dur()*factor)
+ },
+ fast: function(c) {this.doit(c,0)}
+ });
+ classical(o.selectors.animPlay, {
+ init: function(c) {c.all().each(function(){this.pause(); try{this.currentTime=0}catch(e){} })},
+ undo: function(c) {c.all().each(function(){this.pause()})},
+ doit: function(c) {c.all().each(function(){this.play()})},
+ fast: function(c) {c.all().each(function(){this.play()})}
+ });
+ classical(o.selectors.animPause, {
+ undo: function(c) {c.all().each(function(){this.play()})},
+ doit: function(c) {c.all().each(function(){this.pause()})},
+ fast: function(c) {c.all().each(function(){this.pause()})}
+ });
+ classical(o.selectors.animViewboxAs, {
+ create: function(c) {c.whatFrom = {}},
+ init: function(c) {this.undo(c)},
+ undo: function(c) {c.all().animate(c.whatFrom, 0)},
+ doit: function(c, factor) {
+ if (factor === undefined) factor = 1
+ var attr = "svgViewBox";
+ var whatTo = {};
+ var asWhat = $(c.as());
+ var a = function (i) {return asWhat.attr(i)}
+ // todo should do as with the generic attribute above (maintain a list)
+ c.whatFrom[attr] = c.all().first().get(0).attributes.getNamedItem('viewBox').nodeValue // custom access to the svg viewbox attribute
+ var toViewBox = a('x')+" "+a('y')+" "+a('width')+" "+a('height');
+ whatTo[attr] = toViewBox;
+ c.all().animate(whatTo, c.dur()*factor)
+ },
+ fast: function(c) {this.doit(c, 0)}
+ });
+ classical(o.selectors.animContinue, {
+ doit: function(c) {setTimeout(function(){$[deck]('next')}, 1)}
+ // do not do it in fast mode
+ });
+ // handle the chained undo for "anim-continue"
+ $(o.selectors.animContinue).each(function(i, curSlide) {
+ $(curSlide).bind('deck.becameCurrent', function(_, direction) {
+ if (direction == 'forward') return;
+ setTimeout(function(){$[deck]('prev')}, 1)
+ });
+
+ });
+
+ // finally force "refresh" (notification of slide change)
+ var current = $[deck]('getSlide')
+ var icur = 0
+ for (; icur < $[deck]('getSlides').length; icur++) {
+ if ($[deck]('getSlides')[icur] == current) break;
+ }
+ $d.trigger("deck.change", [icur, 0]);
+ $d.trigger("deck.change", [0, icur]);
+
+ }
+ $(document).bind('deck.init', function() {
+ setTimeout(doInitIfReady, 10) // try the first time after init
+ });
+
+})(jQuery, 'deck');
+
diff --git a/deck.js/extensions/bundle-maker/README.txt b/deck.js/extensions/bundle-maker/README.txt
new file mode 100644
index 0000000..f58232f
--- /dev/null
+++ b/deck.js/extensions/bundle-maker/README.txt
@@ -0,0 +1,24 @@
+
+PRESENTATION FILE
+=================
+An bare example file including most used extensions is given in the current folder as "presentation.html".
+This files references and uses the files from the "deck.js" folder.
+If you want to reduce the overall size of the "deck.js" folder, you can safely remove the "deck.js/samples" directory (if you don't need the samples obviously).
+
+
+
+RESOURCES
+=========
+Example presentations can be found in the the deck.js/samples folder.
+You can also consult online examples, see http://home.heeere.com/tech-deckjs-ext.html
+
+
+
+NOTE FOR USE WITH CHROME/CHROMIUM
+=================================
+To allow the presentation page to load all the resources when stored locally, you must start chrome/chromium with a special command line option.
+Use "chromium-browser --disable-web-security " to do so.
+
+
+
+
diff --git a/deck.js/extensions/bundle-maker/make-bundle.sh b/deck.js/extensions/bundle-maker/make-bundle.sh
new file mode 100755
index 0000000..30f740b
--- /dev/null
+++ b/deck.js/extensions/bundle-maker/make-bundle.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+N=deckjs-bundle
+W=$(basename $(dirname $(readlink -f $0)))
+
+SCRATCH=/tmp
+test -d /media/ramdisk && SCRATCH=/media/ramdisk
+
+if test -d .git
+then
+ pwd=$(pwd)
+ cd $SCRATCH
+ tmp=,,for-$N
+ rm -rf $tmp
+ git clone $pwd $tmp
+ tmp=$(pwd)/$tmp
+ cd -
+ rm -rf $N $N.zip
+ mkdir -p $N/deck.js
+ cp -t $N/deck.js -r $tmp/core/ $tmp/extensions/ $tmp/libs/ $tmp/samples/ $tmp/themes/ $tmp/modernizr.custom.js $tmp/jquery-1.7.2.min.js
+ cp -t $N $tmp/extensions/$W/README.txt $tmp/extensions/$W/presentation.html
+ cat $tmp/.git/refs/heads/master >> $N/README.txt
+ zip -r $N.zip $N
+else
+ echo "This script is designed to be run from the root of the git repository"
+fi
diff --git a/deck.js/extensions/bundle-maker/presentation.html b/deck.js/extensions/bundle-maker/presentation.html
new file mode 100644
index 0000000..1561c35
--- /dev/null
+++ b/deck.js/extensions/bundle-maker/presentation.html
@@ -0,0 +1,140 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+ <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0">
+
+ <!-- PROVIDE METADATA -->
+ <!-- ================ -->
+ <title>ZZZZ A Deck.js Presentation</title>
+ <meta name="author" content="ZZZZ Author">
+
+ <!-- Required stylesheet -->
+ <link rel="stylesheet" href="deck.js/core/deck.core.css">
+
+ <!-- Style theme. More available in deck.js/themes/style/ or create your own. -->
+ <link rel="stylesheet" href="deck.js/themes/style/web-2.0.css">
+
+ <!-- Transition, for your audience, use it only for short presentations, see deck.js/themes/transition -->
+ <!--link rel="stylesheet" href="deck.js/themes/transition/****.css"-->
+
+ <!-- Required Modernizr file -->
+ <script src="deck.js/modernizr.custom.js"></script>
+ <!-- Required JS files. -->
+ <script src="deck.js/jquery-1.7.2.min.js"></script>
+ <script src="deck.js/core/deck.core.js"></script>
+
+ <!-- PROVIDE EXTENSIONS: JS and CSS files -->
+ <!-- ============================ -->
+ <!-- proper slide scaling (type 's' to disable) -->
+ <script src="deck.js/extensions/fit/deck.fit.js"></script>
+ <link rel="stylesheet" href="deck.js/extensions/fit/deck.fit-fs.css"> <!-- fit to window -->
+ <!-- animations, svg etc (better to include it after the 'status' extension... so see below) -->
+ <!-- math equations -->
+ <script src="deck.js/libs/display-latex2.user.js"></script>
+ <script src="deck.js/extensions/simplemath/deck.simplemath.js"></script>
+ <!-- smart syntax -->
+ <script src="deck.js/extensions/smartsyntax/deck.smartsyntax.js"></script>
+ <!-- clone by typing 'c' (popups a slave presentation) (uses "clone snippet" at the end of the page) -->
+ <script src="deck.js/extensions/clone/deck.clone.js"></script>
+ <!-- goto by typing 'g' (uses "goto snippet" at the end of the page) -->
+ <link rel="stylesheet" href="deck.js/extensions/goto/deck.goto.css">
+ <script src="deck.js/extensions/goto/deck.goto.js"></script>
+ <!-- slide number indicator (uses "status snippet" at the end of the page) -->
+ <link rel="stylesheet" href="deck.js/extensions/status/deck.status.css">
+ <script src="deck.js/extensions/status/deck.status.js"></script>
+ <!-- navigation buttons (uses "navigation snippet" at the end of the page) -->
+ <link rel="stylesheet" href="deck.js/extensions/navigation/deck.navigation.css">
+ <script src="deck.js/extensions/navigation/deck.navigation.js"></script>
+ <!-- slide selector by typing 'm' -->
+ <script src="deck.js/extensions/menu/deck.menu.js"></script>
+ <link rel="stylesheet" href="deck.js/extensions/menu/deck.menu.css">
+ <!-- permalink (uses "hash snippet" at the end of the page) -->
+ <link rel="stylesheet" href="deck.js/extensions/hash/deck.hash.css">
+ <script src="deck.js/extensions/hash/deck.hash.js"></script>
+ <!-- animations, svg etc (better to include it after the 'status' extension (to avoid huge fake slide numbers) -->
+ <script src="deck.js/extensions/step/deck.step.js"></script>
+ <script src="deck.js/extensions/events/deck.events.js"></script>
+ <script src="deck.js/extensions/anim/deck.anim.js"></script>
+ <script src="deck.js/libs/jquerysvg/jquery.svg.min.js"></script>
+ <script src="deck.js/libs/jquerysvg/jquery.svganim.min.js"></script>
+ <script src="deck.js/extensions/svg/deck.svg.js"></script>
+
+
+ <!-- Deck.js options (advanced) -->
+ <script>$(function() {$.deck('.slide', {
+ // fitMarginX:100, fitMarginY:100, // uncomment to tune margin
+ // fitMode: "stretched", // uncomment to strech
+ dummy:""
+ });});
+ </script>
+
+ <!-- override some style here if needed (or in an external file) -->
+ <style type="text/css">
+ /* example */ .slide b {color: blue;}
+ /* example */ .deck-container > .slide {border: 1px solid green;}
+ /* example */ body.has-clones .deck-container {background: lightslategrey;}
+ /* example */ .deck-container .title-slide {border: 1px solid red; font-size: 70%}
+ </style>
+ </head>
+
+
+<body>
+This text should not be displayed if everything goes well: use left/right arrow keys to browse the presentation.<br/>
+
+<div class="deck-container">
+
+ <!-- this presentation uses smart syntax -->
+<section class="smart">
+ ==New Presentation With deck.js and Extensions==[title-slide]
+
+ =Hello=
+ * Hi, .....
+ * Todo
+ ** Write you presentation
+ ** <b>Rehearse a little</b>
+ * See also
+ ** <a href="http://home.heeere.com/tech-deckjs-ext.html">online samples</a>
+ ** <a href="deck.js/samples">local samples</a>
+
+ ==Thank you for your attention==[end-slide]
+
+</section>
+
+<!-- end of the presentation -->
+
+
+
+
+<!-- deck.hash snippet -->
+<a href="." title="Permalink to this slide" class="deck-permalink">#</a>
+<!-- deck.status snippet -->
+<p class="deck-status">
+ footer −
+ <span class="deck-status-current"></span>
+ /
+ <span class="deck-status-total"></span>
+</p>
+<!-- deck.goto snippet -->
+<form action="." method="get" class="goto-form">
+ <label for="goto-slide">Go to slide:</label>
+ <input type="text" name="slidenum" id="goto-slide" list="goto-datalist">
+ <datalist id="goto-datalist"></datalist>
+ <input type="submit" value="Go">
+</form>
+<!-- deck.navigation snippet -->
+<a href="#" class="deck-prev-link" title="Previous">&#8592;</a>
+<a href="#" class="deck-next-link" title="Next">&#8594;</a>
+<!-- deck.clone snippet: simple red box with top-left corner as cursor position -->
+<div class="clonepointer" style="position:absolute; width:20px; height:20px; background:red; z-index:10"></div>
+<!-- deck.clone snippet: simple green box with center as cursor position -->
+<div class="clonepointer" style="position:absolute; z-index:11"><div style="margin: -13px 0 0 -13px; width:18px; height:18px; border:4px solid green;"></div></div>
+
+
+
+
+</div> <!-- end of deck container -->
+
+</body>
+</html>
diff --git a/deck.js/extensions/clone/deck.clone.js b/deck.js/extensions/clone/deck.clone.js
new file mode 100644
index 0000000..847d8f8
--- /dev/null
+++ b/deck.js/extensions/clone/deck.clone.js
@@ -0,0 +1,127 @@
+/*!
+Deck JS - deck.clone
+Copyright (c) 2011 Remi BARRAQUAND
+Dual licensed under the MIT license and GPL license.
+https://github.com/imakewebthings/deck.js/blob/master/MIT-license.txt
+https://github.com/imakewebthings/deck.js/blob/master/GPL-license.txt
+*/
+
+/*
+This module provides a support for cloning the deck.
+*/
+
+(function($, deck, undefined) {
+ var $d = $(document);
+ var clones = new Array();
+
+ $.extend(true, $[deck].defaults, {
+ selectors: {
+ clonepointer: ".clonepointer"
+ },
+ classes: {
+ hasClones: 'has-clones'
+ },
+ keys: {
+ clone: 67 // c
+ }
+ });
+
+ var cleanClones = function() {
+ var opts = $[deck]('getOptions');
+ // remove closed windows
+ $.each(clones, function(index, clone) {
+ if (clone.closed()) {
+ clones.splice(index, 1); // remove element "index"
+ }
+ });
+ // tag/untag the current container depending on the presence of clones
+ if (clones.length > 0) {
+ $("body").addClass(opts.classes.hasClones);
+ } else {
+ $("body").removeClass(opts.classes.hasClones);
+ }
+ };
+ /*
+ jQuery.deck('addClone')
+
+ Create a clone of this window and add it to the clones list.
+ */
+ $[deck]('extend', 'addClone', function() {
+ clone = new DeckClone();
+ clones.push(clone);
+ cleanClones();
+ return clone;
+ });
+ $[deck]('extend', 'pointerAt', function(rx, ry) {
+ var opts = $[deck]('getOptions');
+ var r = $(".deck-current").get(0).getBoundingClientRect();
+ var x = r.left + r.width * rx;
+ var y = r.top + r.height * ry;
+ var pos = {left: x, top: y};
+ var current = $(".deck-current").get(0);
+ var pointers = $(opts.selectors.clonepointer);
+ if (pointers.get(0).parentNode != current) { // move them within the new slide if it changed
+ pointers.show().appendTo(".deck-current");
+ }
+ pointers.offset(pos);
+ });
+
+ /*
+ jQuery.deck('Init')
+ */
+ $d.bind('deck.init', function() {
+ var opts = $[deck]('getOptions');
+ var container = $[deck]('getContainer');
+
+ $(opts.selectors.clonepointer).hide();
+
+ /* Bind key events */
+ $d.unbind('keydown.deckclone').bind('keydown.deckclone', function(e) {
+ if (e.which === opts.keys.clone || $.inArray(e.which, opts.keys.clone) > -1) {
+ $[deck]('addClone');
+ e.preventDefault();
+ }
+ });
+ })
+ /* Update current slide number with each change event */
+ .bind('deck.change', function(e, from, to) {
+ var opts = $[deck]('getOptions');
+ var slideTo = $[deck]('getSlide', to);
+ var container = $[deck]('getContainer');
+ cleanClones();
+ $.each(clones, function(index, clone) {
+ clone.deck('go', to);
+ });
+ })
+ /* Do the animations locally */
+ .bind('deck.step', function(e, delta) {
+ cleanClones();
+ $.each(clones, function(index, clone) {
+ if (delta == -1) clone.deck('stepPrev');
+ else if (delta == 1) clone.deck('stepNext');
+ });
+ })
+ /* Replicate mouse cursor */
+ .bind('mousemove', function(e) {
+ var r = $(".deck-current").get(0).getBoundingClientRect();
+ var x = (e.clientX - r.left) / r.width;
+ var y = (e.clientY - r.top) / r.height;
+ cleanClones();
+ $.each(clones, function(index, clone) {
+ clone.deck('pointerAt', x, y);
+ });
+ });
+
+ /*
+ Simple Clone manager (must be improved, by for instance adding cloning
+ option e.g. propagate change, etc.)
+ */
+ var DeckClone = function() {
+ var clone = window.open(window.location);
+ this.closed = function() {return clone.closed;}
+ this.deck = function() {
+ if (clone.closed) return;
+ if (clone['$']) clone['$'].deck.apply(clone['$'], arguments)
+ }
+ }
+})(jQuery, 'deck'); \ No newline at end of file
diff --git a/deck.js/extensions/events/README.md b/deck.js/extensions/events/README.md
new file mode 100644
index 0000000..22d003e
--- /dev/null
+++ b/deck.js/extensions/events/README.md
@@ -0,0 +1,64 @@
+# deck.events.js
+
+An extension for [deck.js][] allowing you to execute Javascript when a
+ slide becomes/leaves the current, next, or previous slide.
+
+## Requirements
+
+[deck.js][]
+
+## Events
+
+Each event is triggered "on" the slide on which the event occurs (see _Example_)
+ and given a single argument -- the direction (see _Direction_)
+
+* **deck.becameCurrent**: Triggered when a slide becomes the current one
+ (`to` in `deck.change`).
+* **deck.lostCurrent**: The slide is no longer "current"
+ (`from` in `deck.change`).
+* **deck.becamePrevious**: The slide (by order) just before the current slide.
+ (`to - 1` in `deck.change`).
+* **deck.becameNext**: The slide (by order) just after the current slide.
+ (`to + 1` in `deck.change`).
+* **deck.lostPrevious**: The slide (by order) just before the last current slide.
+ (`from - 1` in `deck.change`).
+* **deck.lostNext**: The slide (by order) just after the last current slide.
+ (`from + 1` in `deck.change`).
+
+
+## Direction
+
+Each event is given a direction that helps determine whether the user is
+ moving forward or backward in the slide stack. It is provided as an argument
+ for the event and can be either `forward` or `reverse`. Essentially:
+
+```
+ if(from < to){
+ direction = "forward";
+ }
+ else{
+ direction = "reverse";
+ }
+```
+
+
+## Example
+
+If you put a placeholder slide `<div id="showGraph" class="slide"></div>` into
+ your source, this event will display a Javascript graph when you visit the
+ slide (forward) and remove it if you hit the back arrow and return to
+ the slide.
+
+```
+$("#showGraph").bind('deck.becameCurrent', function(ev, direction) {
+ if(direction == "forward"){
+ animateGraphIn();
+ }
+ else{
+ animateGraphOut();
+ }
+});
+```
+
+
+[deck.js]: https://github.com/imakewebthings/deck.js
diff --git a/deck.js/extensions/events/deck.events.js b/deck.js/extensions/events/deck.events.js
new file mode 100644
index 0000000..e00d28d
--- /dev/null
+++ b/deck.js/extensions/events/deck.events.js
@@ -0,0 +1,23 @@
+(function($, deck, undefined) {
+ $(document).bind('deck.change', function(e, from, to) {
+ var $prev = $[deck]('getSlide', to-1),
+ $next = $[deck]('getSlide', to+1),
+ $oldprev = $[deck]('getSlide', from-1),
+ $oldnext = $[deck]('getSlide', from+1);
+
+ var direction = "forward";
+ if(from > to){
+ direction = "reverse";
+ }
+
+ $[deck]('getSlide', to).trigger('deck.becameCurrent', [direction, from, to]);
+ $[deck]('getSlide', from).trigger('deck.lostCurrent', [direction, from, to]);
+
+ $prev && $prev.trigger('deck.becamePrevious', [direction, from, to]);
+ $next && $next.trigger('deck.becameNext', [direction, from, to]);
+
+ $oldprev && $oldprev.trigger('deck.lostPrevious', [direction, from, to]);
+ $oldnext && $oldnext.trigger('deck.lostNext', [direction, from, to]);
+ });
+})(jQuery, 'deck');
+
diff --git a/deck.js/extensions/fit/deck.fit-fs.css b/deck.js/extensions/fit/deck.fit-fs.css
new file mode 100644
index 0000000..fd58665
--- /dev/null
+++ b/deck.js/extensions/fit/deck.fit-fs.css
@@ -0,0 +1,14 @@
+
+.deck-container {
+ width: 100%; height: 100%; /* to get a proper filling of the parent */
+ margin: 0; padding: 0; /* any margin is handled by the parent or the fit extension */
+ position: absolute;
+ left:0; top:0; width:100%; height:100%;
+ border: 0;
+}
+.deck-container>.slide {
+ width: 100%; height: 100%; /* to get a proper filling of the parent */
+ min-width:0; min-height:0; /* undoing some hurting style in the defaults of deck.js */
+ overflow: hidden; /* don't show slides outside of their box */
+ /* margin:0; padding:0; /* remove possible margins */
+}
diff --git a/deck.js/extensions/fit/deck.fit.js b/deck.js/extensions/fit/deck.fit.js
new file mode 100644
index 0000000..ea71ef9
--- /dev/null
+++ b/deck.js/extensions/fit/deck.fit.js
@@ -0,0 +1,171 @@
+/*!
+ Deck JS - deck.fit
+ Copyright (c) 2012 Rémi Emonet
+ Dual licensed under the MIT license and GPL license.
+ https://github.com/imakewebthings/deck.js/blob/master/MIT-license.txt
+ https://github.com/imakewebthings/deck.js/blob/master/GPL-license.txt
+*/
+
+/*
+ This extension provides a way of scaling the slides to fit the slide container.
+ A "design size" is used to do global scaling of all slides in the same way.
+ The default design size is 800x600.
+*/
+(function($, deck, window, undefined) {
+ var $d = $(document),
+ $w = $(window),
+ timer, // Timeout id for debouncing
+ rootSlides,
+
+ /*
+ Internal function to do all the dirty work of scaling the slides.
+ */
+ scaleDeck = function() {
+ var opts = $[deck]('getOptions');
+ var addMarginX = opts.fitMarginX * 2;
+ var addMarginY = opts.fitMarginY * 2;
+ var fitMode = opts.fitMode;
+ var sdw = opts.designWidth;
+ var sdh = opts.designHeight;
+ var $container = $[deck]('getContainer');
+ var scaleX = $container.hasClass(opts.classes.globalscale) ? $container.innerWidth() / (sdw+addMarginX) : 1;
+ var scaleY = $container.hasClass(opts.classes.globalscale) ? $container.innerHeight() / (sdh+addMarginY) : 1;
+ var truescaleX = $container.hasClass(opts.classes.globalscale) ? $container.innerWidth() / (sdw) : 1;
+ var truescaleY = $container.hasClass(opts.classes.globalscale) ? $container.innerHeight() / (sdh) : 1;
+ var scale = scaleX < scaleY ? scaleX : scaleY;
+ var rootSlides = [];
+ var slideTest = $.map([opts.classes.before, opts.classes.previous, opts.classes.current, opts.classes.next, opts.classes.after],
+ function(el, i) {return '.' + el;}).join(', ');
+
+ $.each($[deck]('getSlides'), function(i, $el) {
+ if (!$el.parentsUntil(opts.selectors.container).length) {
+ rootSlides.push($el);
+ }
+ });
+ $.each(rootSlides, function(i, $slide) {
+ $slide.width(sdw);
+ $slide.height(sdh);
+ $.each('Webkit Moz O ms Khtml'.split(' '), function(i, prefix) {
+ if (scale == 1) {
+ $slide.css(prefix + 'Transform', '');
+ } else {
+ if (fitMode == "left top" || fitMode == "top left") {
+ // ok align left/top (ok with the percents)
+ $slide.css(prefix + 'Transform', 'translate(-50%,-50%) scale(' + scale + ' , ' + scale + ') translate(50%,50%) translate('+(addMarginX/2)+'px,'+(addMarginY/2)+'px)');
+ } else if (fitMode == "center middle") {
+ // ok align center/middle
+ $slide.css(prefix + 'Transform', 'translate(-50%,-50%) scale(' + scale + ' , ' + scale + ') translate(50%, 50%) translate('+($container.innerWidth()/2/scale - sdw/2)+'px,'+($container.innerHeight()/2/scale - sdh/2)+'px)');
+ } else if (fitMode == "right bottom" || fitMode == "bottom right") {
+ // ok align right/bottom
+ $slide.css(prefix + 'Transform', 'translate(-50%,-50%) scale(' + scale + ' , ' + scale + ') translate(50%, 50%) translate('+($container.innerWidth()/scale - sdw - addMarginX/2)+'px,'+($container.innerHeight()/scale - sdh - addMarginY/2)+'px)');
+ } else if (fitMode == "stretched") {
+ // ok stretched (with respect of the margin, i.e., it is center/middle)
+ $slide.css(prefix + 'Transform', 'scale(' + scaleX + ' , ' + scaleY + ') translate('+(($container.innerWidth()-sdw)/2/scaleX)+'px,'+(($container.innerHeight()-sdh)/2/scaleY)+'px)');
+ }
+ }
+ });
+ });
+
+ }
+
+ /*
+ Extends defaults/options.
+
+ options.designWidth
+ Defaults to 800. You may instead specify a width as a number
+ of px and all slides will be scaled in the same way, considering their
+ size is the provided one.
+
+ options.designHeight
+ Defaults to 600. You may instead specify a height as a number
+ of px and all slides will be scaled in the same way, considering their
+ size is the provided one.
+
+ options.fitMode
+ How to adapt the slide to the container.
+ Only the following combinations are available for now:
+ "center middle", "top left", "bottom right", "stretched"
+
+ options.fitMarginX
+ options.fitMarginY
+ Defaults to 5. Adds some margin in design space units.
+ E.g., if the designe width is 800 and the margin is 5, the slide will be
+ 810 pixel wide before rescaling.
+
+ options.scaleDebounce
+ Scaling on the browser resize event is debounced. This number is the
+ threshold in milliseconds. You can learn more about debouncing here:
+ http://unscriptable.com/index.php/2009/03/20/debouncing-javascript-methods/
+
+ */
+ $.extend(true, $[deck].defaults, {
+ classes: {
+ globalscale: 'deck-globalscale'
+ },
+ keys: {
+ scale: 83 // s
+ },
+
+ designWidth: 800,
+ designHeight: 600,
+ fitMode: "center middle",
+ fitMarginX: 5,
+ fitMarginY: 5,
+ scaleDebounce: 200
+ });
+
+ /*
+ jQuery.deck('disableScale')
+
+ Disables scaling and removes the scale class from the deck container.
+ */
+ $[deck]('extend', 'disableScale', function() {
+ $[deck]('getContainer').removeClass($[deck]('getOptions').classes.globalscale);
+ scaleDeck();
+ });
+
+ /*
+ jQuery.deck('enableScale')
+
+ Enables scaling and adds the scale class to the deck container.
+ */
+ $[deck]('extend', 'enableScale', function() {
+ $[deck]('getContainer').addClass($[deck]('getOptions').classes.globalscale);
+ scaleDeck();
+ });
+
+ /*
+ jQuery.deck('toggleScale')
+
+ Toggles between enabling and disabling scaling.
+ */
+ $[deck]('extend', 'toggleScale', function() {
+ var $c = $[deck]('getContainer');
+ $[deck]($c.hasClass($[deck]('getOptions').classes.globalscale) ?
+ 'disableScale' : 'enableScale');
+ });
+
+ $d.bind('deck.init', function() {
+ var opts = $[deck]('getOptions');
+
+ // Debounce the resize scaling
+ $w.unbind('resize.deckscale').bind('resize.deckscale', function() {
+ window.clearTimeout(timer);
+ timer = window.setTimeout(scaleDeck, opts.scaleDebounce);
+ })
+ // Scale once on load, in case images or something change layout
+ .unbind('load.deckscale').bind('load.deckscale', scaleDeck);
+
+ // Bind key events
+ $d.unbind('keydown.deckscale').bind('keydown.deckscale', function(e) {
+ if (e.which === opts.keys.scale || $.inArray(e.which, opts.keys.scale) > -1) {
+ $[deck]('toggleScale');
+ e.preventDefault();
+ }
+ });
+
+ // Enable scale on init
+ $[deck]('enableScale');
+ });
+})(jQuery, 'deck', this);
+
diff --git a/deck.js/extensions/goto/deck.goto.css b/deck.js/extensions/goto/deck.goto.css
new file mode 100644
index 0000000..108e4f9
--- /dev/null
+++ b/deck.js/extensions/goto/deck.goto.css
@@ -0,0 +1,41 @@
+.deck-container .goto-form {
+ position: absolute;
+ z-index: 3;
+ bottom: 10px;
+ left: 50%;
+ height: 1.75em;
+ margin: 0 0 0 -9.125em;
+ line-height: 1.75em;
+ padding: 0.625em;
+ display: none;
+ background: #ccc;
+ overflow: hidden;
+}
+.borderradius .deck-container .goto-form {
+ -webkit-border-radius: 10px;
+ -moz-border-radius: 10px;
+ border-radius: 10px;
+}
+.deck-container .goto-form label {
+ font-weight: bold;
+}
+.deck-container .goto-form label, .deck-container .goto-form input {
+ display: inline-block;
+ font-family: inherit;
+}
+
+.deck-goto .goto-form {
+ display: block;
+}
+
+#goto-slide {
+ width: 8.375em;
+ margin: 0 0.625em;
+ height: 1.4375em;
+}
+
+@media print {
+ .goto-form, #goto-slide {
+ display: none !important;
+ }
+}
diff --git a/deck.js/extensions/goto/deck.goto.html b/deck.js/extensions/goto/deck.goto.html
new file mode 100644
index 0000000..e3b6a18
--- /dev/null
+++ b/deck.js/extensions/goto/deck.goto.html
@@ -0,0 +1,7 @@
+<!-- Place the following snippet at the bottom of the deck container. -->
+<form action="." method="get" class="goto-form">
+ <label for="goto-slide">Go to slide:</label>
+ <input type="text" name="slidenum" id="goto-slide" list="goto-datalist">
+ <datalist id="goto-datalist"></datalist>
+ <input type="submit" value="Go">
+</form> \ No newline at end of file
diff --git a/deck.js/extensions/goto/deck.goto.js b/deck.js/extensions/goto/deck.goto.js
new file mode 100644
index 0000000..eedba10
--- /dev/null
+++ b/deck.js/extensions/goto/deck.goto.js
@@ -0,0 +1,170 @@
+/*!
+Deck JS - deck.goto
+Copyright (c) 2011 Caleb Troughton
+Dual licensed under the MIT license and GPL license.
+https://github.com/imakewebthings/deck.js/blob/master/MIT-license.txt
+https://github.com/imakewebthings/deck.js/blob/master/GPL-license.txt
+*/
+
+/*
+This module adds the necessary methods and key bindings to show and hide a form
+for jumping to any slide number/id in the deck (and processes that form
+accordingly). The form-showing state is indicated by the presence of a class on
+the deck container.
+*/
+(function($, deck, undefined) {
+ var $d = $(document);
+
+ /*
+ Extends defaults/options.
+
+ options.classes.goto
+ This class is added to the deck container when showing the Go To Slide
+ form.
+
+ options.selectors.gotoDatalist
+ The element that matches this selector is the datalist element that will
+ be populated with options for each of the slide ids. In browsers that
+ support the datalist element, this provides a drop list of slide ids to
+ aid the user in selecting a slide.
+
+ options.selectors.gotoForm
+ The element that matches this selector is the form that is submitted
+ when a user hits enter after typing a slide number/id in the gotoInput
+ element.
+
+ options.selectors.gotoInput
+ The element that matches this selector is the text input field for
+ entering a slide number/id in the Go To Slide form.
+
+ options.keys.goto
+ The numeric keycode used to show the Go To Slide form.
+
+ options.countNested
+ If false, only top level slides will be counted when entering a
+ slide number.
+ */
+ $.extend(true, $[deck].defaults, {
+ classes: {
+ goto: 'deck-goto'
+ },
+
+ selectors: {
+ gotoDatalist: '#goto-datalist',
+ gotoForm: '.goto-form',
+ gotoInput: '#goto-slide'
+ },
+
+ keys: {
+ goto: 71 // g
+ },
+
+ countNested: true
+ });
+
+ /*
+ jQuery.deck('showGoTo')
+
+ Shows the Go To Slide form by adding the class specified by the goto class
+ option to the deck container.
+ */
+ $[deck]('extend', 'showGoTo', function() {
+ $[deck]('getContainer').addClass($[deck]('getOptions').classes.goto);
+ $($[deck]('getOptions').selectors.gotoInput).focus();
+ });
+
+ /*
+ jQuery.deck('hideGoTo')
+
+ Hides the Go To Slide form by removing the class specified by the goto class
+ option from the deck container.
+ */
+ $[deck]('extend', 'hideGoTo', function() {
+ $($[deck]('getOptions').selectors.gotoInput).blur();
+ $[deck]('getContainer').removeClass($[deck]('getOptions').classes.goto);
+ });
+
+ /*
+ jQuery.deck('toggleGoTo')
+
+ Toggles between showing and hiding the Go To Slide form.
+ */
+ $[deck]('extend', 'toggleGoTo', function() {
+ $[deck]($[deck]('getContainer').hasClass($[deck]('getOptions').classes.goto) ? 'hideGoTo' : 'showGoTo');
+ });
+
+ $d.bind('deck.init', function() {
+ var opts = $[deck]('getOptions'),
+ $datalist = $(opts.selectors.gotoDatalist),
+ slideTest = $.map([
+ opts.classes.before,
+ opts.classes.previous,
+ opts.classes.current,
+ opts.classes.next,
+ opts.classes.after
+ ], function(el, i) {
+ return '.' + el;
+ }).join(', '),
+ rootCounter = 1;
+
+ // Bind key events
+ $d.unbind('keydown.deckgoto').bind('keydown.deckgoto', function(e) {
+ var key = $[deck]('getOptions').keys.goto;
+
+ if (e.which === key || $.inArray(e.which, key) > -1) {
+ e.preventDefault();
+ $[deck]('toggleGoTo');
+ }
+ });
+
+ /* Populate datalist and work out countNested*/
+ $.each($[deck]('getSlides'), function(i, $slide) {
+ var id = $slide.attr('id'),
+ $parentSlides = $slide.parentsUntil(opts.selectors.container, slideTest);
+
+ if (id) {
+ $datalist.append('<option value="' + id + '">');
+ }
+
+ if ($parentSlides.length) {
+ $slide.removeData('rootIndex');
+ }
+ else if (!opts.countNested) {
+ $slide.data('rootIndex', rootCounter);
+ ++rootCounter;
+ }
+ });
+
+ // Process form submittal, go to the slide entered
+ $(opts.selectors.gotoForm)
+ .unbind('submit.deckgoto')
+ .bind('submit.deckgoto', function(e) {
+ var $field = $($[deck]('getOptions').selectors.gotoInput),
+ ndx = parseInt($field.val(), 10);
+
+ if (!$[deck]('getOptions').countNested) {
+ if (ndx >= rootCounter) return false;
+ $.each($[deck]('getSlides'), function(i, $slide) {
+ if ($slide.data('rootIndex') === ndx) {
+ ndx = i + 1;
+ return false;
+ }
+ });
+ }
+
+ $[deck]('go', isNaN(ndx) ? $field.val() : ndx - 1);
+ $[deck]('hideGoTo');
+ $field.val('');
+
+ e.preventDefault();
+ });
+
+ // Dont let keys in the input trigger deck actions
+ $(opts.selectors.gotoInput)
+ .unbind('keydown.deckgoto')
+ .bind('keydown.deckgoto', function(e) {
+ e.stopPropagation();
+ });
+ });
+})(jQuery, 'deck');
+
diff --git a/deck.js/extensions/goto/deck.goto.scss b/deck.js/extensions/goto/deck.goto.scss
new file mode 100755
index 0000000..9170d5d
--- /dev/null
+++ b/deck.js/extensions/goto/deck.goto.scss
@@ -0,0 +1,46 @@
+.deck-container {
+ .goto-form {
+ position:absolute;
+ z-index:3;
+ bottom:10px;
+ left:50%;
+ height:1.75em;
+ margin:0 0 0 -9.125em;
+ line-height:1.75em;
+ padding:0.625em;
+ display:none;
+ background:#ccc;
+ overflow:hidden;
+
+ .borderradius & {
+ -webkit-border-radius:10px;
+ -moz-border-radius:10px;
+ border-radius:10px;
+ }
+
+ label {
+ font-weight:bold;
+ }
+
+ label, input {
+ display:inline-block;
+ font-family:inherit;
+ }
+ }
+}
+
+.deck-goto .goto-form {
+ display:block;
+}
+
+#goto-slide {
+ width:8.375em;
+ margin:0 0.625em;
+ height:1.4375em;
+}
+
+@media print {
+ .goto-form, #goto-slide {
+ display:none !important;
+ }
+} \ No newline at end of file
diff --git a/deck.js/extensions/hash/deck.hash.css b/deck.js/extensions/hash/deck.hash.css
new file mode 100644
index 0000000..28f0732
--- /dev/null
+++ b/deck.js/extensions/hash/deck.hash.css
@@ -0,0 +1,13 @@
+.deck-container .deck-permalink {
+ display: none;
+ position: absolute;
+ z-index: 4;
+ bottom: 30px;
+ right: 0;
+ width: 48px;
+ text-align: center;
+}
+
+.no-history .deck-container:hover .deck-permalink {
+ display: block;
+}
diff --git a/deck.js/extensions/hash/deck.hash.html b/deck.js/extensions/hash/deck.hash.html
new file mode 100644
index 0000000..102579c
--- /dev/null
+++ b/deck.js/extensions/hash/deck.hash.html
@@ -0,0 +1,2 @@
+<!-- Place the following snippet at the bottom of the deck container. -->
+<a href="." title="Permalink to this slide" class="deck-permalink">#</a> \ No newline at end of file
diff --git a/deck.js/extensions/hash/deck.hash.js b/deck.js/extensions/hash/deck.hash.js
new file mode 100644
index 0000000..879bc62
--- /dev/null
+++ b/deck.js/extensions/hash/deck.hash.js
@@ -0,0 +1,142 @@
+/*!
+Deck JS - deck.hash
+Copyright (c) 2011 Caleb Troughton
+Dual licensed under the MIT license and GPL license.
+https://github.com/imakewebthings/deck.js/blob/master/MIT-license.txt
+https://github.com/imakewebthings/deck.js/blob/master/GPL-license.txt
+*/
+
+/*
+This module adds deep linking to individual slides, enables internal links
+to slides within decks, and updates the address bar with the hash as the user
+moves through the deck. A permalink anchor is also updated. Standard themes
+hide this link in browsers that support the History API, and show it for
+those that do not. Slides that do not have an id are assigned one according to
+the hashPrefix option. In addition to the on-slide container state class
+kept by core, this module adds an on-slide state class that uses the id of each
+slide.
+*/
+(function ($, deck, window, undefined) {
+ var $d = $(document),
+ $window = $(window),
+
+ /* Collection of internal fragment links in the deck */
+ $internals,
+
+ /*
+ Internal only function. Given a string, extracts the id from the hash,
+ matches it to the appropriate slide, and navigates there.
+ */
+ goByHash = function(str) {
+ var id = str.substr(str.indexOf("#") + 1),
+ slides = $[deck]('getSlides');
+
+ $.each(slides, function(i, $el) {
+ if ($el.attr('id') === id) {
+ $[deck]('go', i);
+ return false;
+ }
+ });
+
+ // If we don't set these to 0 the container scrolls due to hashchange
+ $[deck]('getContainer').scrollLeft(0).scrollTop(0);
+ };
+
+ /*
+ Extends defaults/options.
+
+ options.selectors.hashLink
+ The element matching this selector has its href attribute updated to
+ the hash of the current slide as the user navigates through the deck.
+
+ options.hashPrefix
+ Every slide that does not have an id is assigned one at initialization.
+ Assigned ids take the form of hashPrefix + slideIndex, e.g., slide-0,
+ slide-12, etc.
+
+ options.preventFragmentScroll
+ When deep linking to a hash of a nested slide, this scrolls the deck
+ container to the top, undoing the natural browser behavior of scrolling
+ to the document fragment on load.
+ */
+ $.extend(true, $[deck].defaults, {
+ selectors: {
+ hashLink: '.deck-permalink'
+ },
+
+ hashPrefix: 'slide-',
+ preventFragmentScroll: true
+ });
+
+
+ $d.bind('deck.init', function() {
+ var opts = $[deck]('getOptions');
+ $internals = $(),
+ slides = $[deck]('getSlides');
+
+ $.each(slides, function(i, $el) {
+ var hash;
+
+ /* Hand out ids to the unfortunate slides born without them */
+ if (!$el.attr('id') || $el.data('deckAssignedId') === $el.attr('id')) {
+ $el.attr('id', opts.hashPrefix + i);
+ $el.data('deckAssignedId', opts.hashPrefix + i);
+ }
+
+ hash ='#' + $el.attr('id');
+
+ /* Deep link to slides on init */
+ if (hash === window.location.hash) {
+ setTimeout(function() {$[deck]('go', i)}, 1);
+ }
+
+ /* Add internal links to this slide */
+ $internals = $internals.add('a[href="' + hash + '"]');
+ });
+
+ if (!Modernizr.hashchange) {
+ /* Set up internal links using click for the poor browsers
+ without a hashchange event. */
+ $internals.unbind('click.deckhash').bind('click.deckhash', function(e) {
+ goByHash($(this).attr('href'));
+ });
+ }
+
+ /* Set up first id container state class */
+ if (slides.length) {
+ $[deck]('getContainer').addClass(opts.classes.onPrefix + $[deck]('getSlide').attr('id'));
+ };
+ })
+ /* Update permalink, address bar, and state class on a slide change */
+ .bind('deck.change', function(e, from, to) {
+ var hash = '#' + $[deck]('getSlide', to).attr('id'),
+ hashPath = window.location.href.replace(/#.*/, '') + hash,
+ opts = $[deck]('getOptions'),
+ osp = opts.classes.onPrefix,
+ $c = $[deck]('getContainer');
+
+ $c.removeClass(osp + $[deck]('getSlide', from).attr('id'));
+ $c.addClass(osp + $[deck]('getSlide', to).attr('id'));
+
+ $(opts.selectors.hashLink).attr('href', hashPath);
+ if (Modernizr.history) {
+ window.history.replaceState({}, "", hashPath);
+ }
+ });
+
+ /* Deals with internal links in modern browsers */
+ $window.bind('hashchange.deckhash', function(e) {
+ if (e.originalEvent && e.originalEvent.newURL) {
+ goByHash(e.originalEvent.newURL);
+ }
+ else {
+ goByHash(window.location.hash);
+ }
+ })
+ /* Prevent scrolling on deep links */
+ .bind('load', function() {
+ if ($[deck]('getOptions').preventFragmentScroll) {
+ $[deck]('getContainer').scrollLeft(0).scrollTop(0);
+ }
+ });
+})(jQuery, 'deck', this); \ No newline at end of file
diff --git a/deck.js/extensions/hash/deck.hash.scss b/deck.js/extensions/hash/deck.hash.scss
new file mode 100644
index 0000000..03b412d
--- /dev/null
+++ b/deck.js/extensions/hash/deck.hash.scss
@@ -0,0 +1,15 @@
+.deck-container {
+ .deck-permalink {
+ display:none;
+ position:absolute;
+ z-index:4;
+ bottom:30px;
+ right:0;
+ width:48px;
+ text-align:center;
+ }
+}
+
+.no-history .deck-container:hover .deck-permalink {
+ display:block;
+} \ No newline at end of file
diff --git a/deck.js/extensions/menu/deck.menu.css b/deck.js/extensions/menu/deck.menu.css
new file mode 100644
index 0000000..c664a3f
--- /dev/null
+++ b/deck.js/extensions/menu/deck.menu.css
@@ -0,0 +1,47 @@
+.deck-menu .slide {
+ background: #eee;
+ position: relative;
+ left: 0;
+ top: 0;
+ visibility: visible;
+ cursor: pointer;
+}
+.no-csstransforms .deck-menu > .slide {
+ float: left;
+ width: 22%;
+ height: 22%;
+ min-height: 0;
+ margin: 1%;
+ font-size: 0.22em;
+ overflow: hidden;
+ padding: 0 0.5%;
+}
+.csstransforms .deck-menu > .slide {
+ -webkit-transform: scale(0.22) !important;
+ -moz-transform: scale(0.22) !important;
+ -o-transform: scale(0.22) !important;
+ -ms-transform: scale(0.22) !important;
+ transform: scale(0.22) !important;
+ -webkit-transform-origin: 0 0;
+ -moz-transform-origin: 0 0;
+ -o-transform-origin: 0 0;
+ -ms-transform-origin: 0 0;
+ transform-origin: 0 0;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ width: 100%;
+ height: 100%;
+ overflow: hidden;
+ padding: 0 48px;
+ margin: 12px;
+}
+.deck-menu iframe, .deck-menu img, .deck-menu video {
+ max-width: 100%;
+}
+.deck-menu .deck-current, .no-touch .deck-menu .slide:hover {
+ background: #ddf;
+}
+.deck-menu.deck-container:hover .deck-prev-link, .deck-menu.deck-container:hover .deck-next-link {
+ display: none;
+}
diff --git a/deck.js/extensions/menu/deck.menu.js b/deck.js/extensions/menu/deck.menu.js
new file mode 100644
index 0000000..743cf77
--- /dev/null
+++ b/deck.js/extensions/menu/deck.menu.js
@@ -0,0 +1,187 @@
+/*!
+Deck JS - deck.menu
+Copyright (c) 2011 Caleb Troughton
+Dual licensed under the MIT license and GPL license.
+https://github.com/imakewebthings/deck.js/blob/master/MIT-license.txt
+https://github.com/imakewebthings/deck.js/blob/master/GPL-license.txt
+*/
+
+/*
+This module adds the methods and key binding to show and hide a menu of all
+slides in the deck. The deck menu state is indicated by the presence of a class
+on the deck container.
+*/
+(function($, deck, undefined) {
+ var $d = $(document),
+ rootSlides; // Array of top level slides
+
+ /*
+ Extends defaults/options.
+
+ options.classes.menu
+ This class is added to the deck container when showing the slide menu.
+
+ options.keys.menu
+ The numeric keycode used to toggle between showing and hiding the slide
+ menu.
+
+ options.touch.doubletapWindow
+ Two consecutive touch events within this number of milliseconds will
+ be considered a double tap, and will toggle the menu on touch devices.
+ */
+ $.extend(true, $[deck].defaults, {
+ classes: {
+ menu: 'deck-menu'
+ },
+
+ keys: {
+ menu: 77 // m
+ },
+
+ touch: {
+ doubletapWindow: 400
+ }
+ });
+
+ /*
+ jQuery.deck('showMenu')
+
+ Shows the slide menu by adding the class specified by the menu class option
+ to the deck container.
+ */
+ $[deck]('extend', 'showMenu', function() {
+ var $c = $[deck]('getContainer'),
+ opts = $[deck]('getOptions');
+
+ if ($c.hasClass(opts.classes.menu)) return;
+
+ // Hide through loading class to short-circuit transitions (perf)
+ $c.addClass([opts.classes.loading, opts.classes.menu].join(' '));
+
+ /* Forced to do this in JS until CSS learns second-grade math. Save old
+ style value for restoration when menu is hidden. */
+ if (Modernizr.csstransforms) {
+ $.each(rootSlides, function(i, $slide) {
+ $slide.data('oldStyle', $slide.attr('style'));
+ $slide.css({
+ 'position': 'absolute',
+ 'left': ((i % 4) * 25) + '%',
+ 'top': (Math.floor(i / 4) * 25) + '%'
+ });
+ });
+ }
+
+ // Need to ensure the loading class renders first, then remove
+ window.setTimeout(function() {
+ $c.removeClass(opts.classes.loading)
+ .scrollTop($[deck]('getSlide').offset().top);
+ }, 0);
+ });
+
+ /*
+ jQuery.deck('hideMenu')
+
+ Hides the slide menu by removing the class specified by the menu class
+ option from the deck container.
+ */
+ $[deck]('extend', 'hideMenu', function() {
+ var $c = $[deck]('getContainer'),
+ opts = $[deck]('getOptions');
+
+ if (!$c.hasClass(opts.classes.menu)) return;
+
+ $c.removeClass(opts.classes.menu);
+ $c.addClass(opts.classes.loading);
+
+ /* Restore old style value */
+ if (Modernizr.csstransforms) {
+ $.each(rootSlides, function(i, $slide) {
+ var oldStyle = $slide.data('oldStyle');
+
+ $slide.attr('style', oldStyle ? oldStyle : '');
+ });
+ }
+
+ window.setTimeout(function() {
+ $c.removeClass(opts.classes.loading).scrollTop(0);
+ }, 0);
+ });
+
+ /*
+ jQuery.deck('toggleMenu')
+
+ Toggles between showing and hiding the slide menu.
+ */
+ $[deck]('extend', 'toggleMenu', function() {
+ $[deck]('getContainer').hasClass($[deck]('getOptions').classes.menu) ?
+ $[deck]('hideMenu') : $[deck]('showMenu');
+ });
+
+ $d.bind('deck.init', function() {
+ var opts = $[deck]('getOptions'),
+ touchEndTime = 0,
+ currentSlide,
+ slideTest = $.map([
+ opts.classes.before,
+ opts.classes.previous,
+ opts.classes.current,
+ opts.classes.next,
+ opts.classes.after
+ ], function(el, i) {
+ return '.' + el;
+ }).join(', ');
+
+ // Build top level slides array
+ rootSlides = [];
+ $.each($[deck]('getSlides'), function(i, $el) {
+ if (!$el.parentsUntil(opts.selectors.container, slideTest).length) {
+ rootSlides.push($el);
+ }
+ });
+
+ // Bind key events
+ $d.unbind('keydown.deckmenu').bind('keydown.deckmenu', function(e) {
+ if (e.which === opts.keys.menu || $.inArray(e.which, opts.keys.menu) > -1) {
+ $[deck]('toggleMenu');
+ e.preventDefault();
+ }
+ });
+
+ // Double tap to toggle slide menu for touch devices
+ $[deck]('getContainer').unbind('touchstart.deckmenu').bind('touchstart.deckmenu', function(e) {
+ currentSlide = $[deck]('getSlide');
+ })
+ .unbind('touchend.deckmenu').bind('touchend.deckmenu', function(e) {
+ var now = Date.now();
+
+ // Ignore this touch event if it caused a nav change (swipe)
+ if (currentSlide !== $[deck]('getSlide')) return;
+
+ if (now - touchEndTime < opts.touch.doubletapWindow) {
+ $[deck]('toggleMenu');
+ e.preventDefault();
+ }
+ touchEndTime = now;
+ });
+
+ // Selecting slides from the menu
+ $.each($[deck]('getSlides'), function(i, $s) {
+ $s.unbind('click.deckmenu').bind('click.deckmenu', function(e) {
+ if (!$[deck]('getContainer').hasClass(opts.classes.menu)) return;
+
+ $[deck]('go', i);
+ $[deck]('hideMenu');
+ e.stopPropagation();
+ e.preventDefault();
+ });
+ });
+ })
+ .bind('deck.change', function(e, from, to) {
+ var container = $[deck]('getContainer');
+
+ if (container.hasClass($[deck]('getOptions').classes.menu)) {
+ container.scrollTop($[deck]('getSlide', to).offset().top);
+ }
+ });
+})(jQuery, 'deck');
+
diff --git a/deck.js/extensions/menu/deck.menu.scss b/deck.js/extensions/menu/deck.menu.scss
new file mode 100755
index 0000000..0bd576d
--- /dev/null
+++ b/deck.js/extensions/menu/deck.menu.scss
@@ -0,0 +1,58 @@
+.deck-menu {
+ .slide {
+ background:#eee;
+ position:relative;
+ left:0;
+ top:0;
+ visibility:visible;
+ cursor:pointer;
+ }
+
+ > .slide {
+ .no-csstransforms & {
+ float:left;
+ width:22%;
+ height:22%;
+ min-height:0;
+ margin:1%;
+ font-size:0.22em;
+ overflow:hidden;
+ padding:0 0.5%;
+ }
+
+ .csstransforms & {
+ -webkit-transform:scale(.22) !important;
+ -moz-transform:scale(.22) !important;
+ -o-transform:scale(.22) !important;
+ -ms-transform:scale(.22) !important;
+ transform:scale(.22) !important;
+ -webkit-transform-origin:0 0;
+ -moz-transform-origin:0 0;
+ -o-transform-origin:0 0;
+ -ms-transform-origin:0 0;
+ transform-origin:0 0;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ width:100%;
+ height:100%;
+ overflow:hidden;
+ padding:0 48px;
+ margin:12px;
+ }
+ }
+
+ iframe, img, video {
+ max-width:100%;
+ }
+
+ .deck-current, .no-touch & .slide:hover {
+ background:#ddf;
+ }
+
+ &.deck-container:hover {
+ .deck-prev-link, .deck-next-link {
+ display:none;
+ }
+ }
+} \ No newline at end of file
diff --git a/deck.js/extensions/navigation/deck.navigation.css b/deck.js/extensions/navigation/deck.navigation.css
new file mode 100644
index 0000000..e1ebad8
--- /dev/null
+++ b/deck.js/extensions/navigation/deck.navigation.css
@@ -0,0 +1,43 @@
+.deck-container .deck-prev-link, .deck-container .deck-next-link {
+ display: none;
+ position: absolute;
+ z-index: 3;
+ top: 50%;
+ width: 32px;
+ height: 32px;
+ margin-top: -16px;
+ font-size: 20px;
+ font-weight: bold;
+ line-height: 32px;
+ vertical-align: middle;
+ text-align: center;
+ text-decoration: none;
+ color: #fff;
+ background: #888;
+}
+.borderradius .deck-container .deck-prev-link, .borderradius .deck-container .deck-next-link {
+ -webkit-border-radius: 16px;
+ -moz-border-radius: 16px;
+ border-radius: 16px;
+}
+.deck-container .deck-prev-link:hover, .deck-container .deck-prev-link:focus, .deck-container .deck-prev-link:active, .deck-container .deck-prev-link:visited, .deck-container .deck-next-link:hover, .deck-container .deck-next-link:focus, .deck-container .deck-next-link:active, .deck-container .deck-next-link:visited {
+ color: #fff;
+}
+.deck-container .deck-prev-link {
+ left: 8px;
+}
+.deck-container .deck-next-link {
+ right: 8px;
+}
+.deck-container:hover .deck-prev-link, .deck-container:hover .deck-next-link {
+ display: block;
+}
+.deck-container:hover .deck-prev-link.deck-nav-disabled, .touch .deck-container:hover .deck-prev-link, .deck-container:hover .deck-next-link.deck-nav-disabled, .touch .deck-container:hover .deck-next-link {
+ display: none;
+}
+
+@media print {
+ .deck-prev-link, .deck-next-link {
+ display: none !important;
+ }
+}
diff --git a/deck.js/extensions/navigation/deck.navigation.html b/deck.js/extensions/navigation/deck.navigation.html
new file mode 100644
index 0000000..c756624
--- /dev/null
+++ b/deck.js/extensions/navigation/deck.navigation.html
@@ -0,0 +1,3 @@
+<!-- Place the following snippet at the bottom of the deck container. -->
+<a href="#" class="deck-prev-link" title="Previous">&#8592;</a>
+<a href="#" class="deck-next-link" title="Next">&#8594;</a> \ No newline at end of file
diff --git a/deck.js/extensions/navigation/deck.navigation.js b/deck.js/extensions/navigation/deck.navigation.js
new file mode 100644
index 0000000..a07f7ea
--- /dev/null
+++ b/deck.js/extensions/navigation/deck.navigation.js
@@ -0,0 +1,92 @@
+/*!
+Deck JS - deck.navigation
+Copyright (c) 2011 Caleb Troughton
+Dual licensed under the MIT license and GPL license.
+https://github.com/imakewebthings/deck.js/blob/master/MIT-license.txt
+https://github.com/imakewebthings/deck.js/blob/master/GPL-license.txt
+*/
+
+/*
+This module adds clickable previous and next links to the deck.
+*/
+(function($, deck, undefined) {
+ var $d = $(document),
+
+ /* Updates link hrefs, and disabled states if last/first slide */
+ updateButtons = function(e, from, to) {
+ var opts = $[deck]('getOptions'),
+ last = $[deck]('getSlides').length - 1,
+ prevSlide = $[deck]('getSlide', to - 1),
+ nextSlide = $[deck]('getSlide', to + 1),
+ hrefBase = window.location.href.replace(/#.*/, ''),
+ prevId = prevSlide ? prevSlide.attr('id') : undefined,
+ nextId = nextSlide ? nextSlide.attr('id') : undefined;
+
+ $(opts.selectors.previousLink)
+ .toggleClass(opts.classes.navDisabled, !to)
+ .attr('href', hrefBase + '#' + (prevId ? prevId : ''));
+ $(opts.selectors.nextLink)
+ .toggleClass(opts.classes.navDisabled, to === last)
+ .attr('href', hrefBase + '#' + (nextId ? nextId : ''));
+ };
+
+ /*
+ Extends defaults/options.
+
+ options.classes.navDisabled
+ This class is added to a navigation link when that action is disabled.
+ It is added to the previous link when on the first slide, and to the
+ next link when on the last slide.
+
+ options.selectors.nextLink
+ The elements that match this selector will move the deck to the next
+ slide when clicked.
+
+ options.selectors.previousLink
+ The elements that match this selector will move to deck to the previous
+ slide when clicked.
+ */
+ $.extend(true, $[deck].defaults, {
+ classes: {
+ navDisabled: 'deck-nav-disabled'
+ },
+
+ selectors: {
+ nextLink: '.deck-next-link',
+ previousLink: '.deck-prev-link'
+ }
+ });
+
+ $d.bind('deck.init', function() {
+ var opts = $[deck]('getOptions'),
+ slides = $[deck]('getSlides'),
+ $current = $[deck]('getSlide'),
+ ndx;
+
+ // Setup prev/next link events
+ $(opts.selectors.previousLink)
+ .unbind('click.decknavigation')
+ .bind('click.decknavigation', function(e) {
+ $[deck]('prev');
+ e.preventDefault();
+ });
+
+ $(opts.selectors.nextLink)
+ .unbind('click.decknavigation')
+ .bind('click.decknavigation', function(e) {
+ $[deck]('next');
+ e.preventDefault();
+ });
+
+ // Find where we started in the deck and set initial states
+ $.each(slides, function(i, $slide) {
+ if ($slide === $current) {
+ ndx = i;
+ return false;
+ }
+ });
+ updateButtons(null, ndx, ndx);
+ })
+ .bind('deck.change', updateButtons);
+})(jQuery, 'deck');
+
diff --git a/deck.js/extensions/navigation/deck.navigation.scss b/deck.js/extensions/navigation/deck.navigation.scss
new file mode 100755
index 0000000..815602f
--- /dev/null
+++ b/deck.js/extensions/navigation/deck.navigation.scss
@@ -0,0 +1,56 @@
+@mixin border-radius($r) {
+ -webkit-border-radius:$r;
+ -moz-border-radius:$r;
+ border-radius:$r;
+}
+
+.deck-container {
+ .deck-prev-link, .deck-next-link {
+ display:none;
+ position:absolute;
+ z-index:3;
+ top:50%;
+ width:32px;
+ height:32px;
+ margin-top:-16px;
+ font-size:20px;
+ font-weight:bold;
+ line-height:32px;
+ vertical-align:middle;
+ text-align:center;
+ text-decoration:none;
+ color:#fff;
+ background:#888;
+
+ .borderradius & {
+ @include border-radius(16px);
+ }
+
+ &:hover, &:focus, &:active, &:visited {
+ color:#fff;
+ }
+ }
+
+ .deck-prev-link {
+ left:8px;
+ }
+
+ .deck-next-link {
+ right:8px;
+ }
+
+ &:hover .deck-prev-link, &:hover .deck-next-link {
+ display:block;
+
+ &.deck-nav-disabled, .touch & {
+ display:none;
+ }
+ }
+}
+
+
+@media print {
+ .deck-prev-link, .deck-next-link {
+ display:none !important;
+ }
+}
diff --git a/deck.js/extensions/scale/deck.scale.css b/deck.js/extensions/scale/deck.scale.css
new file mode 100644
index 0000000..d6a4eb0
--- /dev/null
+++ b/deck.js/extensions/scale/deck.scale.css
@@ -0,0 +1,28 @@
+/* Remove this line if you are embedding deck.js in a page and
+using the scale extension. */
+.csstransforms {
+ overflow: hidden;
+}
+
+.csstransforms .deck-container.deck-scale:not(.deck-menu) > .slide {
+ -webkit-box-sizing: padding-box;
+ -moz-box-sizing: padding-box;
+ box-sizing: padding-box;
+ width: 100%;
+ padding-bottom: 20px;
+}
+.csstransforms .deck-container.deck-scale:not(.deck-menu) > .slide > .deck-slide-scaler {
+ -webkit-transform-origin: 50% 0;
+ -moz-transform-origin: 50% 0;
+ -o-transform-origin: 50% 0;
+ -ms-transform-origin: 50% 0;
+ transform-origin: 50% 0;
+}
+
+.csstransforms .deck-container.deck-menu .deck-slide-scaler {
+ -webkit-transform: none !important;
+ -moz-transform: none !important;
+ -o-transform: none !important;
+ -ms-transform: none !important;
+ transform: none !important;
+}
diff --git a/deck.js/extensions/scale/deck.scale.js b/deck.js/extensions/scale/deck.scale.js
new file mode 100644
index 0000000..14feb1a
--- /dev/null
+++ b/deck.js/extensions/scale/deck.scale.js
@@ -0,0 +1,170 @@
+/*!
+Deck JS - deck.scale
+Copyright (c) 2011-2012 Caleb Troughton
+Dual licensed under the MIT license and GPL license.
+https://github.com/imakewebthings/deck.js/blob/master/MIT-license.txt
+https://github.com/imakewebthings/deck.js/blob/master/GPL-license.txt
+*/
+
+/*
+This module adds automatic scaling to the deck. Slides are scaled down
+using CSS transforms to fit within the deck container. If the container is
+big enough to hold the slides without scaling, no scaling occurs. The user
+can disable and enable scaling with a keyboard shortcut.
+
+Note: CSS transforms may make Flash videos render incorrectly. Presenters
+that need to use video may want to disable scaling to play them. HTML5 video
+works fine.
+*/
+(function($, deck, window, undefined) {
+ var $d = $(document),
+ $w = $(window),
+ baseHeight, // Value to scale against
+ timer, // Timeout id for debouncing
+ rootSlides,
+
+ /*
+ Internal function to do all the dirty work of scaling the slides.
+ */
+ scaleDeck = function() {
+ var opts = $[deck]('getOptions'),
+ obh = opts.baseHeight,
+ $container = $[deck]('getContainer'),
+ baseHeight = obh ? obh : $container.height();
+
+ // Scale each slide down if necessary (but don't scale up)
+ $.each(rootSlides, function(i, $slide) {
+ var slideHeight = $slide.innerHeight(),
+ $scaler = $slide.find('.' + opts.classes.scaleSlideWrapper),
+ scale = $container.hasClass(opts.classes.scale) ?
+ baseHeight / slideHeight :
+ 1;
+
+ $.each('Webkit Moz O ms Khtml'.split(' '), function(i, prefix) {
+ if (scale === 1) {
+ $scaler.css(prefix + 'Transform', '');
+ }
+ else {
+ $scaler.css(prefix + 'Transform', 'scale(' + scale + ')');
+ }
+ });
+ });
+ }
+
+ /*
+ Extends defaults/options.
+
+ options.classes.scale
+ This class is added to the deck container when scaling is enabled.
+ It is enabled by default when the module is included.
+
+ options.classes.scaleSlideWrapper
+ Scaling is done using a wrapper around the contents of each slide. This
+ class is applied to that wrapper.
+
+ options.keys.scale
+ The numeric keycode used to toggle enabling and disabling scaling.
+
+ options.baseHeight
+ When baseHeight is falsy, as it is by default, the deck is scaled in
+ proportion to the height of the deck container. You may instead specify
+ a height as a number of px, and slides will be scaled against this
+ height regardless of the container size.
+
+ options.scaleDebounce
+ Scaling on the browser resize event is debounced. This number is the
+ threshold in milliseconds. You can learn more about debouncing here:
+ http://unscriptable.com/index.php/2009/03/20/debouncing-javascript-methods/
+
+ */
+ $.extend(true, $[deck].defaults, {
+ classes: {
+ scale: 'deck-scale',
+ scaleSlideWrapper: 'deck-slide-scaler'
+ },
+
+ keys: {
+ scale: 83 // s
+ },
+
+ baseHeight: null,
+ scaleDebounce: 200
+ });
+
+ /*
+ jQuery.deck('disableScale')
+
+ Disables scaling and removes the scale class from the deck container.
+ */
+ $[deck]('extend', 'disableScale', function() {
+ $[deck]('getContainer').removeClass($[deck]('getOptions').classes.scale);
+ scaleDeck();
+ });
+
+ /*
+ jQuery.deck('enableScale')
+
+ Enables scaling and adds the scale class to the deck container.
+ */
+ $[deck]('extend', 'enableScale', function() {
+ $[deck]('getContainer').addClass($[deck]('getOptions').classes.scale);
+ scaleDeck();
+ });
+
+ /*
+ jQuery.deck('toggleScale')
+
+ Toggles between enabling and disabling scaling.
+ */
+ $[deck]('extend', 'toggleScale', function() {
+ var $c = $[deck]('getContainer');
+ $[deck]($c.hasClass($[deck]('getOptions').classes.scale) ?
+ 'disableScale' : 'enableScale');
+ });
+
+ $d.bind('deck.init', function() {
+ var opts = $[deck]('getOptions'),
+ slideTest = $.map([
+ opts.classes.before,
+ opts.classes.previous,
+ opts.classes.current,
+ opts.classes.next,
+ opts.classes.after
+ ], function(el, i) {
+ return '.' + el;
+ }).join(', ');
+
+ // Build top level slides array
+ rootSlides = [];
+ $.each($[deck]('getSlides'), function(i, $el) {
+ if (!$el.parentsUntil(opts.selectors.container, slideTest).length) {
+ rootSlides.push($el);
+ }
+ });
+
+ // Use a wrapper on each slide to handle content scaling
+ $.each(rootSlides, function(i, $slide) {
+ $slide.children().wrapAll('<div class="' + opts.classes.scaleSlideWrapper + '"/>');
+ });
+
+ // Debounce the resize scaling
+ $w.unbind('resize.deckscale').bind('resize.deckscale', function() {
+ window.clearTimeout(timer);
+ timer = window.setTimeout(scaleDeck, opts.scaleDebounce);
+ })
+ // Scale once on load, in case images or something change layout
+ .unbind('load.deckscale').bind('load.deckscale', scaleDeck);
+
+ // Bind key events
+ $d.unbind('keydown.deckscale').bind('keydown.deckscale', function(e) {
+ if (e.which === opts.keys.scale || $.inArray(e.which, opts.keys.scale) > -1) {
+ $[deck]('toggleScale');
+ e.preventDefault();
+ }
+ });
+
+ // Enable scale on init
+ $[deck]('enableScale');
+ });
+})(jQuery, 'deck', this);
+
diff --git a/deck.js/extensions/scale/deck.scale.scss b/deck.js/extensions/scale/deck.scale.scss
new file mode 100644
index 0000000..2fa0851
--- /dev/null
+++ b/deck.js/extensions/scale/deck.scale.scss
@@ -0,0 +1,31 @@
+/* Remove this line if you are embedding deck.js in a page and
+using the scale extension. */
+.csstransforms {
+ overflow:hidden;
+}
+
+.csstransforms .deck-container.deck-scale:not(.deck-menu) {
+ > .slide {
+ -webkit-box-sizing: padding-box;
+ -moz-box-sizing: padding-box;
+ box-sizing: padding-box;
+ width:100%;
+ padding-bottom:20px;
+
+ > .deck-slide-scaler {
+ -webkit-transform-origin: 50% 0;
+ -moz-transform-origin: 50% 0;
+ -o-transform-origin: 50% 0;
+ -ms-transform-origin: 50% 0;
+ transform-origin: 50% 0;
+ }
+ }
+}
+
+.csstransforms .deck-container.deck-menu .deck-slide-scaler {
+ -webkit-transform:none !important;
+ -moz-transform:none !important;
+ -o-transform:none !important;
+ -ms-transform:none !important;
+ transform:none !important;
+} \ No newline at end of file
diff --git a/deck.js/extensions/simplemath/deck.simplemath.js b/deck.js/extensions/simplemath/deck.simplemath.js
new file mode 100644
index 0000000..c09d6f3
--- /dev/null
+++ b/deck.js/extensions/simplemath/deck.simplemath.js
@@ -0,0 +1,25 @@
+/*!
+Deck JS - deck.simplemath
+Copyright (c) 2012 Rémi Emonet,
+using a modified version of the script from http://gold-saucer.afraid.org/mathml/greasemonkey/ by Steve Cheng
+*/
+
+/*
+This module provides a support for latex equation syntax.
+*/
+
+(function($, deck, undefined) {
+ var $d = $(document);
+ var may = function(f) {return f ? f : function() {}};
+
+ $d.bind('deck.init', function() {
+ var container = $[deck]('getContainer');
+ $('.latex', container).each(function() {
+ var it = this;
+ var v = $(it).text();
+ it.innerHTML = "$\\displaystyle "+v+"$";
+ new latex2mml().patch_element(it);
+ });
+ });
+
+})(jQuery, 'deck'); \ No newline at end of file
diff --git a/deck.js/extensions/smartsyntax/deck.smartsyntax.js b/deck.js/extensions/smartsyntax/deck.smartsyntax.js
new file mode 100644
index 0000000..581f9e1
--- /dev/null
+++ b/deck.js/extensions/smartsyntax/deck.smartsyntax.js
@@ -0,0 +1,226 @@
+/*!
+Deck JS - deck.smartsyntax
+Copyright (c) 2012 Rémi Emonet
+Dual licensed under the MIT license and GPL license.
+https://github.com/imakewebthings/deck.js/blob/master/MIT-license.txt
+https://github.com/imakewebthings/deck.js/blob/master/GPL-license.txt
+*/
+
+/*
+This module provides a support for a shorter syntax for slides.
+*/
+
+(function($, deck, undefined) {
+ var $d = $(document);
+ var may = function(f) {return f ? f : function() {}};
+ var startsWith = function(longStr, part) {return longStr.substr(0, part.length) == part;}
+ var startsWithIgnoreCase = function(longStr, part) {return longStr.substr(0, part.length).toUpperCase() == part.toUpperCase();}
+ var maybeAddClasses = function(toWhat, spaceSeparatedClasses, uniqueId) {
+ if (uniqueId != "") $(toWhat).attr("id", uniqueId);
+ if (spaceSeparatedClasses == "") return;
+ var parts = spaceSeparatedClasses.split(/ +/);
+ for (i in parts) {
+ $(toWhat).addClass(parts[i]);
+ }
+ }
+
+ var interpretationOfSmartLanguage = function(smart, doc) {
+ var res = new Array();
+ var inSlide = null;
+ var indent = "";
+ var deepestList = null;
+ var remain = smart;
+
+ var processMath = function(content) {
+ return content.replace(/\$([^$][^$]*)\$/g, '<span class="latex">\\displaystyle $1</span>').replace(/\$\$/, '$');
+ }
+
+ var setEnrichedContent = function(what, content) {
+ content = processMath(content);
+ return what.innerHTML = content;
+ }
+ var endSlide = function() {
+ inSlide = null;
+ indent = new Array();
+ indent = "";
+ deepestList = null;
+ }
+
+ while (true) {
+ var nl = remain.indexOf("\n");
+ var line = remain.substring(0, nl).replace(/^ */, "");
+ // we iterate over the lines
+ // treat trailing unique-id and classes before anything
+ var uniqueId = "";
+ while (line.match(/^(.*)#([^\]\| >]*)$/)) {
+ uniqueId = RegExp.$2;
+ line = RegExp.$1;
+ }
+ var addClasses = "";
+ {
+ while (line.match(/^(.*)\[([^\] >]*)\]$/)) {
+ addClasses = RegExp.$2 + " " + addClasses;
+ line = RegExp.$1;
+ }
+ }
+ if (line == "") {
+ } else if (line.match(/^==(.*)==$/)) {
+ var title = RegExp.$1;
+ if (inSlide) endSlide();
+ inSlide = doc.createElement("section");
+ $(inSlide).addClass("slide");
+ maybeAddClasses(inSlide, addClasses, uniqueId);
+ var h = doc.createElement("h1");
+ setEnrichedContent(h, title);
+ inSlide.appendChild(h);
+ deepestList = inSlide;
+ res[res.length] = inSlide;
+ } else if (line.match(/^=(.*)=$/)) {
+ var title = RegExp.$1;
+ if (inSlide) endSlide();
+ inSlide = doc.createElement("section");
+ $(inSlide).addClass("slide");
+ maybeAddClasses(inSlide, addClasses, uniqueId);
+ var h = doc.createElement("h2");
+ setEnrichedContent(h, title);
+ inSlide.appendChild(h);
+ deepestList = inSlide;
+ res[res.length] = inSlide;
+ } else if (line.match(/^([-*#]+)(.*)$/)) {
+ var pref = RegExp.$1;
+ var content = RegExp.$2;
+ if (indent == "" && pref == "") {
+ // do not create the li
+ } else if (pref == indent) {
+ var li = doc.createElement("li");
+ maybeAddClasses(li, addClasses, uniqueId);
+ setEnrichedContent(li, content);
+ deepestList.appendChild(li);
+ } else {
+ // un-push as needed
+ while (! startsWith(pref, indent)) {
+ deepestList = deepestList.parentNode;
+ if (deepestList.tagName == "LI") deepestList = deepestList.parentNode;
+ indent = indent.substr(0, indent.length - 1);
+ }
+ // clean the special '-' that we can use for magic unpush
+ pref = pref.replace(/^-*/, "");
+ // re-push as needed
+ while (pref.length > indent.length) {
+ var asso = {"*": "ul", "#": "ol"};
+ var toPush = pref.substr(indent.length, 1);
+ indent = indent.concat(toPush);
+ var list = doc.createElement(asso[toPush]);
+ if ((deepestList.tagName == "UL" || deepestList.tagName == "OL") && deepestList.childNodes.length > 0) {
+ deepestList.lastChild.appendChild(list);
+ } else {
+ deepestList.appendChild(list);
+ }
+ deepestList = list;
+ }
+ if (indent == "" && pref == "") {
+ // do not create the li
+ } else {
+ var li = doc.createElement("li");
+ maybeAddClasses(li, addClasses, uniqueId);
+ setEnrichedContent(li, content);
+ deepestList.appendChild(li);
+ }
+ }
+ } else if (startsWithIgnoreCase(line, "@SVG:")) {
+ var parts = line.replace(/@SVG\: */i, "").split(/ +/);
+ var obj = $("<object type='deckjs/svg'/>");
+ $.each(parts[0].split(/,/), function(i,c){obj.addClass(c);});
+ obj.append($("<param name='src'/>").attr("value", parts[1]))
+ .append($("<param name='width'/>").attr("value", parts[2]))
+ .append($("<param name='height'/>").attr("value", parts[3]))
+ .appendTo(inSlide);
+ } else if (startsWithIgnoreCase(line, "@ANIM-PLAY:")) {
+ line = line.replace(/@ANIM-PLAY\: */i, "");
+ $("<div/>").addClass("anim-play slide").attr("data-what", line).appendTo(deepestList);
+ } else if (startsWithIgnoreCase(line, "@ANIM-PAUSE:")) {
+ line = line.replace(/@ANIM-PAUSE\: */i, "");
+ $("<div/>").addClass("anim-pause slide").attr("data-what", line).appendTo(deepestList);
+ } else if (startsWithIgnoreCase(line, "@ANIM-ATTRIBUTE:")) {
+ line = line.replace(/@ANIM-ATTRIBUTE\: */i, "");
+ var main = line.split(/ *: */);
+ $("<div/>").addClass("anim-attribute slide").attr("data-dur", main[0]).attr("data-what", main[1]).attr("data-attr", main[2]+":"+main[3]).appendTo(deepestList);
+ } else if (startsWithIgnoreCase(line, "@ANIM-APPEAR:")) {
+ line = line.replace(/@ANIM-APPEAR\: */i, "");
+ if (uniqueId != "") line += "#"+uniqueId; // restore possibly removed id
+ var main = line.split(/ *: */);
+ var dur = main[0];
+ var parts = main[1].split(/ *\| */);
+ for (i in parts) {
+ // process each group of simultaneous animations
+ var subparts = parts[i].split(/ *\+ */);
+ for (ii in subparts) {
+ var what = subparts[ii];
+ var continuating = ii != subparts.length-1;
+ var add = $("<div/>");
+ add.attr("data-dur", dur);
+ if (what[0] == '-') {
+ add.addClass("anim-hide");
+ what = what.substring(1);
+ } else if (what[0] == '@') {
+ // TODO if it looks like @....@ then the target is specified, else it is just all SVGs root elements
+ add.addClass("anim-viewboxas");
+ what = what.substring(1);
+ add.attr("data-as", what);
+ what = "svg";
+ } else {
+ add.addClass("anim-show");
+ }
+ add.addClass("slide").attr("data-what", what);
+ if (continuating) add.addClass("anim-continue");
+ add.appendTo(deepestList);
+ }
+ }
+ } else if (startsWith(line, "@<")) {
+ line = line.replace(/^@/, "");
+ var contentToAdd = "";
+ // test on remain to avoid infinite loop
+ while (line != null && remain.length != 0) {
+ if (line.match(/^@<\//)) {
+ // normal stopping condition
+ line = line.replace(/^@/, "");
+ contentToAdd += " " + line + "\n";
+ break;
+ }
+ if (nl != -1) remain = remain.substring(nl + 1);
+ contentToAdd += " " + line + "\n";
+ nl = remain.indexOf("\n");
+ line = remain.substring(0, nl).replace(/^ */, "");
+ }
+ deepestList.innerHTML = deepestList.innerHTML + processMath(contentToAdd) + " ";
+ } else {
+ while (true) {
+ try {
+ deepestList.innerHTML = deepestList.innerHTML + processMath(line) + " ";
+ break;
+ } catch (e) {
+ // TODO was ok with xhtml not really now
+ remain = remain.substring(nl + 1);
+ nl = remain.indexOf("\n");
+ var line2 = remain.substring(0, nl).replace(/^ */, "");
+ line = line + "\n" + line2;
+ }
+ }
+ }
+ if (nl != -1) remain = remain.substring(nl + 1);
+ else break;
+ }
+ return res;
+ }
+
+ // this have to be executed before the deck init
+ $d.bind('deck.beforeInit', function() {
+ $('.smart').each(function() {
+ var it = this;
+ var slides = interpretationOfSmartLanguage(it.innerHTML, document);
+ it.innerHTML = ""; // clear the smart node
+ $(it).after(slides);
+ });
+ });
+
+})(jQuery, 'deck'); \ No newline at end of file
diff --git a/deck.js/extensions/status/deck.status.css b/deck.js/extensions/status/deck.status.css
new file mode 100644
index 0000000..1188905
--- /dev/null
+++ b/deck.js/extensions/status/deck.status.css
@@ -0,0 +1,25 @@
+.deck-container .deck-status {
+ position: absolute;
+ bottom: 0px;
+ left: 0px;
+ right: 0px;
+ color: #f0f;
+ z-index: 3;
+ margin: 0;
+ padding: 4px;
+ padding-top: 8px;
+ border-top: 1px solid #eee;
+ background-color: #000;
+ font-weight: 700;
+ font-size: 1.0em;
+}
+
+body.deck-container .deck-status {
+ position: fixed;
+}
+
+@media print {
+ .deck-status {
+ display: none;
+ }
+}
diff --git a/deck.js/extensions/status/deck.status.html b/deck.js/extensions/status/deck.status.html
new file mode 100644
index 0000000..310a025
--- /dev/null
+++ b/deck.js/extensions/status/deck.status.html
@@ -0,0 +1,6 @@
+<!-- Place the following snippet at the bottom of the deck container. -->
+<p class="deck-status">
+ <span class="deck-status-current"></span>
+ /
+ <span class="deck-status-total"></span>
+</p> \ No newline at end of file
diff --git a/deck.js/extensions/status/deck.status.js b/deck.js/extensions/status/deck.status.js
new file mode 100644
index 0000000..9513c67
--- /dev/null
+++ b/deck.js/extensions/status/deck.status.js
@@ -0,0 +1,120 @@
+/*!
+Deck JS - deck.status
+Copyright (c) 2011 Caleb Troughton
+Dual licensed under the MIT license and GPL license.
+https://github.com/imakewebthings/deck.js/blob/master/MIT-license.txt
+https://github.com/imakewebthings/deck.js/blob/master/GPL-license.txt
+*/
+
+/*
+This module adds a (current)/(total) style status indicator to the deck.
+*/
+(function($, deck, undefined) {
+ var $d = $(document),
+
+ updateCurrent = function(e, from, to) {
+ var opts = $[deck]('getOptions');
+
+ $(opts.selectors.statusCurrent).text(opts.countNested ?
+ to + 1 :
+ $[deck]('getSlide', to).data('rootSlide')
+ );
+ };
+
+ /*
+ Extends defaults/options.
+
+ options.selectors.statusCurrent
+ The element matching this selector displays the current slide number.
+
+ options.selectors.statusTotal
+ The element matching this selector displays the total number of slides.
+
+ options.countNested
+ If false, only top level slides will be counted in the current and
+ total numbers.
+ */
+ $.extend(true, $[deck].defaults, {
+ selectors: {
+ statusCurrent: '.deck-status-current',
+ statusTotal: '.deck-status-total',
+ statusFakeEnd: '.deck-status-fake-end',
+ statusFullTotal: '.deck-status-full-total'
+ },
+
+ countNested: true
+ });
+
+ $d.bind('deck.init', function() {
+ var opts = $[deck]('getOptions'),
+ slides = $[deck]('getSlides'),
+ $current = $[deck]('getSlide'),
+ ndx;
+
+ // Set total slides once
+ if (opts.countNested) {
+ var notfound = 1000000;
+ var fakeEnd = notfound;
+ $.each(slides, function(i, $el) {
+ if (fakeEnd > i) {
+ if ($el.filter(opts.selectors.statusFakeEnd).length) {
+ fakeEnd = i;
+ }
+ }
+ });
+ $(opts.selectors.statusTotal).text(fakeEnd == notfound ? slides.length : fakeEnd+1);
+ $(opts.selectors.statusFullTotal).text(slides.length);
+ }
+ else {
+ /* Determine root slides by checking each slide's ancestor tree for
+ any of the slide classes. */
+ var rootIndex = 1,
+ slideTest = $.map([
+ opts.classes.before,
+ opts.classes.previous,
+ opts.classes.current,
+ opts.classes.next,
+ opts.classes.after
+ ], function(el, i) {
+ return '.' + el;
+ }).join(', ');
+
+ /* Store the 'real' root slide number for use during slide changes. */
+ $.each(slides, function(i, $el) {
+ var $parentSlides = $el.parentsUntil(opts.selectors.container, slideTest);
+
+ $el.data('rootSlide', $parentSlides.length ?
+ $parentSlides.last().data('rootSlide') :
+ rootIndex++
+ );
+ });
+
+ var notfound = 1000000;
+ var fakeEnd = notfound;
+ var rootOfFakeEnd = null;
+ $.each(slides, function(i, $el) {
+ if (fakeEnd > i) {
+ if ($el.filter(opts.selectors.statusFakeEnd).length) {
+ fakeEnd = i;
+ rootOfFakeEnd = $el.data('rootSlide');
+ }
+ }
+ });
+
+ $(opts.selectors.statusTotal).text(fakeEnd == notfound ? rootIndex - 1 : rootOfFakeEnd);
+ $(opts.selectors.statusFullTotal).text(rootIndex - 1);
+ }
+
+ // Find where we started in the deck and set initial state
+ $.each(slides, function(i, $el) {
+ if ($el === $current) {
+ ndx = i;
+ return false;
+ }
+ });
+ updateCurrent(null, ndx, ndx);
+ })
+ /* Update current slide number with each change event */
+ .bind('deck.change', updateCurrent);
+})(jQuery, 'deck');
+
diff --git a/deck.js/extensions/status/deck.status.scss b/deck.js/extensions/status/deck.status.scss
new file mode 100755
index 0000000..d57af24
--- /dev/null
+++ b/deck.js/extensions/status/deck.status.scss
@@ -0,0 +1,22 @@
+.deck-container {
+ .deck-status {
+ position:absolute;
+ bottom:10px;
+ right:5px;
+ color:#888;
+ z-index:3;
+ margin:0;
+ }
+}
+
+body.deck-container {
+ .deck-status {
+ position:fixed;
+ }
+}
+
+@media print {
+ .deck-status {
+ display:none;
+ }
+}
diff --git a/deck.js/extensions/step/deck.step.js b/deck.js/extensions/step/deck.step.js
new file mode 100644
index 0000000..1b1ac70
--- /dev/null
+++ b/deck.js/extensions/step/deck.step.js
@@ -0,0 +1,119 @@
+/*!
+Deck JS - deck.step
+Copyright (c) 2011 Rémi Emonet
+Dual licensed under the MIT license and GPL license.
+https://github.com/imakewebthings/deck.js/blob/master/MIT-license.txt
+https://github.com/imakewebthings/deck.js/blob/master/GPL-license.txt
+*/
+
+/*
+This module provides new methods for stepping without considering sub-slides, together with tools for finding toplevel slides etc.
+It also overrides the defaults keybinding and countNested value (so it is better to include it after "goto" and "status" extensions).
+*/
+
+(function($, deck, undefined) {
+ var $d = $(document);
+ // undo the defaults (to be sure jquery behaves properly when overriding it)
+ $.extend(true, $[deck].defaults, { keys: {next:null, previous:null}});
+ // and go on
+ $.extend(true, $[deck].defaults, {
+ selectors: {
+ subslidesToNotify: ".slide,.onshowtoplevel"
+ },
+ // Here we redefined the defaults:
+ // - we avoid counting nested slides
+ // - we keep up/down for top-level slides
+ // - we still use pgup/pgdown for inner slides as they are sent by some pluggable remote controls
+ keys: {
+ // backspace, left arrow, page down
+ previous: [8, 37, 34],
+ // enter, space, right arrow, page up
+ next: [13, 32, 39, 33],
+ // up arrow
+ previousTopLevel: [38],
+ // down arrow,
+ nextTopLevel: [40]
+ },
+ countNested: false
+ });
+ var myInArray = function(el, arr) {
+ for (i in arr) if (arr[i].is(el)) return i*1; // cast to int
+ return -1;
+ };
+ $[deck]('extend', 'getToplevelSlideOf', function(node) {
+ var opts = $[deck]('getOptions');
+ var slides = $[deck]('getSlides');
+ var last = {node: $(node), index: myInArray(node, slides)};
+ $(node).parentsUntil(opts.selectors.container).each( function(ii, v) {
+ var ind = myInArray(v, slides);
+ if (ind != -1) {
+ last = {node: $(v), index: ind};
+ }
+ });
+ return last;
+ });
+ $[deck]('extend', 'getToplevelSlideOfIndex', function(ind) {
+ return $[deck]('getToplevelSlideOf', $[deck]('getSlide', ind));
+ });
+ $[deck]('extend', 'previousTopLevelSlide', function() {
+ /* Find the real previous parent */
+ var current = $[deck]('getSlide');
+ var currentParent = $[deck]('getToplevelSlideOf', current);
+ var toGo = currentParent.index;
+ if (current.is(currentParent.node) && toGo > 0) {
+ // This is already toplevel slide, just go to the previous toplevel one (parent of the previous one)
+ toGo = $[deck]('getToplevelSlideOfIndex', toGo-1).index;
+ }
+ $[deck]('go', toGo);
+
+ });
+ $[deck]('extend', 'nextTopLevelSlide', function() {
+ /* Find the real next parent */
+ var current = $[deck]('getSlide');
+ var currentParent = $[deck]('getToplevelSlideOf', current);
+ var icur = currentParent.index;
+ for (; icur < $[deck]('getSlides').length; icur++) {
+ var cursorParent = $[deck]('getToplevelSlideOfIndex', icur).node;
+ if (!cursorParent.is(currentParent.node)) {
+ $[deck]('go', icur);
+ break;
+ }
+ }
+ });
+ $d.bind('deck.init', function() {
+ $d.unbind('keydown.decknexttoplevel').bind('keydown.decknexttoplevel', function(e) {
+ var $opts = $[deck]('getOptions');
+ var key = $opts.keys.nextTopLevel;
+ if (e.which === key || $.inArray(e.which, key) > -1) {
+ e.preventDefault();
+ $[deck]('nextTopLevelSlide');
+ }
+ });
+ $d.unbind('keydown.deckprevioustoplevel').bind('keydown.deckprevioustoplevel', function(e) {
+ var $opts = $[deck]('getOptions');
+ var key = $opts.keys.previousTopLevel;
+ if (e.which === key || $.inArray(e.which, key) > -1) {
+ e.preventDefault();
+ $[deck]('previousTopLevelSlide');
+ }
+ });
+ });
+ // When jumping (not steping), we will init the subslides (in case they are animations), in a backward order, and then fast forward necessary animations
+ var bigJump = function(from, to) {
+ var direction = "forward";
+ if (from > to){
+ direction = "reverse";
+ }
+ var opts = $[deck]('getOptions');
+ $($[deck]('getToplevelSlideOfIndex', to).node.find(opts.selectors.subslidesToNotify).get().reverse()).trigger('deck.toplevelBecameCurrent', direction);
+ for (icur = $[deck]('getToplevelSlideOfIndex', to).index + 1; icur < to+1; icur++) {
+ $[deck]('getSlides')[icur].trigger('deck.afterToplevelBecameCurrent', 'forward');
+ }
+ }
+ $d.bind('deck.change', function(e, from, to) {
+ if ( Math.abs(from - to) > 1 || ! $[deck]('getToplevelSlideOfIndex', to).node.is($[deck]('getToplevelSlideOfIndex', from).node)) {
+ // consider natural jumps and the case where we actually changed (top level) slide (even with a step)
+ bigJump(from, to);
+ }
+ });
+})(jQuery, 'deck');
diff --git a/deck.js/extensions/svg/deck.svg.js b/deck.js/extensions/svg/deck.svg.js
new file mode 100644
index 0000000..cd65c87
--- /dev/null
+++ b/deck.js/extensions/svg/deck.svg.js
@@ -0,0 +1,115 @@
+/*!
+Deck JS - deck.svg
+Copyright (c) 2012 Rémi Emonet, as a major refactor from an early version from Rémi Barraquand.
+*/
+
+/*
+This module provides a support for managed svg inclusion (allowing proper DOM access subsequently for animations, etc.).
+*/
+
+(function($, deck, undefined) {
+ var $d = $(document);
+ var may = function(f) {return f ? f : function() {}};
+
+ $.extend(true, $[deck].defaults, {
+ classes: {
+ svgPlaceholder: 'deck-svg'
+ }
+ });
+
+ /*
+ jQuery.deck('Init')
+ */
+ $d.bind('deck.init', function() {
+ var opts = $[deck]('getOptions');
+ var container = $[deck]('getContainer');
+
+ /*
+ Load parameters from an Object element
+ */
+ var loadObjectParams = function(objectElement) {
+ var attributes = {};
+ $(objectElement).children("param").each(function(index){
+ attributes[$(this).attr("name")] = $(this).attr("value");
+ });
+ return attributes;
+ }
+
+ /*
+ Return true if default params are set.
+ */
+ var validateParams = function(params) {
+ return params['src'];// && params['width'] && params['height'];// && params['animator'];
+ }
+
+ /*
+ Create SVG placeholder
+ */
+ var createSVG = function(object, attributes) {
+ var $canvas, $control, $next, $reload, $placeholder;
+
+ /* Create svg canvas */
+ $canvas = $("<div />").attr({
+ 'id': $(object).attr('id'),
+ 'class': opts.classes.svgPlaceholder + " " + $(object).attr('class')
+ }).css({
+ 'height': attributes['height'],
+ 'width': attributes['width']
+ });
+ return $canvas;
+ }
+
+
+ /* Go through all toplevel slides */
+ $($[deck]('getSlides')).each( function(i, $el) {
+ var $slide = $[deck]('getSlide', i);
+
+ /*
+ if ($slide.has("object[type='deckjs/svg']").length>0) {
+ $slide.data('animators', new Array());
+ }*/
+
+ /* Find all the object of type deckjs/svg */
+ if ($slide == null) return true;
+ $slide.find("object[type='deckjs/svg']").each(function(index, obj) {
+ //var id = $(this);
+ /* Load attributes and validate them */
+ var attributes = loadObjectParams(obj);
+ if (!validateParams(attributes) ) {
+ throw "Error while initializing "+$(obj).attr('id')+", please ensure you have setup the required parameters."
+ return false;
+ }
+
+ /* Add this animator to the list of animators of the current slide. */
+ //$slide.data('animators').push(attributes['animator']);
+
+ /* Create SVG placeholder */
+ var SVG = createSVG(obj, attributes);
+ $(obj).replaceWith(SVG);
+
+ // Finaly load the SVG data
+ //$[deck]('addLoading');
+ $[deck]("animWaitMore");
+ SVG.svg({
+ loadURL: attributes['src'],
+ onLoad: function($svg, w, h) {
+ var aa = $($svg.root());
+ if (aa.attr('viewBox') == undefined) {
+ var to = "0 0 " + w + " " + h;
+ $svg.root().setAttribute("viewBox", to);
+ aa.attr("svgViewBox", to);
+ if (attributes['stretch'] == 'true') $svg.root().setAttribute('preserveAspectRatio', "none");
+ }
+ $[deck]("animWaitLess");
+ /*
+ $[deck]('removeLoading')
+ */
+ }
+ });
+ });
+ });
+ })
+
+
+})(jQuery, 'deck');
+