new postMessage-based notes plugin, moved node-based notes to notes-server (#190)

This commit is contained in:
Hakim El Hattab
2012-10-20 20:40:52 -04:00
7 changed files with 253 additions and 29 deletions

View File

@ -35,4 +35,4 @@
socket.emit('slidechanged', slideData);
} );
}());
}());

View File

@ -32,12 +32,12 @@ app.get("/", function(req, res) {
app.get("/notes/:socketId", function(req, res) {
fs.readFile(opts.baseDir + 'plugin/speakernotes/notes.html', function(err, data) {
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 + 'speakernotes/notes.html').pipe(res);
// fs.createReadStream(opts.baseDir + 'notes-server/notes.html').pipe(res);
});
// Actually listen
@ -52,4 +52,4 @@ 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" );
console.log( "3. Advance through your slides and your notes will advance automatically" );

View File

@ -125,4 +125,4 @@
</script>
</body>
</html>
</html>

157
plugin/notes/notes.html Normal file
View File

@ -0,0 +1,157 @@
<!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="../../lib/js/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 );
if( data.markdown ) {
notes.innerHTML = (new Showdown.converter()).makeHtml( data.notes );
}
else {
notes.innerHTML = data.notes;
}
// Kill the slide listeners while responding to the event
removeSlideListeners();
// Update the note slides
currentSlide.contentWindow.Reveal.slide( data.indexh, data.indexv );
nextSlide.contentWindow.Reveal.slide( data.nextindexh, data.nextindexv );
// Resume listening on the next cycle
setTimeout( addSlideListeners, 1 );
}, false );
function addSlideListeners() {
currentSlide.contentWindow.Reveal.addEventListener( 'slidechanged', onNotesSlideChange, false );
nextSlide.contentWindow.Reveal.addEventListener( 'slidechanged', onNotesSlideChange, false );
}
function removeSlideListeners() {
currentSlide.contentWindow.Reveal.removeEventListener( 'slidechanged', onNotesSlideChange, false );
nextSlide.contentWindow.Reveal.removeEventListener( 'slidechanged', onNotesSlideChange, false );
}
function onNotesSlideChange( event ) {
window.opener.postMessage( JSON.stringify({
indexh : event.indexh,
indexv : event.indexv
}), '*' );
}
addSlideListeners();
})( window );
}, false );
</script>
</body>
</html>

74
plugin/notes/notes.js Normal file
View File

@ -0,0 +1,74 @@
/**
* 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' );
Reveal.addEventListener( 'slidechanged', post );
// Posts the current slide data to the notes window
function post() {
var slideElement = Reveal.getCurrentSlide(),
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;
}
var notes = slideElement.querySelector( 'aside.notes' );
var slideData = {
notes : notes ? notes.innerHTML : '',
indexh : indexh,
indexv : indexv,
nextindexh : nextindexh,
nextindexv : nextindexv,
markdown : notes ? typeof notes.getAttribute( 'data-markdown' ) === 'string' : false
};
notesPopup.postMessage( JSON.stringify( slideData ), '*' );
}
// The main presentation is kept in sync when navigating the
// note slides so that the popup may be used as a remote
window.addEventListener( 'message', function( event ) {
var data = JSON.parse( event.data );
if( data && typeof data.indexh === 'number' && typeof data.indexv === 'number' ) {
Reveal.slide( data.indexh, data.indexv );
}
} );
// Navigate to the current slide when the notes are loaded
notesPopup.addEventListener( 'load', post, 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 }
})();