1 | // Copyright 2016 The Go Authors. All rights reserved. |
---|---|
2 | // Use of this source code is governed by a BSD-style |
3 | // license that can be found in the LICENSE file. |
4 | |
5 | // Store child window object which will display slides with notes |
6 | var notesWindow = null; |
7 | |
8 | var isParentWindow = window.parent == window; |
9 | |
10 | // When parent window closes, clear storage and close child window |
11 | if (isParentWindow) { |
12 | window.onbeforeunload = function() { |
13 | localStorage.clear(); |
14 | if (notesWindow) notesWindow.close(); |
15 | }; |
16 | } |
17 | |
18 | function toggleNotesWindow() { |
19 | if (!isParentWindow) return; |
20 | if (notesWindow) { |
21 | notesWindow.close(); |
22 | notesWindow = null; |
23 | return; |
24 | } |
25 | |
26 | initNotes(); |
27 | } |
28 | |
29 | // Create an unique key for the local storage so we don't mix the |
30 | // destSlide of different presentations. For golang.org/issue/24688. |
31 | function destSlideKey() { |
32 | var key = ''; |
33 | if (notesWindow) { |
34 | var slides = notesWindow.document.getElementById('presenter-slides'); |
35 | key = slides.src.split('#')[0]; |
36 | } else { |
37 | key = window.location.href.split('#')[0]; |
38 | } |
39 | return 'destSlide:' + key; |
40 | } |
41 | |
42 | function initNotes() { |
43 | notesWindow = window.open('', '', 'width=1000,height=700'); |
44 | var w = notesWindow; |
45 | var slidesUrl = window.location.href; |
46 | |
47 | // Hack to apply css. Requires existing html on notesWindow. |
48 | w.document.write("<div style='display:none;'></div>"); |
49 | |
50 | w.document.title = window.document.title; |
51 | |
52 | var slides = w.document.createElement('iframe'); |
53 | slides.id = 'presenter-slides'; |
54 | slides.src = slidesUrl; |
55 | w.document.body.appendChild(slides); |
56 | |
57 | var curSlide = parseInt(localStorage.getItem(destSlideKey()), 10); |
58 | var formattedNotes = ''; |
59 | var section = sections[curSlide - 1]; |
60 | // curSlide is 0 when initialized from the first page of slides. |
61 | // Check if section is valid before retrieving Notes. |
62 | if (section) { |
63 | formattedNotes = formatNotes(section.Notes); |
64 | } else if (curSlide == 0) { |
65 | formattedNotes = formatNotes(titleNotes); |
66 | } |
67 | |
68 | // setTimeout needed for Firefox |
69 | setTimeout(function() { |
70 | slides.focus(); |
71 | }, 100); |
72 | |
73 | var notes = w.document.createElement('div'); |
74 | notes.id = 'presenter-notes'; |
75 | notes.innerHTML = formattedNotes; |
76 | w.document.body.appendChild(notes); |
77 | |
78 | w.document.close(); |
79 | |
80 | function addPresenterNotesStyle() { |
81 | var el = w.document.createElement('link'); |
82 | el.rel = 'stylesheet'; |
83 | el.type = 'text/css'; |
84 | el.href = PERMANENT_URL_PREFIX + 'notes.css'; |
85 | w.document.body.appendChild(el); |
86 | w.document.querySelector('head').appendChild(el); |
87 | } |
88 | |
89 | addPresenterNotesStyle(); |
90 | |
91 | // Add listener on notesWindow to update notes when triggered from |
92 | // parent window |
93 | w.addEventListener('storage', updateNotes, false); |
94 | } |
95 | |
96 | function formatNotes(notes) { |
97 | var formattedNotes = ''; |
98 | if (notes) { |
99 | for (var i = 0; i < notes.length; i++) { |
100 | formattedNotes = formattedNotes + '<p>' + notes[i] + '</p>'; |
101 | } |
102 | } |
103 | return formattedNotes; |
104 | } |
105 | |
106 | function updateNotes() { |
107 | // When triggered from parent window, notesWindow is null |
108 | // The storage event listener on notesWindow will update notes |
109 | if (!notesWindow) return; |
110 | var destSlide = parseInt(localStorage.getItem(destSlideKey()), 10); |
111 | var section = sections[destSlide - 1]; |
112 | var el = notesWindow.document.getElementById('presenter-notes'); |
113 | |
114 | if (!el) return; |
115 | |
116 | if (section && section.Notes) { |
117 | el.innerHTML = formatNotes(section.Notes); |
118 | } else if (destSlide == 0) { |
119 | el.innerHTML = formatNotes(titleNotes); |
120 | } else { |
121 | el.innerHTML = ''; |
122 | } |
123 | } |
124 | |
125 | /* Playground syncing */ |
126 | |
127 | // When presenter notes are enabled, playground click handlers are |
128 | // stored here to sync click events on the correct playground |
129 | var playgroundHandlers = { onRun: [], onKill: [], onClose: [] }; |
130 | |
131 | function updatePlay(e) { |
132 | var i = localStorage.getItem('play-index'); |
133 | |
134 | switch (e.key) { |
135 | case 'play-index': |
136 | return; |
137 | case 'play-action': |
138 | // Sync 'run', 'kill', 'close' actions |
139 | var action = localStorage.getItem('play-action'); |
140 | playgroundHandlers[action][i](e); |
141 | return; |
142 | case 'play-code': |
143 | // Sync code editing |
144 | var play = document.querySelectorAll('div.playground')[i]; |
145 | play.innerHTML = localStorage.getItem('play-code'); |
146 | return; |
147 | case 'output-style': |
148 | // Sync resizing of playground output |
149 | var out = document.querySelectorAll('.output')[i]; |
150 | out.style = localStorage.getItem('output-style'); |
151 | return; |
152 | } |
153 | } |
154 | |
155 | // Reset 'run', 'kill', 'close' storage items when synced |
156 | // so that successive actions can be synced correctly |
157 | function updatePlayStorage(action, index, e) { |
158 | localStorage.setItem('play-index', index); |
159 | |
160 | if (localStorage.getItem('play-action') === action) { |
161 | // We're the receiving window, and the message has been received |
162 | localStorage.removeItem('play-action'); |
163 | } else { |
164 | // We're the triggering window, send the message |
165 | localStorage.setItem('play-action', action); |
166 | } |
167 | |
168 | if (action === 'onRun') { |
169 | if (localStorage.getItem('play-shiftKey') === 'true') { |
170 | localStorage.removeItem('play-shiftKey'); |
171 | } else if (e.shiftKey) { |
172 | localStorage.setItem('play-shiftKey', e.shiftKey); |
173 | } |
174 | } |
175 | } |
176 |
Members