From 80aadaf74e901b184d86b536c0c01e0fe98623d0 Mon Sep 17 00:00:00 2001 From: Gabriel Pillet Date: Thu, 31 Oct 2013 14:02:34 +0100 Subject: Removing global flag for replacing whitespaces --- plugin/markdown/markdown.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugin') diff --git a/plugin/markdown/markdown.js b/plugin/markdown/markdown.js index d6c6c45..23a3ed4 100755 --- a/plugin/markdown/markdown.js +++ b/plugin/markdown/markdown.js @@ -49,7 +49,7 @@ text = text.replace( new RegExp('\\n?\\t{' + leadingTabs + '}','g'), '\n' ); } else if( leadingWs > 1 ) { - text = text.replace( new RegExp('\\n? {' + leadingWs + '}','g'), '\n' ); + text = text.replace( new RegExp('\\n? {' + leadingWs + '}'), '\n' ); } return text; -- cgit v1.2.3 From a22d00ab25b13b82d19890428f124b4ed3759f92 Mon Sep 17 00:00:00 2001 From: Hakim El Hattab Date: Mon, 17 Feb 2014 20:07:41 +0100 Subject: server side notes plugin now supports input via data-notes attribute --- plugin/notes-server/client.js | 45 +++++++++++++++++++++++++++---------------- plugin/notes/notes.js | 21 ++++++++++++++------ 2 files changed, 43 insertions(+), 23 deletions(-) (limited to 'plugin') diff --git a/plugin/notes-server/client.js b/plugin/notes-server/client.js index 156cb9a..ee60ff7 100644 --- a/plugin/notes-server/client.js +++ b/plugin/notes-server/client.js @@ -1,12 +1,13 @@ (function() { // don't emit events from inside the previews themselves - if ( window.location.search.match( /receiver/gi ) ) { return; } + 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); + 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 ) { @@ -23,16 +24,17 @@ fragment : 'previous', socketId : socketId }; - socket.emit('fragmentchanged', fragmentData); + socket.emit( 'fragmentchanged', fragmentData ); } ); // Fires when slide is changed Reveal.addEventListener( 'slidechanged', function( event ) { - var nextindexh; - var nextindexv; - var slideElement = event.currentSlide; + var nextindexh, + nextindexv, + slideElement = event.currentSlide, + notesElement = slideElement.querySelector( 'aside.notes' ); - if (slideElement.nextElementSibling && slideElement.parentNode.nodeName == 'SECTION') { + if( slideElement.nextElementSibling && slideElement.parentNode.nodeName == 'SECTION' ) { nextindexh = event.indexh; nextindexv = event.indexv + 1; } else { @@ -40,18 +42,27 @@ nextindexv = 0; } - var notes = slideElement.querySelector('aside.notes'); - var slideData = { - notes : notes ? notes.innerHTML : '', + var messageData = { + notes : '', indexh : event.indexh, indexv : event.indexv, nextindexh : nextindexh, nextindexv : nextindexv, socketId : socketId, - markdown : notes ? typeof notes.getAttribute('data-markdown') === 'string' : false - + markdown : false }; - socket.emit('slidechanged', slideData); + // Look for notes defined in a slide attribute + if( slideElement.hasAttribute( 'data-notes' ) ) { + messageData.notes = slideElement.getAttribute( 'data-notes' ); + } + + // Look for notes defined in an aside element + if( notesElement ) { + messageData.notes = notesElement.innerHTML; + messageData.markdown = typeof notesElement.getAttribute( 'data-markdown' ) === 'string'; + } + + socket.emit( 'slidechanged', messageData ); } ); }()); diff --git a/plugin/notes/notes.js b/plugin/notes/notes.js index 9a82c3c..3f68b5d 100644 --- a/plugin/notes/notes.js +++ b/plugin/notes/notes.js @@ -24,9 +24,7 @@ var RevealNotes = (function() { function post() { var slideElement = Reveal.getCurrentSlide(), slideIndices = Reveal.getIndices(), - messageData; - - var notes = slideElement.querySelector( 'aside.notes' ), + notesElement = slideElement.querySelector( 'aside.notes' ), nextindexh, nextindexv; @@ -38,16 +36,27 @@ var RevealNotes = (function() { nextindexv = 0; } - messageData = { - notes : notes ? notes.innerHTML : '', + var messageData = { + notes : '', indexh : slideIndices.h, indexv : slideIndices.v, indexf : slideIndices.f, nextindexh : nextindexh, nextindexv : nextindexv, - markdown : notes ? typeof notes.getAttribute( 'data-markdown' ) === 'string' : false + markdown : false }; + // Look for notes defined in a slide attribute + if( slideElement.hasAttribute( 'data-notes' ) ) { + messageData.notes = slideElement.getAttribute( 'data-notes' ); + } + + // Look for notes defined in an aside element + if( notesElement ) { + messageData.notes = notesElement.innerHTML; + messageData.markdown = typeof notesElement.getAttribute( 'data-markdown' ) === 'string'; + } + notesPopup.postMessage( JSON.stringify( messageData ), '*' ); } -- cgit v1.2.3 From 015468c3a2d1d4092f33920ac555a0e288e6213f Mon Sep 17 00:00:00 2001 From: Hakim El Hattab Date: Mon, 17 Feb 2014 21:15:02 +0100 Subject: renamed markdown attributes for clarity and consistency: data-vertical -> data-separator-vertical, data-notes -> data-separator-notes --- README.md | 6 +++--- plugin/markdown/example.html | 4 ++-- plugin/markdown/markdown.js | 10 +++++----- test/test-markdown-element-attributes.html | 8 ++++---- test/test-markdown-slide-attributes.html | 10 +++++----- test/test-markdown.html | 4 ++-- 6 files changed, 21 insertions(+), 21 deletions(-) (limited to 'plugin') diff --git a/README.md b/README.md index 8a37a0d..cbdb088 100644 --- a/README.md +++ b/README.md @@ -59,8 +59,8 @@ When used locally, this feature requires that reveal.js [runs from a local web s ```html
``` @@ -621,7 +621,7 @@ When used locally, this feature requires that reveal.js [runs from a local web s If you're using the external Markdown plugin, you can add notes with the help of a special delimiter: ```html -
+
# Title ## Sub-title diff --git a/plugin/markdown/example.html b/plugin/markdown/example.html index 909639f..364e866 100644 --- a/plugin/markdown/example.html +++ b/plugin/markdown/example.html @@ -19,7 +19,7 @@
-
+
@@ -36,7 +36,7 @@
-
+
- - - diff --git a/plugin/postmessage/postmessage.js b/plugin/postmessage/postmessage.js deleted file mode 100644 index d0f4140..0000000 --- a/plugin/postmessage/postmessage.js +++ /dev/null @@ -1,42 +0,0 @@ -/* - - 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); - -}()); - - - -- cgit v1.2.3 From 5b18c1f308523527566cefc85414170e922bc4a2 Mon Sep 17 00:00:00 2001 From: Hakim El Hattab Date: Sat, 19 Apr 2014 10:54:14 +0200 Subject: notes plugin now operates entirely through window.postMessage, adding support for file protocol --- plugin/notes/notes.html | 176 ++++++++++++++++++++++++++++++------------------ plugin/notes/notes.js | 88 ++++++++++++++++-------- 2 files changed, 168 insertions(+), 96 deletions(-) (limited to 'plugin') diff --git a/plugin/notes/notes.html b/plugin/notes/notes.html index 847499d..3e9e8b7 100644 --- a/plugin/notes/notes.html +++ b/plugin/notes/notes.html @@ -82,6 +82,7 @@ left: 3px; font-weight: bold; font-size: 14px; + z-index: 2; color: rgba( 255, 255, 255, 0.9 ); } @@ -138,22 +139,8 @@ - - -
- -
- -
- - UPCOMING: -
+
+
UPCOMING:
@@ -171,37 +158,112 @@ diff --git a/plugin/notes/notes.js b/plugin/notes/notes.js index 3f68b5d..31efd81 100644 --- a/plugin/notes/notes.js +++ b/plugin/notes/notes.js @@ -1,6 +1,13 @@ /** * Handles opening of and synchronization with the reveal.js * notes window. + * + * Handshake process: + * 1. This window posts 'connect' to notes window + * - Includes URL of presentation to show + * 2. Notes window responds with 'connected' when it is available + * 3. This window proceeds to send the current presentation state + * to the notes window */ var RevealNotes = (function() { @@ -9,41 +16,46 @@ var RevealNotes = (function() { jsFileLocation = jsFileLocation.replace(/notes\.js(\?.*)?$/, ''); // the js folder path var notesPopup = window.open( jsFileLocation + 'notes.html', 'reveal.js - Notes', 'width=1120,height=850' ); - // Fires when slide is changed - Reveal.addEventListener( 'slidechanged', post ); - - // Fires when a fragment is shown - Reveal.addEventListener( 'fragmentshown', post ); + /** + * Connect to the notes window through a postmessage handshake. + * Using postmessage enables us to work in situations where the + * origins differ, such as a presentation being opened from the + * file system. + */ + function connect() { + // Keep trying to connect until we get a 'connected' message back + var connectInterval = setInterval( function() { + notesPopup.postMessage( JSON.stringify( { + namespace: 'reveal-notes', + type: 'connect', + url: window.location.protocol + '//' + window.location.host + window.location.pathname, + state: Reveal.getState() + } ), '*' ); + }, 500 ); - // Fires when a fragment is hidden - Reveal.addEventListener( 'fragmenthidden', post ); + window.addEventListener( 'message', function( event ) { + var data = JSON.parse( event.data ); + if( data && data.namespace === 'reveal-notes' && data.type === 'connected' ) { + clearInterval( connectInterval ); + onConnected(); + } + } ); + } /** * Posts the current slide data to the notes window */ function post() { + var slideElement = Reveal.getCurrentSlide(), - slideIndices = Reveal.getIndices(), - notesElement = slideElement.querySelector( 'aside.notes' ), - nextindexh, - nextindexv; - - if( slideElement.nextElementSibling && slideElement.parentNode.nodeName == 'SECTION' ) { - nextindexh = slideIndices.h; - nextindexv = slideIndices.v + 1; - } else { - nextindexh = slideIndices.h + 1; - nextindexv = 0; - } + notesElement = slideElement.querySelector( 'aside.notes' ); var messageData = { - notes : '', - indexh : slideIndices.h, - indexv : slideIndices.v, - indexf : slideIndices.f, - nextindexh : nextindexh, - nextindexv : nextindexv, - markdown : false + namespace: 'reveal-notes', + type: 'state', + notes: '', + markdown: false, + state: Reveal.getState() }; // Look for notes defined in a slide attribute @@ -58,12 +70,30 @@ var RevealNotes = (function() { } notesPopup.postMessage( JSON.stringify( messageData ), '*' ); + } - // Navigate to the current slide when the notes are loaded - notesPopup.addEventListener( 'load', function( event ) { + /** + * Called once we have established a connection to the notes + * window. + */ + function onConnected() { + + // Monitor events that trigger a change in state + Reveal.addEventListener( 'slidechanged', post ); + Reveal.addEventListener( 'fragmentshown', post ); + Reveal.addEventListener( 'fragmenthidden', post ); + Reveal.addEventListener( 'overviewhidden', post ); + Reveal.addEventListener( 'overviewshown', post ); + Reveal.addEventListener( 'paused', post ); + Reveal.addEventListener( 'resumed', post ); + + // Post the initial state post(); - }, false ); + + } + + connect(); } // If the there's a 'notes' query set, open directly -- cgit v1.2.3 From 3795ef1599cae8debe161c13a530ad565a767291 Mon Sep 17 00:00:00 2001 From: Hakim El Hattab Date: Sun, 20 Apr 2014 10:26:00 +0200 Subject: update style of notes plugin to match Slides --- plugin/notes/notes.html | 283 ++++++++++++++++++++++++++---------------------- 1 file changed, 152 insertions(+), 131 deletions(-) (limited to 'plugin') diff --git a/plugin/notes/notes.html b/plugin/notes/notes.html index 3e9e8b7..15c7ae9 100644 --- a/plugin/notes/notes.html +++ b/plugin/notes/notes.html @@ -10,128 +10,129 @@ font-family: Helvetica; } - #notes { - font-size: 24px; - width: 640px; - margin-top: 5px; - clear: left; + #current-slide, + #next-slide, + #speaker-controls { + padding: 6px; + box-sizing: border-box; + -moz-box-sizing: border-box; } - #wrap-current-slide { - width: 640px; - height: 512px; - float: left; - overflow: hidden; + #current-slide iframe, + #next-slide iframe { + width: 100%; + height: 100%; + border: 1px solid #ddd; } - #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); + #current-slide .label, + #next-slide .label { + position: absolute; + top: 10px; + left: 10px; + font-weight: bold; + font-size: 14px; + z-index: 2; + color: rgba( 255, 255, 255, 0.9 ); } - #wrap-next-slide { - width: 448px; - height: 358px; - float: left; - margin: 0 0 0 10px; - overflow: hidden; + #current-slide { + position: absolute; + width: 65%; + height: 100%; + top: 0; + left: 0; + padding-right: 0; } #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); + position: absolute; + width: 35%; + height: 40%; + right: 0; + top: 0; } - .slides span { + #speaker-controls { position: absolute; - top: 3px; - left: 3px; - font-weight: bold; - font-size: 14px; - z-index: 2; - color: rgba( 255, 255, 255, 0.9 ); - } + top: 40%; + right: 0; + width: 35%; + height: 60%; - .error { - font-weight: bold; - color: red; - font-size: 1.5em; - text-align: center; - margin-top: 10%; + font-size: 18px; } - .error code { - font-family: monospace; - } + .speaker-controls-time.hidden, + .speaker-controls-notes.hidden { + display: none; + } + + .speaker-controls-time .label, + .speaker-controls-notes .label { + text-transform: uppercase; + font-weight: normal; + font-size: 0.66em; + color: #666; + margin: 0; + } + + .speaker-controls-time { + border-bottom: 1px solid rgba( 200, 200, 200, 0.5 ); + margin-bottom: 10px; + padding: 10px 16px; + padding-bottom: 20px; + } + + .speaker-controls-time .timer, + .speaker-controls-time .clock { + width: 50%; + font-size: 1.9em; + } + + .speaker-controls-time .timer { + float: left; + } - .time { - width: 448px; - margin: 30px 0 0 10px; - float: left; - text-align: center; - opacity: 0; - - -webkit-transition: opacity 0.4s; - -moz-transition: opacity 0.4s; - -o-transition: opacity 0.4s; - transition: opacity 0.4s; + .speaker-controls-time .clock { + float: right; + text-align: right; + } + + .speaker-controls-time span.mute { + color: #bbb; + } + + .speaker-controls-notes { + padding: 10px 16px; + } + + .speaker-controls-notes .value { + margin-top: 5px; + line-height: 1.4; + font-size: 1.2em; + } + + .clear { + clear: both; } - .elapsed, - .clock { - color: #333; - font-size: 2em; - text-align: center; - display: inline-block; - padding: 0.5em; - background-color: #eee; - border-radius: 10px; + @media screen and (max-width: 1080px) { + #speaker-controls { + font-size: 16px; + } } - .elapsed h2, - .clock h2 { - font-size: 0.8em; - line-height: 100%; - margin: 0; - color: #aaa; + @media screen and (max-width: 900px) { + #speaker-controls { + font-size: 14px; + } } - .elapsed .mute { - color: #ddd; + @media screen and (max-width: 800px) { + #speaker-controls { + font-size: 12px; + } } @@ -139,28 +140,33 @@ -
-
UPCOMING:
- -
-
-

Time

- 0:00:00 AM +
+
UPCOMING:
+
+
+

Time

+
+ 0:00 AM +
+
+ 00:00:00 +
+
-
-

Elapsed

- 00:00:00 + +
-
- -- cgit v1.2.3 From 37ebe0732c411bee812852e80294bd36d75cd76c Mon Sep 17 00:00:00 2001 From: Hakim El Hattab Date: Tue, 22 Apr 2014 15:05:06 +0200 Subject: skip transitions in notes window for better main window performance --- plugin/notes/notes.html | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) (limited to 'plugin') diff --git a/plugin/notes/notes.html b/plugin/notes/notes.html index 9e9dfb5..e488075 100644 --- a/plugin/notes/notes.html +++ b/plugin/notes/notes.html @@ -252,25 +252,17 @@ */ function setupIframes( data ) { - var currentParams = [ + var params = [ 'receiver', 'progress=false', 'history=false', - 'postMessageEvents=true' - ].join( '&' ); - - var upcomingParams = [ - 'receiver', - 'progress=false', - 'history=false', - 'controls=false', 'transition=none', 'backgroundTransition=none' ].join( '&' ); var hash = '#/' + data.state.indexh + '/' + data.state.indexv; - var currentURL = data.url + '?' + currentParams + hash; - var upcomingURL = data.url + '?' + upcomingParams + hash; + var currentURL = data.url + '?' + params + '&postMessageEvents=true' + hash; + var upcomingURL = data.url + '?' + params + '&controls=false' + hash; currentSlide = document.createElement( 'iframe' ); currentSlide.setAttribute( 'width', 1280 ); -- cgit v1.2.3 From 1e5ca748a49b35ec698fc73d0420bb63534b9ae7 Mon Sep 17 00:00:00 2001 From: Hakim El Hattab Date: Sat, 26 Apr 2014 11:35:55 +0200 Subject: enable reveal.js keyboard shortcuts anywhere in notes window --- js/reveal.js | 5 +++++ plugin/notes/notes.html | 14 ++++++++++++++ 2 files changed, 19 insertions(+) (limited to 'plugin') diff --git a/js/reveal.js b/js/reveal.js index 7a032d0..d81a19d 100644 --- a/js/reveal.js +++ b/js/reveal.js @@ -3702,6 +3702,11 @@ var Reveal = (function(){ if( 'addEventListener' in window ) { ( dom.wrapper || document.querySelector( '.reveal' ) ).removeEventListener( type, listener, useCapture ); } + }, + + // Programatically triggers a keyboard event + triggerKey: function( keyCode ) { + onDocumentKeyDown( { keyCode: keyCode } ); } }; diff --git a/plugin/notes/notes.html b/plugin/notes/notes.html index e488075..30e1669 100644 --- a/plugin/notes/notes.html +++ b/plugin/notes/notes.html @@ -208,6 +208,7 @@ connected = true; setupIframes( data ); + setupKeyboard(); setupNotes(); setupTimer(); } @@ -247,6 +248,19 @@ // Limit to max one state update per X ms handleStateMessage = debounce( handleStateMessage, 200 ); + /** + * Forward keyboard events to the current slide window. + * This enables keyboard events to work even if focus + * isn't set on the current slide iframe. + */ + function setupKeyboard() { + + document.addEventListener( 'keydown', function( event ) { + currentSlide.contentWindow.postMessage( JSON.stringify({ method: 'triggerKey', args: [ event.keyCode ] }), '*' ); + } ); + + } + /** * Creates the preview iframes. */ -- cgit v1.2.3 From ebb9a689a052eb80b2603f6722cb0cfeebd30e47 Mon Sep 17 00:00:00 2001 From: Hakim El Hattab Date: Tue, 29 Apr 2014 10:23:52 +0200 Subject: updates to phantom pdf print script, arguments for width/height --- plugin/print-pdf/print-pdf.js | 44 +++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 20 deletions(-) (limited to 'plugin') diff --git a/plugin/print-pdf/print-pdf.js b/plugin/print-pdf/print-pdf.js index 6b6cad6..86dc4df 100644 --- a/plugin/print-pdf/print-pdf.js +++ b/plugin/print-pdf/print-pdf.js @@ -11,34 +11,38 @@ var page = new WebPage(); var system = require( 'system' ); -page.viewportSize = { - width: 1024, - height: 768 +var slideWidth = system.args[3] ? system.args[3].split( 'x' )[0] : 960; +var slideHeight = system.args[3] ? system.args[3].split( 'x' )[1] : 700; + +page.viewportSize = { + width: slideWidth, + height: slideHeight }; +// TODO +// Something is wrong with these config values. An input +// paper width of 1920px actually results in a 756px wide +// PDF. page.paperSize = { - format: 'letter', - orientation: 'landscape', - margin: { - left: '0', - right: '0', - top: '0', - bottom: '0' - } + width: Math.round( slideWidth * 2 ), + height: Math.round( slideHeight * 2 ), + border: 0 }; -var revealFile = system.args[1] || 'index.html?print-pdf'; -var slideFile = system.args[2] || 'slides.pdf'; +var inputFile = system.args[1] || 'index.html?print-pdf'; +var outputFile = system.args[2] || 'slides.pdf'; -if( slideFile.match( /\.pdf$/gi ) === null ) { - slideFile += '.pdf'; +if( outputFile.match( /\.pdf$/gi ) === null ) { + outputFile += '.pdf'; } -console.log( 'Printing PDF...' ); +console.log( 'Printing PDF (Paper size: '+ page.paperSize.width + 'x' + page.paperSize.height +')' ); -page.open( revealFile, function( status ) { - console.log( 'Printed succesfully' ); - page.render( slideFile ); - phantom.exit(); +page.open( inputFile, function( status ) { + window.setTimeout( function() { + console.log( 'Printed succesfully' ); + page.render( outputFile ); + phantom.exit(); + }, 1000 ); } ); -- cgit v1.2.3 From fa6187072e70ed8c8f08df6a4a6bd4d68db8074e Mon Sep 17 00:00:00 2001 From: Hakim El Hattab Date: Sun, 4 May 2014 08:13:03 +0200 Subject: clicking on notes timer now resets it #779 --- plugin/notes/notes.html | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'plugin') diff --git a/plugin/notes/notes.html b/plugin/notes/notes.html index 30e1669..43385bf 100644 --- a/plugin/notes/notes.html +++ b/plugin/notes/notes.html @@ -82,6 +82,17 @@ margin-bottom: 10px; padding: 10px 16px; padding-bottom: 20px; + cursor: pointer; + } + + .speaker-controls-time .reset-button { + opacity: 0; + float: right; + color: #666; + text-decoration: none; + } + .speaker-controls-time:hover .reset-button { + opacity: 1; } .speaker-controls-time .timer, @@ -144,7 +155,7 @@
UPCOMING:
-

Time

+

Time Click to Reset

0:00 AM
@@ -340,6 +351,12 @@ // Then update every second setInterval( _updateTimer, 1000 ); + timeEl.addEventListener( 'click', function() { + start = new Date(); + _updateTimer(); + return false; + } ); + } function zeroPadInteger( num ) { -- cgit v1.2.3 From 4c5b15d0b92cae5828df5d39c5e5a51e68242752 Mon Sep 17 00:00:00 2001 From: Hakim El Hattab Date: Sun, 4 May 2014 09:32:00 +0200 Subject: update server side notes to match client side plugin --- plugin/notes-server/client.js | 69 +++---- plugin/notes-server/index.js | 47 ++--- plugin/notes-server/notes.html | 436 ++++++++++++++++++++++++++++++++--------- 3 files changed, 392 insertions(+), 160 deletions(-) (limited to 'plugin') diff --git a/plugin/notes-server/client.js b/plugin/notes-server/client.js index ee60ff7..f7ecfa2 100644 --- a/plugin/notes-server/client.js +++ b/plugin/notes-server/client.js @@ -1,55 +1,28 @@ (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 ); + var socket = io.connect( window.location.origin ), + 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); - } ); + /** + * Posts the current slide data to the notes window + */ + function post() { - // 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, - nextindexv, - slideElement = event.currentSlide, + var slideElement = Reveal.getCurrentSlide(), notesElement = slideElement.querySelector( 'aside.notes' ); - if( slideElement.nextElementSibling && slideElement.parentNode.nodeName == 'SECTION' ) { - nextindexh = event.indexh; - nextindexv = event.indexv + 1; - } else { - nextindexh = event.indexh + 1; - nextindexv = 0; - } - var messageData = { - notes : '', - indexh : event.indexh, - indexv : event.indexv, - nextindexh : nextindexh, - nextindexv : nextindexv, - socketId : socketId, - markdown : false + notes: '', + markdown: false, + socketId: socketId, + state: Reveal.getState() }; // Look for notes defined in a slide attribute @@ -63,6 +36,20 @@ messageData.markdown = typeof notesElement.getAttribute( 'data-markdown' ) === 'string'; } - socket.emit( 'slidechanged', messageData ); - } ); + socket.emit( 'state', messageData ); + + } + + // Monitor events that trigger a change in state + Reveal.addEventListener( 'slidechanged', post ); + Reveal.addEventListener( 'fragmentshown', post ); + Reveal.addEventListener( 'fragmenthidden', post ); + Reveal.addEventListener( 'overviewhidden', post ); + Reveal.addEventListener( 'overviewshown', post ); + Reveal.addEventListener( 'paused', post ); + Reveal.addEventListener( 'resumed', post ); + + // Post the initial state + post(); + }()); diff --git a/plugin/notes-server/index.js b/plugin/notes-server/index.js index 5535c90..b6779d3 100644 --- a/plugin/notes-server/index.js +++ b/plugin/notes-server/index.js @@ -14,46 +14,49 @@ var opts = { 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); +io.sockets.on( 'connection', function( socket ) { + + socket.on( 'state', function( state ) { + socket.broadcast.emit( 'state', state ); }); + }); -app.configure(function() { - [ 'css', 'js', 'images', 'plugin', 'lib' ].forEach(function(dir) { - app.use('/' + dir, staticDir(opts.baseDir + dir)); +app.configure( function() { + + [ 'css', 'js', 'images', 'plugin', 'lib' ].forEach( function( dir ) { + app.use( '/' + dir, staticDir( opts.baseDir + dir ) ); }); + }); -app.get("/", function(req, res) { - res.writeHead(200, {'Content-Type': 'text/html'}); - fs.createReadStream(opts.baseDir + '/index.html').pipe(res); +app.get('/', function( req, res ) { + + res.writeHead( 200, { 'Content-Type': 'text/html' } ); + fs.createReadStream( opts.baseDir + '/index.html' ).pipe( res ); + }); -app.get("/notes/:socketId", function(req, 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(), { + 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); +app.listen( opts.port || null ); var brown = '\033[33m', green = '\033[32m', reset = '\033[0m'; -var slidesLocation = "http://localhost" + ( opts.port ? ( ':' + opts.port ) : '' ); +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( 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' ); diff --git a/plugin/notes-server/notes.html b/plugin/notes-server/notes.html index 25d1a62..4ff48f1 100644 --- a/plugin/notes-server/notes.html +++ b/plugin/notes-server/notes.html @@ -3,8 +3,6 @@ - - reveal.js - Slide Notes -
- -
+
+
UPCOMING:
+
+
+

Time Click to Reset

+
+ 0:00 AM +
+
+ 00:00:00 +
+
+
-
- - UPCOMING: +
-
-- cgit v1.2.3 From 3eb7038a153b12245cffbc840a727a764d82b333 Mon Sep 17 00:00:00 2001 From: Hakim El Hattab Date: Sun, 4 May 2014 10:10:21 +0200 Subject: sync server-side speaker notes after notes window opens --- plugin/notes-server/client.js | 7 ++++++- plugin/notes-server/index.js | 8 ++++++-- plugin/notes-server/notes.html | 16 ++++++++++++++-- 3 files changed, 26 insertions(+), 5 deletions(-) (limited to 'plugin') diff --git a/plugin/notes-server/client.js b/plugin/notes-server/client.js index f7ecfa2..628586f 100644 --- a/plugin/notes-server/client.js +++ b/plugin/notes-server/client.js @@ -36,10 +36,15 @@ messageData.markdown = typeof notesElement.getAttribute( 'data-markdown' ) === 'string'; } - socket.emit( 'state', messageData ); + socket.emit( 'statechanged', messageData ); } + // When a new notes window connects, post our current state + socket.on( 'connect', function( data ) { + post(); + } ); + // Monitor events that trigger a change in state Reveal.addEventListener( 'slidechanged', post ); Reveal.addEventListener( 'fragmentshown', post ); diff --git a/plugin/notes-server/index.js b/plugin/notes-server/index.js index b6779d3..df917f1 100644 --- a/plugin/notes-server/index.js +++ b/plugin/notes-server/index.js @@ -16,8 +16,12 @@ var opts = { io.sockets.on( 'connection', function( socket ) { - socket.on( 'state', function( state ) { - socket.broadcast.emit( 'state', state ); + socket.on( 'connect', function( data ) { + socket.broadcast.emit( 'connect', data ); + }); + + socket.on( 'statechanged', function( data ) { + socket.broadcast.emit( 'statechanged', data ); }); }); diff --git a/plugin/notes-server/notes.html b/plugin/notes-server/notes.html index 4ff48f1..72d0317 100644 --- a/plugin/notes-server/notes.html +++ b/plugin/notes-server/notes.html @@ -187,7 +187,7 @@ var socket = io.connect( window.location.origin ), socketId = '{{socketId}}'; - socket.on( 'state', function( data ) { + socket.on( 'statechanged', function( data ) { // ignore data from sockets that aren't ours if( data.socketId !== socketId ) { return; } @@ -206,6 +206,18 @@ } ); + window.addEventListener( 'message', function( event ) { + + var data = JSON.parse( event.data ); + + if( data && data.namespace === 'reveal' ) { + if( /ready/.test( data.eventName ) ) { + socket.emit( 'connect', { socketId: socketId } ); + } + } + + } ); + /** * Called when the main window sends an updated state. */ @@ -266,7 +278,7 @@ ].join( '&' ); var hash = '#/' + data.state.indexh + '/' + data.state.indexv; - var currentURL = '/?' + params + hash; + var currentURL = '/?' + params + '&postMessageEvents=true' + hash; var upcomingURL = '/?' + params + '&controls=false' + hash; currentSlide = document.createElement( 'iframe' ); -- cgit v1.2.3 From b558f742990f08659348146c2bf3527ed99d519f Mon Sep 17 00:00:00 2001 From: Hakim El Hattab Date: Mon, 19 May 2014 09:26:44 +0200 Subject: zoom viewport is centered on target element #900 --- plugin/zoom-js/zoom.js | 120 ++++++++++++++++++++++++++----------------------- 1 file changed, 64 insertions(+), 56 deletions(-) (limited to 'plugin') diff --git a/plugin/zoom-js/zoom.js b/plugin/zoom-js/zoom.js index cd5b06f..a672af4 100644 --- a/plugin/zoom-js/zoom.js +++ b/plugin/zoom-js/zoom.js @@ -16,11 +16,11 @@ })(); /*! - * zoom.js 0.2 (modified version for use with reveal.js) + * zoom.js 0.3 (modified for use with reveal.js) * http://lab.hakim.se/zoom-js * MIT licensed * - * Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se + * Copyright (C) 2011-2014 Hakim El Hattab, http://hakim.se */ var zoom = (function(){ @@ -35,8 +35,6 @@ var zoom = (function(){ 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 || @@ -58,7 +56,7 @@ var zoom = (function(){ if( level !== 1 && event.keyCode === 27 ) { zoom.out(); } - }, false ); + } ); // Monitor mouse movement for panning document.addEventListener( 'mousemove', function( event ) { @@ -66,38 +64,56 @@ var zoom = (function(){ mouseX = event.clientX; mouseY = event.clientY; } - }, false ); + } ); /** - * Applies the CSS required to zoom in, prioritizes use of CSS3 + * Applies the CSS required to zoom in, prefers the use of CSS3 * transforms but falls back on zoom for IE. * - * @param {Number} pageOffsetX - * @param {Number} pageOffsetY - * @param {Number} elementOffsetX - * @param {Number} elementOffsetY + * @param {Object} rect * @param {Number} scale */ - function magnify( pageOffsetX, pageOffsetY, elementOffsetX, elementOffsetY, scale ) { + function magnify( rect, scale ) { + + var scrollOffset = getScrollOffset(); + + // Ensure a width/height is set + rect.width = rect.width || 1; + rect.height = rect.height || 1; + + // Center the rect within the zoomed viewport + rect.x -= ( window.innerWidth - ( rect.width * scale ) ) / 2; + rect.y -= ( window.innerHeight - ( rect.height * scale ) ) / 2; 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; + // Reset + if( scale === 1 ) { + document.body.style.transform = ''; + document.body.style.OTransform = ''; + document.body.style.msTransform = ''; + document.body.style.MozTransform = ''; + document.body.style.WebkitTransform = ''; + } + // Scale + else { + var origin = scrollOffset.x +'px '+ scrollOffset.y +'px', + transform = 'translate('+ -rect.x +'px,'+ -rect.y +'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 + // Reset if( scale === 1 ) { document.body.style.position = ''; document.body.style.left = ''; @@ -106,11 +122,11 @@ var zoom = (function(){ document.body.style.height = ''; document.body.style.zoom = ''; } - // Apply scale + // 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.left = ( - ( scrollOffset.x + rect.x ) / scale ) + 'px'; + document.body.style.top = ( - ( scrollOffset.y + rect.y ) / scale ) + 'px'; document.body.style.width = ( scale * 100 ) + '%'; document.body.style.height = ( scale * 100 ) + '%'; document.body.style.zoom = scale; @@ -119,11 +135,13 @@ var zoom = (function(){ level = scale; - if( level !== 1 && document.documentElement.classList ) { - document.documentElement.classList.add( 'zoomed' ); - } - else { - document.documentElement.classList.remove( 'zoomed' ); + if( document.documentElement.classList ) { + if( level !== 1 ) { + document.documentElement.classList.add( 'zoomed' ); + } + else { + document.documentElement.classList.remove( 'zoomed' ); + } } } @@ -159,7 +177,7 @@ var zoom = (function(){ function getScrollOffset() { return { x: window.scrollX !== undefined ? window.scrollX : window.pageXOffset, - y: window.scrollY !== undefined ? window.scrollY : window.pageXYffset + y: window.scrollY !== undefined ? window.scrollY : window.pageYOffset } } @@ -175,6 +193,7 @@ var zoom = (function(){ * - 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 ) { @@ -188,11 +207,12 @@ var zoom = (function(){ if( !!options.element ) { // Space around the zoomed in element to leave on screen var padding = 20; + var bounds = options.element.getBoundingClientRect(); - 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; + options.x = bounds.left - padding; + options.y = bounds.top - padding; + options.width = bounds.width + ( padding * 2 ); + options.height = bounds.height + ( padding * 2 ); } // If width/height values are set, calculate scale from those values @@ -204,13 +224,7 @@ var zoom = (function(){ 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 ); + magnify( options, options.scale ); if( options.pan !== false ) { @@ -222,8 +236,6 @@ var zoom = (function(){ } } - - currentOptions = options; } }, @@ -234,13 +246,7 @@ var zoom = (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 ); + magnify( { x: 0, y: 0 }, 1 ); level = 1; }, @@ -256,3 +262,5 @@ var zoom = (function(){ })(); + + -- cgit v1.2.3