Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
2
2015-12-uni-ffm
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
CmS
2015-12-uni-ffm
Commits
4c5b15d0
Commit
4c5b15d0
authored
10 years ago
by
Hakim El Hattab
Browse files
Options
Downloads
Patches
Plain Diff
update server side notes to match client side plugin
parent
54e25676
No related branches found
Branches containing commit
No related tags found
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
plugin/notes-server/client.js
+28
-41
28 additions, 41 deletions
plugin/notes-server/client.js
plugin/notes-server/index.js
+25
-22
25 additions, 22 deletions
plugin/notes-server/index.js
plugin/notes-server/notes.html
+339
-97
339 additions, 97 deletions
plugin/notes-server/notes.html
with
392 additions
and
160 deletions
plugin/notes-server/client.js
+
28
−
41
View file @
4c5b15d0
(
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
();
}());
This diff is collapsed.
Click to expand it.
plugin/notes-server/index.js
+
25
−
22
View file @
4c5b15d0
...
...
@@ -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
'
);
This diff is collapsed.
Click to expand it.
plugin/notes-server/notes.html
+
339
−
97
View file @
4c5b15d0
...
...
@@ -3,8 +3,6 @@
<head>
<meta
charset=
"utf-8"
>
<meta
name=
"viewport"
content=
"width=1150"
>
<title>
reveal.js - Slide Notes
</title>
<style>
...
...
@@ -12,130 +10,374 @@
font-family
:
Helvetica
;
}
#notes
{
font-size
:
24px
;
width
:
640px
;
margin-top
:
5px
;
clear
:
left
;
#current-slide
,
#upcoming-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
,
#upcoming-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
);
}
#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
{
#current-slide
.label
,
#upcoming-slide
.label
{
position
:
absolute
;
top
:
3
px
;
left
:
3
px
;
top
:
10
px
;
left
:
10
px
;
font-weight
:
bold
;
font-size
:
14px
;
z-index
:
2
;
color
:
rgba
(
255
,
255
,
255
,
0.9
);
}
#current-slide
{
position
:
absolute
;
width
:
65%
;
height
:
100%
;
top
:
0
;
left
:
0
;
padding-right
:
0
;
}
#upcoming-slide
{
position
:
absolute
;
width
:
35%
;
height
:
40%
;
right
:
0
;
top
:
0
;
}
#speaker-controls
{
position
:
absolute
;
top
:
40%
;
right
:
0
;
width
:
35%
;
height
:
60%
;
font-size
:
18px
;
}
.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
;
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
,
.speaker-controls-time
.clock
{
width
:
50%
;
font-size
:
1.9em
;
}
.speaker-controls-time
.timer
{
float
:
left
;
}
.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
;
}
@media
screen
and
(
max-width
:
1080px
)
{
#speaker-controls
{
font-size
:
16px
;
}
}
@media
screen
and
(
max-width
:
900px
)
{
#speaker-controls
{
font-size
:
14px
;
}
}
@media
screen
and
(
max-width
:
800px
)
{
#speaker-controls
{
font-size
:
12px
;
}
}
</style>
</head>
<body>
<div
id=
"wrap-current-slide"
class=
"slides"
>
<iframe
src=
"/?receiver"
width=
"1280"
height=
"1024"
id=
"current-slide"
></iframe>
</div>
<div
id=
"current-slide"
></div>
<div
id=
"upcoming-slide"
><span
class=
"label"
>
UPCOMING:
</span></div>
<div
id=
"speaker-controls"
>
<div
class=
"speaker-controls-time"
>
<h4
class=
"label"
>
Time
<span
class=
"reset-button"
>
Click to Reset
</span></h4>
<div
class=
"clock"
>
<span
class=
"clock-value"
>
0:00 AM
</span>
</div>
<div
class=
"timer"
>
<span
class=
"hours-value"
>
00
</span><span
class=
"minutes-value"
>
:00
</span><span
class=
"seconds-value"
>
:00
</span>
</div>
<div
class=
"clear"
></div>
</div>
<div
id=
"wrap-next-slide"
class=
"slides"
>
<iframe
src=
"/?receiver"
width=
"640"
height=
"512"
id=
"next-slide"
></iframe>
<span>
UPCOMING:
</span>
<div
class=
"speaker-controls-notes hidden"
>
<h4
class=
"label"
>
Notes
</h4>
<div
class=
"value"
></div>
</div>
</div>
<div
id=
"notes"
></div>
<script
src=
"/socket.io/socket.io.js"
></script>
<script
src=
"/plugin/markdown/marked.js"
></script>
<script>
var
socketId
=
'
{{socketId}}
'
;
var
socket
=
io
.
connect
(
window
.
location
.
origin
);
var
notes
=
document
.
getElementById
(
'
notes
'
);
var
currentSlide
=
document
.
getElementById
(
'
current-slide
'
);
var
nextSlide
=
document
.
getElementById
(
'
next-slide
'
);
(
function
()
{
var
notes
,
notesValue
,
currentState
,
currentSlide
,
upcomingSlide
,
connected
=
false
;
var
socket
=
io
.
connect
(
window
.
location
.
origin
),
socketId
=
'
{{socketId}}
'
;
socket
.
on
(
'
state
'
,
function
(
data
)
{
// ignore data from sockets that aren't ours
if
(
data
.
socketId
!==
socketId
)
{
return
;
}
if
(
connected
===
false
)
{
connected
=
true
;
setupIframes
(
data
);
setupKeyboard
();
setupNotes
();
setupTimer
();
}
handleStateMessage
(
data
);
socket
.
on
(
'
slidedata
'
,
function
(
data
)
{
// ignore data from sockets that aren't ours
if
(
data
.
socketId
!==
socketId
)
{
return
;
}
}
);
/**
* Called when the main window sends an updated state.
*/
function
handleStateMessage
(
data
)
{
// Store the most recently set state to avoid circular loops
// applying the same state
currentState
=
JSON
.
stringify
(
data
.
state
);
// No need for updating the notes in case of fragment changes
if
(
data
.
notes
)
{
notes
.
classList
.
remove
(
'
hidden
'
);
if
(
data
.
markdown
)
{
notesValue
.
innerHTML
=
marked
(
data
.
notes
);
}
else
{
notesValue
.
innerHTML
=
data
.
notes
;
}
}
else
{
notes
.
classList
.
add
(
'
hidden
'
);
}
// Update the note slides
currentSlide
.
contentWindow
.
postMessage
(
JSON
.
stringify
({
method
:
'
setState
'
,
args
:
[
data
.
state
]
}),
'
*
'
);
upcomingSlide
.
contentWindow
.
postMessage
(
JSON
.
stringify
({
method
:
'
setState
'
,
args
:
[
data
.
state
]
}),
'
*
'
);
upcomingSlide
.
contentWindow
.
postMessage
(
JSON
.
stringify
({
method
:
'
next
'
}),
'
*
'
);
if
(
data
.
markdown
)
{
notes
.
innerHTML
=
marked
(
data
.
notes
);
}
else
{
notes
.
innerHTML
=
data
.
notes
;
// 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
]
}),
'
*
'
);
}
);
}
currentSlide
.
contentWindow
.
Reveal
.
slide
(
data
.
indexh
,
data
.
indexv
);
nextSlide
.
contentWindow
.
Reveal
.
slide
(
data
.
nextindexh
,
data
.
nextindexv
);
});
socket
.
on
(
'
fragmentdata
'
,
function
(
data
)
{
// ignore data from sockets that aren't ours
if
(
data
.
socketId
!==
socketId
)
{
return
;
}
/**
* Creates the preview iframes.
*/
function
setupIframes
(
data
)
{
var
params
=
[
'
receiver
'
,
'
progress=false
'
,
'
history=false
'
,
'
transition=none
'
,
'
backgroundTransition=none
'
].
join
(
'
&
'
);
var
hash
=
'
#/
'
+
data
.
state
.
indexh
+
'
/
'
+
data
.
state
.
indexv
;
var
currentURL
=
'
/?
'
+
params
+
hash
;
var
upcomingURL
=
'
/?
'
+
params
+
'
&controls=false
'
+
hash
;
currentSlide
=
document
.
createElement
(
'
iframe
'
);
currentSlide
.
setAttribute
(
'
width
'
,
1280
);
currentSlide
.
setAttribute
(
'
height
'
,
1024
);
currentSlide
.
setAttribute
(
'
src
'
,
currentURL
);
document
.
querySelector
(
'
#current-slide
'
).
appendChild
(
currentSlide
);
upcomingSlide
=
document
.
createElement
(
'
iframe
'
);
upcomingSlide
.
setAttribute
(
'
width
'
,
640
);
upcomingSlide
.
setAttribute
(
'
height
'
,
512
);
upcomingSlide
.
setAttribute
(
'
src
'
,
upcomingURL
);
document
.
querySelector
(
'
#upcoming-slide
'
).
appendChild
(
upcomingSlide
);
if
(
data
.
fragment
===
'
next
'
)
{
currentSlide
.
contentWindow
.
Reveal
.
nextFragment
();
}
else
if
(
data
.
fragment
===
'
previous
'
)
{
currentSlide
.
contentWindow
.
Reveal
.
prevFragment
();
/**
* Setup the notes UI.
*/
function
setupNotes
()
{
notes
=
document
.
querySelector
(
'
.speaker-controls-notes
'
);
notesValue
=
document
.
querySelector
(
'
.speaker-controls-notes .value
'
);
}
});
/**
* Create the timer and clock and start updating them
* at an interval.
*/
function
setupTimer
()
{
var
start
=
new
Date
(),
timeEl
=
document
.
querySelector
(
'
.speaker-controls-time
'
),
clockEl
=
timeEl
.
querySelector
(
'
.clock-value
'
),
hoursEl
=
timeEl
.
querySelector
(
'
.hours-value
'
),
minutesEl
=
timeEl
.
querySelector
(
'
.minutes-value
'
),
secondsEl
=
timeEl
.
querySelector
(
'
.seconds-value
'
);
function
_updateTimer
()
{
var
diff
,
hours
,
minutes
,
seconds
,
now
=
new
Date
();
diff
=
now
.
getTime
()
-
start
.
getTime
();
hours
=
Math
.
floor
(
diff
/
(
1000
*
60
*
60
)
);
minutes
=
Math
.
floor
(
(
diff
/
(
1000
*
60
)
)
%
60
);
seconds
=
Math
.
floor
(
(
diff
/
1000
)
%
60
);
clockEl
.
innerHTML
=
now
.
toLocaleTimeString
(
'
en-US
'
,
{
hour12
:
true
,
hour
:
'
2-digit
'
,
minute
:
'
2-digit
'
}
);
hoursEl
.
innerHTML
=
zeroPadInteger
(
hours
);
hoursEl
.
className
=
hours
>
0
?
''
:
'
mute
'
;
minutesEl
.
innerHTML
=
'
:
'
+
zeroPadInteger
(
minutes
);
minutesEl
.
className
=
minutes
>
0
?
''
:
'
mute
'
;
secondsEl
.
innerHTML
=
'
:
'
+
zeroPadInteger
(
seconds
);
}
// Update once directly
_updateTimer
();
// Then update every second
setInterval
(
_updateTimer
,
1000
);
timeEl
.
addEventListener
(
'
click
'
,
function
()
{
start
=
new
Date
();
_updateTimer
();
return
false
;
}
);
}
function
zeroPadInteger
(
num
)
{
var
str
=
'
00
'
+
parseInt
(
num
);
return
str
.
substring
(
str
.
length
-
2
);
}
/**
* Limits the frequency at which a function can be called.
*/
function
debounce
(
fn
,
ms
)
{
var
lastTime
=
0
,
timeout
;
return
function
()
{
var
args
=
arguments
;
var
context
=
this
;
clearTimeout
(
timeout
);
var
timeSinceLastCall
=
Date
.
now
()
-
lastTime
;
if
(
timeSinceLastCall
>
ms
)
{
fn
.
apply
(
context
,
args
);
lastTime
=
Date
.
now
();
}
else
{
timeout
=
setTimeout
(
function
()
{
fn
.
apply
(
context
,
args
);
lastTime
=
Date
.
now
();
},
ms
-
timeSinceLastCall
);
}
}
}
})();
</script>
</body>
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment