github.com/mweagle/Sparta@v1.15.0/docs_source/static/presentations/reveal.js-3.9.2/plugin/notes/notes.js (about) 1 /** 2 * Handles opening of and synchronization with the reveal.js 3 * notes window. 4 * 5 * Handshake process: 6 * 1. This window posts 'connect' to notes window 7 * - Includes URL of presentation to show 8 * 2. Notes window responds with 'connected' when it is available 9 * 3. This window proceeds to send the current presentation state 10 * to the notes window 11 */ 12 var RevealNotes = (function() { 13 14 var notesPopup = null; 15 16 function openNotes( notesFilePath ) { 17 18 if (notesPopup && !notesPopup.closed) { 19 notesPopup.focus(); 20 return; 21 } 22 23 if( !notesFilePath ) { 24 var jsFileLocation = document.querySelector('script[src$="notes.js"]').src; // this js file path 25 jsFileLocation = jsFileLocation.replace(/notes\.js(\?.*)?$/, ''); // the js folder path 26 notesFilePath = jsFileLocation + 'notes.html'; 27 } 28 29 notesPopup = window.open( notesFilePath, 'reveal.js - Notes', 'width=1100,height=700' ); 30 31 if( !notesPopup ) { 32 alert( 'Speaker view popup failed to open. Please make sure popups are allowed and reopen the speaker view.' ); 33 return; 34 } 35 36 /** 37 * Connect to the notes window through a postmessage handshake. 38 * Using postmessage enables us to work in situations where the 39 * origins differ, such as a presentation being opened from the 40 * file system. 41 */ 42 function connect() { 43 // Keep trying to connect until we get a 'connected' message back 44 var connectInterval = setInterval( function() { 45 notesPopup.postMessage( JSON.stringify( { 46 namespace: 'reveal-notes', 47 type: 'connect', 48 url: window.location.protocol + '//' + window.location.host + window.location.pathname + window.location.search, 49 state: Reveal.getState() 50 } ), '*' ); 51 }, 500 ); 52 53 window.addEventListener( 'message', function( event ) { 54 var data = JSON.parse( event.data ); 55 if( data && data.namespace === 'reveal-notes' && data.type === 'connected' ) { 56 clearInterval( connectInterval ); 57 onConnected(); 58 } 59 if( data && data.namespace === 'reveal-notes' && data.type === 'call' ) { 60 callRevealApi( data.methodName, data.arguments, data.callId ); 61 } 62 } ); 63 } 64 65 /** 66 * Calls the specified Reveal.js method with the provided argument 67 * and then pushes the result to the notes frame. 68 */ 69 function callRevealApi( methodName, methodArguments, callId ) { 70 71 var result = Reveal[methodName].apply( Reveal, methodArguments ); 72 notesPopup.postMessage( JSON.stringify( { 73 namespace: 'reveal-notes', 74 type: 'return', 75 result: result, 76 callId: callId 77 } ), '*' ); 78 79 } 80 81 /** 82 * Posts the current slide data to the notes window 83 */ 84 function post( event ) { 85 86 var slideElement = Reveal.getCurrentSlide(), 87 notesElement = slideElement.querySelector( 'aside.notes' ), 88 fragmentElement = slideElement.querySelector( '.current-fragment' ); 89 90 var messageData = { 91 namespace: 'reveal-notes', 92 type: 'state', 93 notes: '', 94 markdown: false, 95 whitespace: 'normal', 96 state: Reveal.getState() 97 }; 98 99 // Look for notes defined in a slide attribute 100 if( slideElement.hasAttribute( 'data-notes' ) ) { 101 messageData.notes = slideElement.getAttribute( 'data-notes' ); 102 messageData.whitespace = 'pre-wrap'; 103 } 104 105 // Look for notes defined in a fragment 106 if( fragmentElement ) { 107 var fragmentNotes = fragmentElement.querySelector( 'aside.notes' ); 108 if( fragmentNotes ) { 109 notesElement = fragmentNotes; 110 } 111 else if( fragmentElement.hasAttribute( 'data-notes' ) ) { 112 messageData.notes = fragmentElement.getAttribute( 'data-notes' ); 113 messageData.whitespace = 'pre-wrap'; 114 115 // In case there are slide notes 116 notesElement = null; 117 } 118 } 119 120 // Look for notes defined in an aside element 121 if( notesElement ) { 122 messageData.notes = notesElement.innerHTML; 123 messageData.markdown = typeof notesElement.getAttribute( 'data-markdown' ) === 'string'; 124 } 125 126 notesPopup.postMessage( JSON.stringify( messageData ), '*' ); 127 128 } 129 130 /** 131 * Called once we have established a connection to the notes 132 * window. 133 */ 134 function onConnected() { 135 136 // Monitor events that trigger a change in state 137 Reveal.addEventListener( 'slidechanged', post ); 138 Reveal.addEventListener( 'fragmentshown', post ); 139 Reveal.addEventListener( 'fragmenthidden', post ); 140 Reveal.addEventListener( 'overviewhidden', post ); 141 Reveal.addEventListener( 'overviewshown', post ); 142 Reveal.addEventListener( 'paused', post ); 143 Reveal.addEventListener( 'resumed', post ); 144 145 // Post the initial state 146 post(); 147 148 } 149 150 connect(); 151 152 } 153 154 return { 155 init: function() { 156 157 if( !/receiver/i.test( window.location.search ) ) { 158 159 // If the there's a 'notes' query set, open directly 160 if( window.location.search.match( /(\?|\&)notes/gi ) !== null ) { 161 openNotes(); 162 } 163 164 // Open the notes when the 's' key is hit 165 Reveal.addKeyBinding({keyCode: 83, key: 'S', description: 'Speaker notes view'}, function() { 166 openNotes(); 167 } ); 168 169 } 170 171 }, 172 173 open: openNotes 174 }; 175 176 })(); 177 178 Reveal.registerPlugin( 'notes', RevealNotes );