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/notes.js | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'plugin/notes') 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 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/notes') 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/notes') 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/notes') 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/notes') 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 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/notes') 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