David Banham
12 years ago
9 changed files with 285 additions and 30 deletions
@ -1,20 +1,30 @@ |
|||
{ |
|||
"author": "Hakim El Hattab", |
|||
"name": "reveal.js", |
|||
"description": "HTML5 Slideware with Presenter Notes", |
|||
"version": "1.5.0", |
|||
"repository": { |
|||
"type": "git", |
|||
"url": "git://github.com/hakimel/reveal.js.git" |
|||
}, |
|||
"engines": { |
|||
"node": "~0.6.8" |
|||
}, |
|||
"dependencies": { |
|||
"underscore" : "1.3.3", |
|||
"express" : "2.5.9", |
|||
"socket.io" : "0.9.6", |
|||
"mustache" : "0.4.0" |
|||
}, |
|||
"devDependencies": {} |
|||
"author": "Hakim El Hattab", |
|||
"name": "reveal.js", |
|||
"description": "HTML5 Slideware with Presenter Notes", |
|||
"version": "1.5.1", |
|||
"repository": { |
|||
"type": "git", |
|||
"url": "git://github.com/hakimel/reveal.js.git" |
|||
}, |
|||
"engines": { |
|||
"node": "0.8.*" |
|||
}, |
|||
"scripts": { |
|||
"start": "node ./plugin/multiplex/index.js" |
|||
}, |
|||
"licenses": [ |
|||
{ |
|||
"type": "MIT", |
|||
"url": "https://github.com/hakimel/reveal.js/raw/master/LICENSE" |
|||
} |
|||
], |
|||
"dependencies": { |
|||
"underscore": "1.3.3", |
|||
"express": "2.5.9", |
|||
"socket.io": "0.9.6", |
|||
"mustache": "0.4.0" |
|||
}, |
|||
"devDependencies": {}, |
|||
"subdomain": "revealjs" |
|||
} |
|||
|
@ -0,0 +1,12 @@ |
|||
(function() { |
|||
var socketId = multiplex.id; |
|||
var socket = io.connect(multiplex.url); |
|||
|
|||
socket.on(multiplex.id, function(data) { |
|||
// ignore data from sockets that aren't ours
|
|||
if (data.socketId !== socketId) { return; } |
|||
if( window.location.host === 'localhost:1947' ) return; |
|||
|
|||
Reveal.navigateTo(data.indexh, data.indexv, false); |
|||
}); |
|||
}()); |
@ -0,0 +1,62 @@ |
|||
var express = require('express'); |
|||
var fs = require('fs'); |
|||
var io = require('socket.io'); |
|||
var _ = require('underscore'); |
|||
var Mustache = require('mustache'); |
|||
var crypto = require('crypto'); |
|||
|
|||
var app = express.createServer(); |
|||
var staticDir = express.static; |
|||
|
|||
io = io.listen(app); |
|||
|
|||
var opts = { |
|||
port : 1948, |
|||
baseDir : __dirname + '/../../' |
|||
}; |
|||
|
|||
io.sockets.on('connection', function(socket) { |
|||
socket.on('slidechanged', function(slideData) { |
|||
console.log(slideData); |
|||
if (createHash(slideData.secret) === slideData.socketId) { |
|||
slideData.secret = null; |
|||
socket.broadcast.emit(slideData.socketId, slideData); |
|||
}; |
|||
}); |
|||
}); |
|||
|
|||
app.configure(function() { |
|||
[ 'css', 'js', '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("/token", function(req,res) { |
|||
var ts = new Date().getTime(); |
|||
var rand = Math.floor(Math.random()*9999999); |
|||
var secret = ts.toString() + rand.toString(); |
|||
res.send({secret: secret, socketId: createHash(secret)}); |
|||
}); |
|||
|
|||
var createHash = function(secret) { |
|||
var cipher = crypto.createCipher('blowfish', secret); |
|||
return(cipher.final('hex')); |
|||
}; |
|||
|
|||
// 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" ); |
@ -0,0 +1,32 @@ |
|||
(function() { |
|||
// don't emit events from inside the previews themselves
|
|||
if ( window.location.search.match( /receiver/gi ) ) { return; } |
|||
|
|||
var socket = io.connect(multiplex.url); |
|||
|
|||
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 = { |
|||
indexh : event.indexh, |
|||
indexv : event.indexv, |
|||
nextindexh : nextindexh, |
|||
nextindexv : nextindexv, |
|||
secret: multiplex.secret, |
|||
socketId : multiplex.id |
|||
}; |
|||
|
|||
socket.emit('slidechanged', slideData); |
|||
} ); |
|||
}()); |
@ -0,0 +1,109 @@ |
|||
<!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; |
|||
-moz-transform: scale(0.5); |
|||
-moz-transform-origin: 0 0; |
|||
-o-transform: scale(0.5); |
|||
-o-transform-origin: 0 0; |
|||
-webkit-transform: scale(0.5); |
|||
-webkit-transform-origin: 0 0; |
|||
} |
|||
|
|||
#wrap-next-slide { |
|||
width: 320px; |
|||
height: 256px; |
|||
float: left; |
|||
margin: 0 0 0 10px; |
|||
overflow: hidden; |
|||
} |
|||
|
|||
#next-slide { |
|||
width: 1280px; |
|||
height: 1024px; |
|||
border: none; |
|||
-moz-transform: scale(0.25); |
|||
-moz-transform-origin: 0 0; |
|||
-o-transform: scale(0.25); |
|||
-o-transform-origin: 0 0; |
|||
-webkit-transform: scale(0.25); |
|||
-webkit-transform-origin: 0 0; |
|||
} |
|||
|
|||
.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> |
|||
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; } |
|||
|
|||
notes.innerHTML = data.notes; |
|||
currentSlide.contentWindow.Reveal.navigateTo(data.indexh, data.indexv); |
|||
nextSlide.contentWindow.Reveal.navigateTo(data.nextindexh, data.nextindexv); |
|||
}); |
|||
</script> |
|||
|
|||
</body> |
|||
</html> |
Loading…
Reference in new issue