Browse Source

moving server

windhamdavid 4 years ago
parent
commit
4c578509e5

+ 8 - 8
package.json

@@ -1,10 +1,10 @@
 {
-    "name": "gwd-gapps"
-  , "version": "0.0.1"
-  , "private": true
-  , "main": "app.js"
-  , "dependencies": {
-      "node-static": "~0.6.6",
-      "socket.io": "~0.9.13"
-  }
+	"name": "show",
+	"version": "0.1.0",
+	"private": true,
+	"main": "app.js",
+	"dependencies": {
+		"node-static": "~0.7.7",
+		"socket.io": "~1.3.7"
+	}
 }

+ 421 - 0
public/css/daw.css

@@ -0,0 +1,421 @@
+/* Based on the Sky theme for reveal.js. */
+
+@import url(https://fonts.googleapis.com/css?family=Quicksand:400,700,400italic,700italic);
+@import url(https://fonts.googleapis.com/css?family=Open+Sans:400italic,700italic,400,700);
+@import url(http://fonts.googleapis.com/css?family=Lato:300,400);
+
+@-moz-font-face{
+    font-family: Catull;
+    src: url(font/catull.ttf);
+    font-weight:400;
+}
+@-webkit-font-face{
+    font-family: Catull;
+    src: url(font/catull.ttf);
+    font-weight:400;
+}
+@-o-font-face{
+    font-family: Catull;
+    src: url(font/catull.ttf);
+    font-weight:400;
+}
+@-ms-font-face{
+    font-family: Catull;
+    src: url(font/catull.ttf);
+    font-weight:400;
+}
+@font-face{
+    font-family: Catull;
+    src: url(font/catull.ttf);
+    font-weight:400;
+}
+
+.reveal a:not(.image) {
+  line-height: 1.3em; }
+ 
+ 
+/*********************************************
+ * GLOBAL STYLES
+ *********************************************/
+body {
+  background: #ffffff;
+}
+
+.reveal {
+  font-family: "Open Sans", sans-serif;
+  font-size: 36px;
+  font-weight: normal;
+  letter-spacing: -0.02em;
+  color: #333333; }
+
+::selection {
+  color: white;
+  background: #134674;
+  text-shadow: none; }
+
+/*********************************************
+ * HEADERS
+ *********************************************/
+.reveal h1,
+.reveal h2,
+.reveal h3,
+.reveal h4,
+.reveal h5,
+.reveal h6 {
+  margin: 0 0 20px 0;
+  color: #333333;
+  font-family: "Open Sans", sans-serif;
+  line-height: 0.9em;
+  letter-spacing: -0.05em;
+  text-shadow: none; }
+
+
+
+/*********************************************
+ * LINKS
+ *********************************************/
+.reveal a:not(.image) {
+  color: #0047F1;
+  text-decoration: none;
+  -webkit-transition: color .15s ease;
+  -moz-transition: color .15s ease;
+  -ms-transition: color .15s ease;
+  -o-transition: color .15s ease;
+  transition: color .15s ease; }
+
+.reveal a:not(.image):hover {
+  color: #0047F1;
+  text-shadow: none;
+  border: none; }
+
+.reveal .roll span:after {
+  color: #fff;
+  background: #0047F1; }
+
+/*********************************************
+ * IMAGES
+ *********************************************/
+.reveal section img {
+  margin: 15px 0px;
+  background: rgba(255, 255, 255, 0.12);
+  border: 4px solid #333333;
+  box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
+  -webkit-transition: all .2s linear;
+  -moz-transition: all .2s linear;
+  -ms-transition: all .2s linear;
+  -o-transition: all .2s linear;
+  transition: all .2s linear; }
+ 
+ .reveal section img.noborder {
+ 	border: none;
+	box-shadow: none;
+ }
+
+.reveal a:hover img {
+  background: rgba(255, 255, 255, 0.2);
+  border-color: #3b759e;
+  box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); }
+
+/*********************************************
+ * NAVIGATION CONTROLS
+ *********************************************/
+.reveal .controls div.navigate-left,
+.reveal .controls div.navigate-left.enabled {
+  border-right-color: #3b759e; }
+
+.reveal .controls div.navigate-right,
+.reveal .controls div.navigate-right.enabled {
+  border-left-color: #3b759e; }
+
+.reveal .controls div.navigate-up,
+.reveal .controls div.navigate-up.enabled {
+  border-bottom-color: #3b759e; }
+
+.reveal .controls div.navigate-down,
+.reveal .controls div.navigate-down.enabled {
+  border-top-color: #3b759e; }
+
+.reveal .controls div.navigate-left.enabled:hover {
+  border-right-color: #74a7cb; }
+
+.reveal .controls div.navigate-right.enabled:hover {
+  border-left-color: #74a7cb; }
+
+.reveal .controls div.navigate-up.enabled:hover {
+  border-bottom-color: #74a7cb; }
+
+.reveal .controls div.navigate-down.enabled:hover {
+  border-top-color: #74a7cb; }
+
+/*********************************************
+ * PROGRESS BAR
+ *********************************************/
+.reveal .progress {
+  background: rgba(0, 0, 0, 0.2); }
+
+.reveal .progress span {
+  background: #3b759e;
+  -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
+  -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
+  -ms-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
+  -o-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
+  transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985); }
+
+/*********************************************
+ * SLIDE NUMBER
+ *********************************************/
+.reveal .slide-number {
+  color: #3b759e; }
+
+
+/*********************************************
+* Custom - windhamdavid
+*********************************************/
+
+.reveal h1 {
+	font-size:100px;
+	text-shadow:0px 3px 3px rgba(0,0,0,0.25);
+	letter-spacing: -0.01em;
+}
+
+.reveal h1.light, 
+.reveal h2.light, 
+.reveal h3.light, 
+.reveal h4.light {
+	color: #e1e1e1;
+}
+.reveal p.light {
+	color: #e1e1e1;
+}
+.bg-block {
+	background: #fff;
+	padding: 20px;
+	opacity:0.9;
+	filter:alpha(opacity=90); /* For IE8 and earlier */
+}
+.bg-block h4 {
+	padding: 30px;
+}
+.reveal .theend {
+	background: #000;
+}
+
+.reveal span.raised {
+	color:#cecece;
+	text-shadow: 1px 1px 1px #000;
+}
+.reveal span.highlight {
+	color:#000;
+	background-color:#ffff00;
+}
+.reveal p.footnotes {
+	font-size:14px;
+	margin-bottom:5px;
+	padding-bottom:5px;
+}
+.reveal a.light {
+  color:#FF70F4;
+}
+
+
+
+
+#logo {
+	margin-bottom:30px;
+}
+  @-webkit-keyframes pulse { 
+  	0% {color: #0047F1;} 
+  	25% {color: #DD172C;} 
+  	50% {color: #F9A600;} 
+  	75% {color: #0047F1;} 
+  	100% {color: #00930E;} 
+  }	
+.reveal h1.colors span.g {
+	font-family: "Catull" ,Sans-Serif;
+	-webkit-text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	-moz-text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	color:#0047F1; -webkit-animation: pulse 5s infinite alternate; }
+}
+@-webkit-keyframes pulse { 
+	0% {color: #0047F1;} 
+	25% {color: #DD172C;} 
+	50% {color: #F9A600;} 
+	75% {color: #0047F1;} 
+	100% {color: #00930E;} 
+}	
+.reveal h1.colors span.g2 {
+	font-family: "Catull" ,Sans-Serif;
+	-webkit-text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	-moz-text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	color: #45CEEF; -webkit-animation: pulse 6s infinite alternate; }
+
+}
+@-webkit-keyframes pulse { 
+	0% {color: #0047F1;} 
+	25% {color: #DD172C;} 
+	50% {color: #F9A600;} 
+	75% {color: #0047F1;} 
+	100% {color: #00930E;} 
+}	
+.reveal h1.colors span.o {
+	font-family: "Catull" ,Sans-Serif;
+	-webkit-text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	-moz-text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	color: #45CEEF; -webkit-animation: pulse 7s infinite alternate; }
+}
+@-webkit-keyframes pulse { 
+	0% {color: #0047F1;} 
+	25% {color: #DD172C;} 
+	50% {color: #F9A600;} 
+	75% {color: #0047F1;} 
+	100% {color: #00930E;} 
+}	
+.reveal h1.colors span.o2 {
+	font-family: "Catull" ,Sans-Serif;
+	-webkit-text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	-moz-text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	color: #45CEEF; -webkit-animation: pulse 8s infinite alternate; }
+}
+@-webkit-keyframes pulse { 
+	0% {color: #0047F1;} 
+	25% {color: #DD172C;} 
+	50% {color: #F9A600;} 
+	75% {color: #0047F1;} 
+	100% {color: #00930E;} 
+}		
+.reveal h1.colors span.l {
+	font-family: "Catull" ,Sans-Serif;
+	-webkit-text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	-moz-text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	color: #45CEEF; -webkit-animation: pulse 9s infinite alternate; }
+}
+@-webkit-keyframes pulse { 
+	0% {color: #0047F1;} 
+	25% {color: #DD172C;} 
+	50% {color: #F9A600;} 
+	75% {color: #0047F1;} 
+	100% {color: #00930E;} 
+}		
+.reveal h1.colors span.e {
+	font-family: "Catull" ,Sans-Serif;
+	-webkit-text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	-moz-text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	color: #45CEEF; -webkit-animation: pulse 11s infinite alternate; }
+}
+
+#heart {
+    position: relative;
+    width: 100px;
+    height: 90px;
+}
+#heart:before,
+#heart:after {
+    position: absolute;
+    content: "";
+    left: 50px;
+    top: 0;
+    width: 50px;
+    height: 80px;
+    background: #DD172C;
+    -moz-border-radius: 50px 50px 0 0;
+    border-radius: 50px 50px 0 0;
+    -webkit-transform: rotate(-45deg);
+       -moz-transform: rotate(-45deg);
+        -ms-transform: rotate(-45deg);
+         -o-transform: rotate(-45deg);
+            transform: rotate(-45deg);
+    -webkit-transform-origin: 0 100%;
+       -moz-transform-origin: 0 100%;
+        -ms-transform-origin: 0 100%;
+         -o-transform-origin: 0 100%;
+            transform-origin: 0 100%;
+}
+#heart:after {
+    left: 0;
+    -webkit-transform: rotate(45deg);
+       -moz-transform: rotate(45deg);
+        -ms-transform: rotate(45deg);
+         -o-transform: rotate(45deg);
+            transform: rotate(45deg);
+    -webkit-transform-origin: 100% 100%;
+       -moz-transform-origin: 100% 100%;
+        -ms-transform-origin: 100% 100%;
+         -o-transform-origin: 100% 100%;
+            transform-origin :100% 100%;
+}
+.reveal h2.thanks {
+	text-shadow:0px 3px 3px rgba(0,0,0,0.25);
+	letter-spacing: 0.01em;
+}
+span.t {
+	font-family: "Catull" ,Sans-Serif;
+	-webkit-text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	-moz-text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	color:#0047F1;
+}
+span.h {
+	font-family: "Catull" ,Sans-Serif;
+	-webkit-text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	-moz-text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	color:#DD172C;
+}
+span.a {
+	font-family: "Catull" ,Sans-Serif;
+	-webkit-text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	-moz-text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	color:#F9A600;
+}
+span.n {
+	font-family: "Catull" ,Sans-Serif;
+	-webkit-text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	-moz-text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	color:#0047F1;
+}
+span.k {
+	font-family: "Catull" ,Sans-Serif;
+	-webkit-text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	-moz-text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	color:#00930E;
+}
+span.y {
+	font-family: "Catull" ,Sans-Serif;
+	-webkit-text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	-moz-text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	color:#E61B31;
+}
+span.o {
+	font-family: "Catull" ,Sans-Serif;
+	-webkit-text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	-moz-text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	color:#00930E;
+}
+span.u {
+	font-family: "Catull" ,Sans-Serif;
+	-webkit-text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	-moz-text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	text-shadow: 0px 3px 3px rgba(0,0,0,0.25);
+	color:#F9A600;
+}
+
+/* color key GWD50 005723
+Google - 0047F1 DD172C F9A600 0047F1 00930E E61B31
+*/
+
+/* color key GWD50 005723
+Normal - 008F0B - Green | A68B08 - Yellow | 9C2500 - Red | 70089C - Purple | 0865A6 - Blue
+Inverted - FF70F4 - Pink | 5974F7 - Blue | 63DAFF - Teal | 8FF763 - Green | F79A59 - Orange
+/*
+  

BIN
public/css/font/Catull.ttf


BIN
public/css/font/league_gothic-webfont.eot


File diff suppressed because it is too large
+ 230 - 0
public/css/font/league_gothic-webfont.svg


BIN
public/css/font/league_gothic-webfont.ttf


BIN
public/css/font/league_gothic-webfont.woff


+ 2 - 0
public/css/font/league_gothic_license

@@ -0,0 +1,2 @@
+SIL Open Font License (OFL)
+http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL

File diff suppressed because it is too large
+ 7 - 0
public/css/reveal.min.css


File diff suppressed because it is too large
+ 69 - 0
public/index.html


File diff suppressed because it is too large
+ 8 - 0
public/js/head.min.js


+ 7 - 0
public/js/html5shiv.js

@@ -0,0 +1,7 @@
+document.createElement('header');
+document.createElement('nav');
+document.createElement('section');
+document.createElement('article');
+document.createElement('aside');
+document.createElement('footer');
+document.createElement('hgroup');

+ 28 - 0
public/js/init.js

@@ -0,0 +1,28 @@
+$(function () {
+    $('.animated-gif').each(function (i, e) {
+        disableGif(e)
+    });
+});
+
+Reveal.addEventListener('slidechanged', initAnimatedGifs);
+Reveal.addEventListener('ready', initAnimatedGifs);
+
+function initAnimatedGifs(event) {
+    $('.animated-gif', event.currentSlide).each(function (i, e) {
+        enableGif(e)
+    });
+    if (event.previousSlide)
+        $('.animated-gif', event.previousSlide).each(function (i, e) {
+            disableGif(e)
+        });
+}
+
+function enableGif(e) {
+    var src = $(e).attr("src")
+    $(e).attr('src', src.replace('-image.gif', '.gif'));
+}
+
+function disableGif(e) {
+    var src = $(e).attr("src")
+    $(e).attr('src', src.replace('.gif', '-image.gif'));
+}

File diff suppressed because it is too large
+ 14 - 0
public/js/plugin/highlight/highlight.js


+ 37 - 0
public/js/plugin/markdown/markdown.js

@@ -0,0 +1,37 @@
+// From https://gist.github.com/1343518
+// Modified by Hakim to handle Markdown indented with tabs
+(function(){
+
+    if( typeof Showdown === 'undefined' ) {
+        throw 'The reveal.js Markdown plugin requires Showdown to be loaded';
+    }
+
+    var sections = document.querySelectorAll( '[data-markdown]' );
+
+    for( var i = 0, len = sections.length; i < len; i++ ) {
+        var section = sections[i];
+        var notes = section.querySelector( 'aside.notes' );
+
+        var template = section.querySelector( 'script' );
+
+        // strip leading whitespace so it isn't evaluated as code
+        var text = ( template || section ).innerHTML;
+
+        var leadingWs = text.match(/^\n?(\s*)/)[1].length,
+            leadingTabs = text.match(/^\n?(\t*)/)[1].length;
+
+        if( leadingTabs > 0 ) {
+            text = text.replace( new RegExp('\\n?\\t{' + leadingTabs + '}','g'), '\n' );
+        }
+        else if( leadingWs > 1 ) {
+            text = text.replace( new RegExp('\\n? {' + leadingWs + '}','g'), '\n' );
+        }
+
+        section.innerHTML = (new Showdown.converter()).makeHtml(text);
+
+        if( notes ) {
+            section.appendChild( notes );
+        }
+    }
+
+})();

File diff suppressed because it is too large
+ 62 - 0
public/js/plugin/markdown/showdown.js


+ 57 - 0
public/js/plugin/notes-server/client.js

@@ -0,0 +1,57 @@
+(function() {
+	// don't emit events from inside the previews themselves
+	if ( window.location.search.match( /receiver/gi ) ) { return; }
+
+	var socket = io.connect(window.location.origin);
+	var socketId = Math.random().toString().slice(2);
+	
+	console.log('View slide notes at ' + window.location.origin + '/notes/' + socketId);
+	window.open(window.location.origin + '/notes/' + socketId, 'notes-' + socketId);
+
+	// Fires when a fragment is shown
+	Reveal.addEventListener( 'fragmentshown', function( event ) {
+		var fragmentData = {
+			fragment : 'next',
+			socketId : socketId
+		};
+		socket.emit('fragmentchanged', fragmentData);
+	} );
+
+	// Fires when a fragment is hidden
+	Reveal.addEventListener( 'fragmenthidden', function( event ) {
+		var fragmentData = {
+			fragment : 'previous',
+			socketId : socketId
+		};
+		socket.emit('fragmentchanged', fragmentData);
+	} );
+
+	// Fires when slide is changed
+	Reveal.addEventListener( 'slidechanged', function( event ) {
+		var nextindexh;
+		var nextindexv;
+		var slideElement = event.currentSlide;
+
+		if (slideElement.nextElementSibling && slideElement.parentNode.nodeName == 'SECTION') {
+			nextindexh = event.indexh;
+			nextindexv = event.indexv + 1;
+		} else {
+			nextindexh = event.indexh + 1;
+			nextindexv = 0;
+		}
+
+		var notes = slideElement.querySelector('aside.notes');
+		var slideData = {
+			notes : notes ? notes.innerHTML : '',
+			indexh : event.indexh,
+			indexv : event.indexv,
+			nextindexh : nextindexh,
+			nextindexv : nextindexv,
+			socketId : socketId,
+			markdown : notes ? typeof notes.getAttribute('data-markdown') === 'string' : false
+
+		};
+
+		socket.emit('slidechanged', slideData);
+	} );
+}());

+ 58 - 0
public/js/plugin/notes-server/index.js

@@ -0,0 +1,58 @@
+var express   = require('express');
+var fs        = require('fs');
+var io        = require('socket.io');
+var _         = require('underscore');
+var Mustache  = require('mustache');
+
+var app       = express.createServer();
+var staticDir = express.static;
+
+io            = io.listen(app);
+
+var opts = {
+	port :      1947,
+	baseDir :   __dirname + '/../../'
+};
+
+io.sockets.on('connection', function(socket) {
+	socket.on('slidechanged', function(slideData) {
+		socket.broadcast.emit('slidedata', slideData);
+	});
+	socket.on('fragmentchanged', function(fragmentData) {
+		socket.broadcast.emit('fragmentdata', fragmentData);
+	});
+});
+
+app.configure(function() {
+	[ 'css', 'js', 'images', 'plugin', 'lib' ].forEach(function(dir) {
+		app.use('/' + dir, staticDir(opts.baseDir + dir));
+	});
+});
+
+app.get("/", function(req, res) {
+	fs.createReadStream(opts.baseDir + '/index.html').pipe(res);
+});
+
+app.get("/notes/:socketId", function(req, res) {
+
+	fs.readFile(opts.baseDir + 'plugin/notes-server/notes.html', function(err, data) {
+		res.send(Mustache.to_html(data.toString(), {
+			socketId : req.params.socketId
+		}));
+	});
+	// fs.createReadStream(opts.baseDir + 'notes-server/notes.html').pipe(res);
+});
+
+// Actually listen
+app.listen(opts.port || null);
+
+var brown = '\033[33m',
+	green = '\033[32m',
+	reset = '\033[0m';
+
+var slidesLocation = "http://localhost" + ( opts.port ? ( ':' + opts.port ) : '' );
+
+console.log( brown + "reveal.js - Speaker Notes" + reset );
+console.log( "1. Open the slides at " + green + slidesLocation + reset );
+console.log( "2. Click on the link your JS console to go to the notes page" );
+console.log( "3. Advance through your slides and your notes will advance automatically" );

+ 139 - 0
public/js/plugin/notes-server/notes.html

@@ -0,0 +1,139 @@
+<!doctype html>
+<html lang="en">
+	<head>
+		<meta charset="utf-8">
+
+		<title>reveal.js - Slide Notes</title>
+
+		<style>
+			body {
+				font-family: Helvetica;
+			}
+
+			#notes {
+				font-size: 24px;
+				width: 640px;
+				margin-top: 5px;
+			}
+
+			#wrap-current-slide {
+				width: 640px;
+				height: 512px;
+				float: left;
+				overflow: hidden;
+			}
+
+			#current-slide {
+				width: 1280px;
+				height: 1024px;
+				border: none;
+				
+				-webkit-transform-origin: 0 0;
+				   -moz-transform-origin: 0 0;
+				    -ms-transform-origin: 0 0;
+				     -o-transform-origin: 0 0;
+				        transform-origin: 0 0;
+				 
+				-webkit-transform: scale(0.5);
+				   -moz-transform: scale(0.5);
+				    -ms-transform: scale(0.5);
+				     -o-transform: scale(0.5);
+				        transform: scale(0.5);
+			}
+
+			#wrap-next-slide {
+				width: 448px;
+				height: 358px;
+				float: left;
+				margin: 0 0 0 10px;
+				overflow: hidden;
+			}
+
+			#next-slide {
+				width: 1280px;
+				height: 1024px;
+				border: none;
+				
+				-webkit-transform-origin: 0 0;
+				   -moz-transform-origin: 0 0;
+				    -ms-transform-origin: 0 0;
+				     -o-transform-origin: 0 0;
+				        transform-origin: 0 0;
+
+				-webkit-transform: scale(0.35);
+				   -moz-transform: scale(0.35);
+				    -ms-transform: scale(0.35);
+				     -o-transform: scale(0.35);
+				        transform: scale(0.35);
+			}
+
+			.slides {
+				position: relative;
+				margin-bottom: 10px;
+				border: 1px solid black;
+				border-radius: 2px;
+				background: rgb(28, 30, 32);
+			}
+
+			.slides span {
+				position: absolute;
+				top: 3px;
+				left: 3px;
+				font-weight: bold;
+				font-size: 14px;
+				color: rgba( 255, 255, 255, 0.9 );
+			}
+		</style>
+	</head>
+
+	<body>
+
+		<div id="wrap-current-slide" class="slides">
+			<iframe src="/?receiver" width="1280" height="1024" id="current-slide"></iframe>
+		</div>
+
+		<div id="wrap-next-slide" class="slides">
+			<iframe src="/?receiver" width="640" height="512" id="next-slide"></iframe>
+			<span>UPCOMING:</span>
+		</div>
+		<div id="notes"></div>
+
+		<script src="/socket.io/socket.io.js"></script>
+		<script src="/plugin/markdown/showdown.js"></script>
+
+		<script>
+		var socketId = '{{socketId}}';
+		var socket = io.connect(window.location.origin);
+		var notes = document.getElementById('notes');
+		var currentSlide = document.getElementById('current-slide');
+		var nextSlide = document.getElementById('next-slide');
+
+		socket.on('slidedata', function(data) {
+			// ignore data from sockets that aren't ours
+			if (data.socketId !== socketId) { return; }
+
+			if (data.markdown) {
+				notes.innerHTML = (new Showdown.converter()).makeHtml(data.notes);
+			}
+			else {
+				notes.innerHTML = data.notes;
+			}
+
+			currentSlide.contentWindow.Reveal.slide(data.indexh, data.indexv);
+			nextSlide.contentWindow.Reveal.slide(data.nextindexh, data.nextindexv);
+		});
+		socket.on('fragmentdata', function(data) {
+			// ignore data from sockets that aren't ours
+			if (data.socketId !== socketId) { return; }
+
+			if (data.fragment === 'next') {
+				currentSlide.contentWindow.Reveal.nextFragment();
+			}
+			else if (data.fragment === 'previous') {
+				currentSlide.contentWindow.Reveal.prevFragment();
+			}
+		});
+		</script>
+
+	</body>
+</html>

+ 143 - 0
public/js/plugin/notes/notes.html

@@ -0,0 +1,143 @@
+<!doctype html>
+<html lang="en">
+	<head>
+		<meta charset="utf-8">
+
+		<title>reveal.js - Slide Notes</title>
+
+		<style>
+			body {
+				font-family: Helvetica;
+			}
+
+			#notes {
+				font-size: 24px;
+				width: 640px;
+				margin-top: 5px;
+			}
+
+			#wrap-current-slide {
+				width: 640px;
+				height: 512px;
+				float: left;
+				overflow: hidden;
+			}
+
+			#current-slide {
+				width: 1280px;
+				height: 1024px;
+				border: none;
+
+				-webkit-transform-origin: 0 0;
+					 -moz-transform-origin: 0 0;
+						-ms-transform-origin: 0 0;
+						 -o-transform-origin: 0 0;
+								transform-origin: 0 0;
+
+				-webkit-transform: scale(0.5);
+					 -moz-transform: scale(0.5);
+						-ms-transform: scale(0.5);
+						 -o-transform: scale(0.5);
+								transform: scale(0.5);
+			}
+
+			#wrap-next-slide {
+				width: 448px;
+				height: 358px;
+				float: left;
+				margin: 0 0 0 10px;
+				overflow: hidden;
+			}
+
+			#next-slide {
+				width: 1280px;
+				height: 1024px;
+				border: none;
+
+				-webkit-transform-origin: 0 0;
+					 -moz-transform-origin: 0 0;
+						-ms-transform-origin: 0 0;
+						 -o-transform-origin: 0 0;
+								transform-origin: 0 0;
+
+				-webkit-transform: scale(0.35);
+					 -moz-transform: scale(0.35);
+						-ms-transform: scale(0.35);
+						 -o-transform: scale(0.35);
+								transform: scale(0.35);
+			}
+
+			.slides {
+				position: relative;
+				margin-bottom: 10px;
+				border: 1px solid black;
+				border-radius: 2px;
+				background: rgb(28, 30, 32);
+			}
+
+			.slides span {
+				position: absolute;
+				top: 3px;
+				left: 3px;
+				font-weight: bold;
+				font-size: 14px;
+				color: rgba( 255, 255, 255, 0.9 );
+			}
+		</style>
+	</head>
+
+	<body>
+
+		<div id="wrap-current-slide" class="slides">
+			<iframe src="../../index.html" width="1280" height="1024" id="current-slide"></iframe>
+		</div>
+
+		<div id="wrap-next-slide" class="slides">
+			<iframe src="../../index.html" width="640" height="512" id="next-slide"></iframe>
+			<span>UPCOMING:</span>
+		</div>
+		<div id="notes"></div>
+
+		<script src="../../plugin/markdown/showdown.js"></script>
+		<script>
+			window.addEventListener( 'load', function() {
+
+				(function( window, undefined ) {
+					var notes = document.getElementById( 'notes' ),
+						currentSlide = document.getElementById( 'current-slide' ),
+						nextSlide = document.getElementById( 'next-slide' );
+
+					window.addEventListener( 'message', function( event ) {
+						var data = JSON.parse( event.data );
+						// No need for updating the notes in case of fragment changes
+						if ( data.notes !== undefined) {
+							if( data.markdown ) {
+								notes.innerHTML = (new Showdown.converter()).makeHtml( data.notes );
+							}
+							else {
+								notes.innerHTML = data.notes;
+							}
+						}
+
+						// Showing and hiding fragments
+						if( data.fragment === 'next' ) {
+							currentSlide.contentWindow.Reveal.nextFragment();
+						}
+						else if( data.fragment === 'prev' ) {
+							currentSlide.contentWindow.Reveal.prevFragment();
+						}
+						else {
+							// Update the note slides
+							currentSlide.contentWindow.Reveal.slide( data.indexh, data.indexv );
+							nextSlide.contentWindow.Reveal.slide( data.nextindexh, data.nextindexv );
+						}
+
+					}, false );
+
+				})( window );
+
+			}, false );
+
+		</script>
+	</body>
+</html>

+ 98 - 0
public/js/plugin/notes/notes.js

@@ -0,0 +1,98 @@
+/**
+ * Handles opening of and synchronization with the reveal.js
+ * notes window.
+ */
+var RevealNotes = (function() {
+
+	function openNotes() {
+		var notesPopup = window.open( 'plugin/notes/notes.html', 'reveal.js - Notes', 'width=1120,height=850' );
+
+		// Fires when slide is changed
+		Reveal.addEventListener( 'slidechanged', function( event ) {
+			post('slidechanged');
+		} );
+
+		// Fires when a fragment is shown
+		Reveal.addEventListener( 'fragmentshown', function( event ) {
+			post('fragmentshown');
+		} );
+
+		// Fires when a fragment is hidden
+		Reveal.addEventListener( 'fragmenthidden', function( event ) {
+			post('fragmenthidden');
+		} );
+
+		/**
+		 * Posts the current slide data to the notes window
+		 *
+		 * @param {String} eventType Expecting 'slidechanged', 'fragmentshown' 
+		 * or 'fragmenthidden' set in the events above to define the needed 
+		 * slideDate.
+		 */
+		function post( eventType ) {
+			var slideElement = Reveal.getCurrentSlide(),
+				messageData;
+
+			if( eventType === 'slidechanged' ) {
+				var notes = slideElement.querySelector( 'aside.notes' ),
+					indexh = Reveal.getIndices().h,
+					indexv = Reveal.getIndices().v,
+					nextindexh,
+					nextindexv;
+
+				if( slideElement.nextElementSibling && slideElement.parentNode.nodeName == 'SECTION' ) {
+					nextindexh = indexh;
+					nextindexv = indexv + 1;
+				} else {
+					nextindexh = indexh + 1;
+					nextindexv = 0;
+				}
+
+				messageData = {
+					notes : notes ? notes.innerHTML : '',
+					indexh : indexh,
+					indexv : indexv,
+					nextindexh : nextindexh,
+					nextindexv : nextindexv,
+					markdown : notes ? typeof notes.getAttribute( 'data-markdown' ) === 'string' : false
+				};
+			}
+			else if( eventType === 'fragmentshown' ) {
+				messageData = {
+					fragment : 'next'
+				};
+			}
+			else if( eventType === 'fragmenthidden' ) {
+				messageData = {
+					fragment : 'prev'
+				};
+			}
+
+			notesPopup.postMessage( JSON.stringify( messageData ), '*' );
+		}
+
+		// Navigate to the current slide when the notes are loaded
+		notesPopup.addEventListener( 'load', function( event ) {
+			post('slidechanged');
+		}, false );
+	}
+
+	// If the there's a 'notes' query set, open directly
+	if( window.location.search.match( /(\?|\&)notes/gi ) !== null ) {
+		openNotes();
+	}
+
+	// Open the notes when the 's' key is hit
+	document.addEventListener( 'keydown', function( event ) {
+		// Disregard the event if the target is editable or a
+		// modifier is present
+		if ( document.querySelector( ':focus' ) !== null || event.shiftKey || event.altKey || event.ctrlKey || event.metaKey ) return;
+
+		if( event.keyCode === 83 ) {
+			event.preventDefault();
+			openNotes();
+		}
+	}, false );
+
+	return { open: openNotes };
+})();

+ 39 - 0
public/js/plugin/postmessage/example.html

@@ -0,0 +1,39 @@
+<html>
+	<body>
+
+		<iframe id="reveal" src="../../index.html" style="border: 0;" width="500" height="500"></iframe>
+
+		<div>
+			<input id="back" type="button" value="go back"/>
+			<input id="ahead" type="button" value="go ahead"/>
+			<input id="slideto" type="button" value="slideto 2-2"/>
+		</div>
+
+		<script>
+
+			(function (){
+
+				var back = document.getElementById( 'back' ),
+						ahead = document.getElementById( 'ahead' ),
+						slideto = document.getElementById( 'slideto' ),
+						reveal =  window.frames[0];
+
+					back.addEventListener( 'click', function () {
+						
+					reveal.postMessage( JSON.stringify({method: 'prev', args: []}), '*' );
+				}, false );
+
+				ahead.addEventListener( 'click', function (){
+					reveal.postMessage( JSON.stringify({method: 'next', args: []}), '*' );
+				}, false );
+
+				slideto.addEventListener( 'click', function (){
+					reveal.postMessage( JSON.stringify({method: 'slide', args: [2,2]}), '*' );
+				}, false );
+
+			}());
+
+		</script>
+
+	</body>
+</html>

+ 42 - 0
public/js/plugin/postmessage/postmessage.js

@@ -0,0 +1,42 @@
+/*
+
+	simple postmessage plugin
+
+	Useful when a reveal slideshow is inside an iframe.
+	It allows to call reveal methods from outside.
+
+	Example:
+		 var reveal =  window.frames[0];
+
+		 // Reveal.prev(); 
+		 reveal.postMessage(JSON.stringify({method: 'prev', args: []}), '*');
+		 // Reveal.next(); 
+		 reveal.postMessage(JSON.stringify({method: 'next', args: []}), '*');
+		 // Reveal.slide(2, 2); 
+		 reveal.postMessage(JSON.stringify({method: 'slide', args: [2,2]}), '*');
+
+	Add to the slideshow:
+
+		dependencies: [
+			...
+			{ src: 'plugin/postmessage/postmessage.js', async: true, condition: function() { return !!document.body.classList; } }
+		]
+
+*/
+
+(function (){
+
+	window.addEventListener( "message", function ( event ) {
+		var data = JSON.parse( event.data ),
+				method = data.method,
+				args = data.args;
+
+		if( typeof Reveal[method] === 'function' ) {
+			Reveal[method].apply( Reveal, data.args );
+		}
+	}, false);
+
+}());
+
+
+

+ 19 - 0
public/js/plugin/remotes/remotes.js

@@ -0,0 +1,19 @@
+/**
+ * Touch-based remote controller for your presentation courtesy 
+ * of the folks at http://remotes.io
+ */
+
+head.ready( 'remotes.ne.min.js', function() {
+	
+	new Remotes("preview")
+		.on("swipe-left", function(e){ Reveal.right(); })
+		.on("swipe-right", function(e){ Reveal.left(); })
+		.on("swipe-up", function(e){ Reveal.down(); })
+		.on("swipe-down", function(e){ Reveal.up(); })
+		.on("tap", function(e){ 
+			Reveal.toggleOverview(); 
+		});
+
+} );
+
+head.js( 'https://raw.github.com/Remotes/Remotes/master/dist/remotes.ne.min.js' );

+ 251 - 0
public/js/plugin/zoom-js/zoom.js

@@ -0,0 +1,251 @@
+// Custom reveal.js integration
+(function(){
+	document.querySelector( '.reveal' ).addEventListener( 'click', function( event ) {
+		if( event.altKey ) {
+			event.preventDefault();
+			zoom.to({ element: event.target, pan: false });
+		}
+	} );
+})();
+
+/*!
+ * zoom.js 0.2 (modified version for use with reveal.js)
+ * http://lab.hakim.se/zoom-js
+ * MIT licensed
+ * 
+ * Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se
+ */
+var zoom = (function(){
+
+	// The current zoom level (scale)
+	var level = 1;
+	
+	// The current mouse position, used for panning
+	var mouseX = 0,
+		mouseY = 0;
+	
+	// Timeout before pan is activated
+	var panEngageTimeout = -1,
+		panUpdateInterval = -1;
+
+	var currentOptions = null;
+
+	// Check for transform support so that we can fallback otherwise
+	var supportsTransforms = 	'WebkitTransform' in document.body.style ||
+								'MozTransform' in document.body.style ||
+								'msTransform' in document.body.style ||
+								'OTransform' in document.body.style ||
+								'transform' in document.body.style;
+    
+	if( supportsTransforms ) {
+		// The easing that will be applied when we zoom in/out
+		document.body.style.transition = 'transform 0.8s ease';
+		document.body.style.OTransition = '-o-transform 0.8s ease';
+		document.body.style.msTransition = '-ms-transform 0.8s ease';
+		document.body.style.MozTransition = '-moz-transform 0.8s ease';
+		document.body.style.WebkitTransition = '-webkit-transform 0.8s ease';
+	}
+	
+	// Zoom out if the user hits escape
+	document.addEventListener( 'keyup', function( event ) {
+		if( level !== 1 && event.keyCode === 27 ) {
+			zoom.out();
+		}
+	}, false );
+
+	// Monitor mouse movement for panning
+	document.addEventListener( 'mousemove', function( event ) {
+		if( level !== 1 ) {
+			mouseX = event.clientX;
+			mouseY = event.clientY;
+		}
+	}, false );
+
+	/**
+	 * Applies the CSS required to zoom in, prioritizes use of CSS3 
+	 * transforms but falls back on zoom for IE.
+	 * 
+	 * @param {Number} pageOffsetX 
+	 * @param {Number} pageOffsetY 
+	 * @param {Number} elementOffsetX 
+	 * @param {Number} elementOffsetY 
+	 * @param {Number} scale 
+	 */
+	function magnify( pageOffsetX, pageOffsetY, elementOffsetX, elementOffsetY, scale ) {
+
+		if( supportsTransforms ) {
+			var origin = pageOffsetX +'px '+ pageOffsetY +'px',
+				transform = 'translate('+ -elementOffsetX +'px,'+ -elementOffsetY +'px) scale('+ scale +')';
+			
+			document.body.style.transformOrigin = origin;
+			document.body.style.OTransformOrigin = origin;
+			document.body.style.msTransformOrigin = origin;
+			document.body.style.MozTransformOrigin = origin;
+			document.body.style.WebkitTransformOrigin = origin;
+
+			document.body.style.transform = transform;
+			document.body.style.OTransform = transform;
+			document.body.style.msTransform = transform;
+			document.body.style.MozTransform = transform;
+			document.body.style.WebkitTransform = transform;
+		}
+		else {
+			// Reset all values
+			if( scale === 1 ) {
+				document.body.style.position = '';
+				document.body.style.left = '';
+				document.body.style.top = '';
+				document.body.style.width = '';
+				document.body.style.height = '';
+				document.body.style.zoom = '';
+			}
+			// Apply scale
+			else {
+				document.body.style.position = 'relative';
+				document.body.style.left = ( - ( pageOffsetX + elementOffsetX ) / scale ) + 'px';
+				document.body.style.top = ( - ( pageOffsetY + elementOffsetY ) / scale ) + 'px';
+				document.body.style.width = ( scale * 100 ) + '%';
+				document.body.style.height = ( scale * 100 ) + '%';
+				document.body.style.zoom = scale;
+			}
+		}
+
+		level = scale;
+
+		if( level !== 1 && document.documentElement.classList ) {
+			document.documentElement.classList.add( 'zoomed' );
+		}
+		else {
+			document.documentElement.classList.remove( 'zoomed' );
+		}
+	}
+
+	/**
+	 * Pan the document when the mosue cursor approaches the edges 
+	 * of the window.
+	 */
+	function pan() {
+		var range = 0.12,
+			rangeX = window.innerWidth * range,
+			rangeY = window.innerHeight * range,
+			scrollOffset = getScrollOffset();
+		
+		// Up
+		if( mouseY < rangeY ) {
+			window.scroll( scrollOffset.x, scrollOffset.y - ( 1 - ( mouseY / rangeY ) ) * ( 14 / level ) );
+		}
+		// Down
+		else if( mouseY > window.innerHeight - rangeY ) {
+			window.scroll( scrollOffset.x, scrollOffset.y + ( 1 - ( window.innerHeight - mouseY ) / rangeY ) * ( 14 / level ) );
+		}
+
+		// Left
+		if( mouseX < rangeX ) {
+			window.scroll( scrollOffset.x - ( 1 - ( mouseX / rangeX ) ) * ( 14 / level ), scrollOffset.y );
+		}
+		// Right
+		else if( mouseX > window.innerWidth - rangeX ) {
+			window.scroll( scrollOffset.x + ( 1 - ( window.innerWidth - mouseX ) / rangeX ) * ( 14 / level ), scrollOffset.y );
+		}
+	}
+
+	function getScrollOffset() {
+		return {
+			x: window.scrollX !== undefined ? window.scrollX : window.pageXOffset,
+			y: window.scrollY !== undefined ? window.scrollY : window.pageXYffset
+		}
+	}
+
+	return {
+		/**
+		 * Zooms in on either a rectangle or HTML element.
+		 * 
+		 * @param {Object} options
+		 *   - element: HTML element to zoom in on
+		 *   OR
+		 *   - x/y: coordinates in non-transformed space to zoom in on
+		 *   - width/height: the portion of the screen to zoom in on
+		 *   - scale: can be used instead of width/height to explicitly set scale
+		 */
+		to: function( options ) {
+			// Due to an implementation limitation we can't zoom in
+			// to another element without zooming out first
+			if( level !== 1 ) {
+				zoom.out();
+			}
+			else {
+				options.x = options.x || 0;
+				options.y = options.y || 0;
+
+				// If an element is set, that takes precedence
+				if( !!options.element ) {
+					// Space around the zoomed in element to leave on screen
+					var padding = 20;
+
+					options.width = options.element.getBoundingClientRect().width + ( padding * 2 );
+					options.height = options.element.getBoundingClientRect().height + ( padding * 2 );
+					options.x = options.element.getBoundingClientRect().left - padding;
+					options.y = options.element.getBoundingClientRect().top - padding;
+				}
+
+				// If width/height values are set, calculate scale from those values
+				if( options.width !== undefined && options.height !== undefined ) {
+					options.scale = Math.max( Math.min( window.innerWidth / options.width, window.innerHeight / options.height ), 1 );
+				}
+
+				if( options.scale > 1 ) {
+					options.x *= options.scale;
+					options.y *= options.scale;
+
+					var scrollOffset = getScrollOffset();
+
+					if( options.element ) {
+						scrollOffset.x -= ( window.innerWidth - ( options.width * options.scale ) ) / 2;
+					}
+
+					magnify( scrollOffset.x, scrollOffset.y, options.x, options.y, options.scale );
+
+					if( options.pan !== false ) {
+
+						// Wait with engaging panning as it may conflict with the
+						// zoom transition
+						panEngageTimeout = setTimeout( function() {
+							panUpdateInterval = setInterval( pan, 1000 / 60 );
+						}, 800 );
+
+					}
+				}
+
+				currentOptions = options;
+			}
+		},
+
+		/**
+		 * Resets the document zoom state to its default.
+		 */
+		out: function() {
+			clearTimeout( panEngageTimeout );
+			clearInterval( panUpdateInterval );
+
+			var scrollOffset = getScrollOffset();
+
+			if( currentOptions && currentOptions.element ) {
+				scrollOffset.x -= ( window.innerWidth - ( currentOptions.width * currentOptions.scale ) ) / 2;
+			}
+			
+			magnify( scrollOffset.x, scrollOffset.y, 0, 0, 1 );
+
+			level = 1;
+		},
+
+		// Alias
+		magnify: function( options ) { this.to( options ) },
+		reset: function() { this.out() },
+		
+		zoomLevel: function() {
+			return level;
+		}
+	}
+	
+})();
+

File diff suppressed because it is too large
+ 9 - 0
public/js/reveal.min.js