showoff 0.15.4 → 0.16.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/showoff +247 -240
- data/lib/showoff.rb +11 -6
- data/lib/showoff/version.rb +1 -1
- data/lib/showoff_utils.rb +18 -17
- data/public/css/jquery-ui-1.12.1.css +1311 -0
- data/public/css/presenter.css +97 -85
- data/public/css/showoff.css +19 -0
- data/public/js/jquery-ui-1.12.1.js +18706 -0
- data/public/js/presenter.js +79 -14
- data/public/js/showoff.js +49 -10
- data/views/index.erb +1 -0
- data/views/presenter.erb +73 -63
- metadata +6 -4
data/public/js/presenter.js
CHANGED
@@ -59,20 +59,23 @@ $(document).ready(function(){
|
|
59
59
|
});
|
60
60
|
}
|
61
61
|
|
62
|
-
//
|
63
|
-
|
64
|
-
|
65
|
-
$(
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
$('#navigationHover').show();
|
70
|
-
},function() {
|
71
|
-
$('#navigationHover').hide();
|
72
|
-
});
|
62
|
+
// set up notes resizing
|
63
|
+
$( "#notes" ).resizable({
|
64
|
+
minHeight: 0,
|
65
|
+
handles: {"n": $(".notes-grippy")}
|
66
|
+
});
|
67
|
+
$("#notes").resize(function(){
|
68
|
+
document.cookie = "notes="+$('#notes').height();
|
73
69
|
});
|
74
70
|
|
75
71
|
|
72
|
+
// restore the UI settings
|
73
|
+
var ui = document.cookieHash['ui'];
|
74
|
+
$('#notes').height(document.cookieHash['notes']);
|
75
|
+
if(! document.cookieHash['sidebar']) {
|
76
|
+
toggleSidebar();
|
77
|
+
}
|
78
|
+
|
76
79
|
// Hide with js so jquery knows what display property to assign when showing
|
77
80
|
toggleAnnotations();
|
78
81
|
|
@@ -114,6 +117,7 @@ $(document).ready(function(){
|
|
114
117
|
sendAnnotationConfig('fillColor', color);
|
115
118
|
});
|
116
119
|
|
120
|
+
$('#statusbar .controls input').checkboxradio({icon: false });
|
117
121
|
$('#remoteToggle').change( toggleFollower );
|
118
122
|
$('#followerToggle').change( toggleUpdater );
|
119
123
|
$('#annotationsToggle').change( toggleAnnotations );
|
@@ -258,6 +262,42 @@ function nextSlideNum(url) {
|
|
258
262
|
return snum;
|
259
263
|
}
|
260
264
|
|
265
|
+
// allows subsystems to pin the sidebar open. The sidebar will only hide when
|
266
|
+
// all pins have been removed.
|
267
|
+
function pinSidebar(pin) {
|
268
|
+
$('#topbar #close-sidebar').addClass('disabled');
|
269
|
+
$('#topbar #close-sidebar').removeClass('fa-rotate-90');
|
270
|
+
$('#sidebar').show();
|
271
|
+
zoom(true);
|
272
|
+
|
273
|
+
mode.pinnedSidebar = mode.pinnedSidebar || []
|
274
|
+
if (mode.pinnedSidebar.indexOf(pin) == -1) {
|
275
|
+
mode.pinnedSidebar.push(pin);
|
276
|
+
}
|
277
|
+
}
|
278
|
+
|
279
|
+
function unpinSidebar(pin) {
|
280
|
+
if (Array.isArray(mode.pinnedSidebar)) {
|
281
|
+
mode.pinnedSidebar = mode.pinnedSidebar.filter(function(item) {
|
282
|
+
return item !== pin;
|
283
|
+
});
|
284
|
+
|
285
|
+
if(mode.pinnedSidebar.length == 0) {
|
286
|
+
$('#topbar #close-sidebar').removeClass('disabled');
|
287
|
+
delete mode.pinnedSidebar;
|
288
|
+
}
|
289
|
+
}
|
290
|
+
}
|
291
|
+
|
292
|
+
function toggleSidebar() {
|
293
|
+
if (!mode.pinnedSidebar) {
|
294
|
+
$('#topbar #close-sidebar').toggleClass('fa-rotate-90');
|
295
|
+
$('#sidebar').toggle();
|
296
|
+
zoom(true);
|
297
|
+
|
298
|
+
document.cookie = "sidebar="+$('#sidebar').is(':visible');
|
299
|
+
}
|
300
|
+
}
|
261
301
|
|
262
302
|
function toggleNotes() {
|
263
303
|
mode.notes = !mode.notes;
|
@@ -266,9 +306,17 @@ function toggleNotes() {
|
|
266
306
|
try {
|
267
307
|
if(windowIsClosed(notesWindow)){
|
268
308
|
notesWindow = blankStyledWindow("Showoff Notes", 'width=350,height=450', 'notes', true);
|
269
|
-
window.setTimeout(
|
309
|
+
window.setTimeout(function() {
|
310
|
+
// call back and update the parent presenter if the window is closed
|
311
|
+
notesWindow.onunload = function(e) {
|
312
|
+
notesWindow.opener.toggleNotes();
|
313
|
+
};
|
314
|
+
|
315
|
+
postSlide();
|
316
|
+
}, 500);
|
317
|
+
|
270
318
|
}
|
271
|
-
$('#
|
319
|
+
$('#notes').addClass('hidden');
|
272
320
|
}
|
273
321
|
catch(e) {
|
274
322
|
console.log('Failed to open notes window. Popup blocker?');
|
@@ -277,12 +325,14 @@ function toggleNotes() {
|
|
277
325
|
else {
|
278
326
|
try {
|
279
327
|
notesWindow && notesWindow.close();
|
280
|
-
$('#
|
328
|
+
$('#notes').removeClass('hidden');
|
281
329
|
}
|
282
330
|
catch (e) {
|
283
331
|
console.log('Notes window failed to close properly.');
|
284
332
|
}
|
285
333
|
}
|
334
|
+
|
335
|
+
zoom(true);
|
286
336
|
}
|
287
337
|
|
288
338
|
function blankStyledWindow(title, dimensions, classes, resizable) {
|
@@ -340,6 +390,9 @@ function postQuestion(question, questionID) {
|
|
340
390
|
|
341
391
|
$("#unanswered").append(questionItem);
|
342
392
|
updateQuestionIndicator();
|
393
|
+
|
394
|
+
// don't allow the sidebar to hid when questions exist
|
395
|
+
pinSidebar('question');
|
343
396
|
}
|
344
397
|
|
345
398
|
function removeQuestion(questionID) {
|
@@ -348,6 +401,10 @@ function removeQuestion(questionID) {
|
|
348
401
|
.remove();
|
349
402
|
$('#answered').append($(question));
|
350
403
|
updateQuestionIndicator();
|
404
|
+
|
405
|
+
if($('#unanswered li').length == 0) {
|
406
|
+
unpinSidebar('question');
|
407
|
+
}
|
351
408
|
}
|
352
409
|
|
353
410
|
function updateQuestionIndicator() {
|
@@ -631,6 +688,9 @@ function startTimer() {
|
|
631
688
|
$("#timerDisplay").show();
|
632
689
|
$("#timerSection").addClass('open');
|
633
690
|
|
691
|
+
// keep the sidebar open while the timer is active
|
692
|
+
pinSidebar('timer');
|
693
|
+
|
634
694
|
var time = parseInt( $("#timerMinutes").val() ) * 60;
|
635
695
|
if(time) {
|
636
696
|
$('#timerDisplay')
|
@@ -703,6 +763,8 @@ function toggleTimer() {
|
|
703
763
|
function endTimer() {
|
704
764
|
$('#stopTimer').val('Reset');
|
705
765
|
$("#pauseTimer").hide();
|
766
|
+
|
767
|
+
// don't unpin yet, we don't want the timer to just wander off into the distance!
|
706
768
|
}
|
707
769
|
|
708
770
|
function stopTimer() {
|
@@ -716,6 +778,9 @@ function stopTimer() {
|
|
716
778
|
$("#pauseTimer").hide();
|
717
779
|
$("#timerDisplay").hide();
|
718
780
|
$('#timerSection').removeClass();
|
781
|
+
|
782
|
+
// only unpin when the user has dismissed the timer
|
783
|
+
unpinSidebar('timer');
|
719
784
|
}
|
720
785
|
|
721
786
|
/********************
|
data/public/js/showoff.js
CHANGED
@@ -32,6 +32,10 @@ document.cookie.split(';').forEach( function(item) {
|
|
32
32
|
var pos = item.indexOf('=');
|
33
33
|
var key = item.slice(0,pos).trim();
|
34
34
|
var val = item.slice(pos+1).trim();
|
35
|
+
try {
|
36
|
+
val = JSON.parse(val);
|
37
|
+
}
|
38
|
+
catch(e) { }
|
35
39
|
|
36
40
|
document.cookieHash[key] = val;
|
37
41
|
});
|
@@ -87,6 +91,18 @@ function setupPreso(load_slides, prefix) {
|
|
87
91
|
// yes, this is a global
|
88
92
|
annotations = new Annotate();
|
89
93
|
|
94
|
+
// wait until the presentation is loaded to hook up the previews.
|
95
|
+
$("body").bind("showoff:loaded", function (event) {
|
96
|
+
$('#navigation li a.navItem').hover(function() {
|
97
|
+
var position = $(this).position();
|
98
|
+
$('#navigationHover').css({top: position.top, left: position.left + $('#navigation').width() + 5})
|
99
|
+
$('#navigationHover').html(slides.eq($(this).attr('rel')).html());
|
100
|
+
$('#navigationHover').show();
|
101
|
+
},function() {
|
102
|
+
$('#navigationHover').hide();
|
103
|
+
});
|
104
|
+
});
|
105
|
+
|
90
106
|
// Open up our control socket
|
91
107
|
if(mode.track) {
|
92
108
|
connectControlChannel();
|
@@ -556,18 +572,31 @@ function showSlide(back_step, updatepv) {
|
|
556
572
|
}
|
557
573
|
}
|
558
574
|
|
559
|
-
//
|
560
|
-
|
575
|
+
// if we're a slave/display window
|
576
|
+
if('presenterView' in window) {
|
561
577
|
var pv = window.presenterView;
|
562
|
-
pv.slidenum = slidenum;
|
563
|
-
pv.incrCurr = incrCurr
|
564
|
-
pv.incrSteps = incrSteps
|
565
|
-
pv.showSlide(true);
|
566
|
-
pv.postSlide();
|
567
578
|
|
568
|
-
|
579
|
+
// Update presenter view, if it's tracking us
|
580
|
+
if (updatepv) {
|
581
|
+
pv.slidenum = slidenum;
|
582
|
+
pv.incrCurr = incrCurr
|
583
|
+
pv.incrSteps = incrSteps
|
569
584
|
|
570
|
-
|
585
|
+
pv.showSlide(true);
|
586
|
+
pv.postSlide();
|
587
|
+
pv.update();
|
588
|
+
}
|
589
|
+
|
590
|
+
// if the slide is marked to autoplay videos, then fire them off!
|
591
|
+
if(currentSlide.hasClass('autoplay')) {
|
592
|
+
console.log('Autoplaying ' + currentSlide.attr('id'))
|
593
|
+
setTimeout(function(){
|
594
|
+
$(currentSlide).find('video').each(function() {
|
595
|
+
$(this).get(0).play();
|
596
|
+
});
|
597
|
+
}, 1000);
|
598
|
+
}
|
599
|
+
}
|
571
600
|
|
572
601
|
// Update nav
|
573
602
|
$('.highlighted').removeClass('highlighted');
|
@@ -1026,7 +1055,7 @@ function feedbackActivity() {
|
|
1026
1055
|
|
1027
1056
|
function track() {
|
1028
1057
|
if (mode.track && ws.readyState == WebSocket.OPEN) {
|
1029
|
-
var slideName = $("#slideFilename").text();
|
1058
|
+
var slideName = $("#slideFilename").text() || $("#slideFile").text(); // yey for consistency
|
1030
1059
|
var slideEndTime = new Date().getTime();
|
1031
1060
|
var elapsedTime = slideEndTime - slideStartTime;
|
1032
1061
|
|
@@ -1099,6 +1128,11 @@ function increment() {
|
|
1099
1128
|
|
1100
1129
|
function prevStep(updatepv)
|
1101
1130
|
{
|
1131
|
+
$(currentSlide).find('video').each(function() {
|
1132
|
+
console.log('Pausing videos on ' + currentSlide.attr('id'))
|
1133
|
+
$(this).get(0).pause();
|
1134
|
+
});
|
1135
|
+
|
1102
1136
|
fireEvent("showoff:prev");
|
1103
1137
|
track();
|
1104
1138
|
slidenum--;
|
@@ -1107,6 +1141,11 @@ function prevStep(updatepv)
|
|
1107
1141
|
|
1108
1142
|
function nextStep(updatepv)
|
1109
1143
|
{
|
1144
|
+
$(currentSlide).find('video').each(function() {
|
1145
|
+
console.log('Pausing videos on ' + currentSlide.attr('id'))
|
1146
|
+
$(this).get(0).pause();
|
1147
|
+
});
|
1148
|
+
|
1110
1149
|
fireEvent("showoff:next");
|
1111
1150
|
track();
|
1112
1151
|
|
data/views/index.erb
CHANGED
@@ -10,6 +10,7 @@
|
|
10
10
|
|
11
11
|
<i id="hamburger" class="fa fa-bars fa-2x"></i>
|
12
12
|
<div id="sidebarWrapper">
|
13
|
+
<div id="navigationHover"></div>
|
13
14
|
<div id="feedbackSidebar" class="sideMenu">
|
14
15
|
<img id="disconnected" src="<%= @asset_path %>/css/disconnected.png">
|
15
16
|
<h3>Showoff Menu</h3>
|
data/views/presenter.erb
CHANGED
@@ -5,8 +5,12 @@
|
|
5
5
|
<%= erb :header %>
|
6
6
|
<link rel="stylesheet" href="<%= @asset_path %>/css/presenter.css?v=<%= SHOWOFF_VERSION %>" type="text/css"/>
|
7
7
|
<link href="<%= @asset_path %>/css/TimeCircles-89ac5ae.css" rel="stylesheet">
|
8
|
+
<link href="<%= @asset_path %>/css/jquery-ui-1.12.1.css" rel="stylesheet">
|
9
|
+
|
8
10
|
<script type="text/javascript" src="<%= @asset_path %>/js/TimeCircles-89ac5ae.js"></script>
|
9
11
|
<script type="text/javascript" src="<%= @asset_path %>/js/presenter.js?v=<%= SHOWOFF_VERSION %>"></script>
|
12
|
+
<script type="text/javascript" src="<%= @asset_path %>/js/jquery-ui-1.12.1.js"></script>
|
13
|
+
|
10
14
|
<script type="text/javascript">
|
11
15
|
editUrl = "<%= @edit %>";
|
12
16
|
issueUrl = "<%= @issues %>";
|
@@ -16,8 +20,9 @@
|
|
16
20
|
<body class="presenter">
|
17
21
|
<%= erb :help %>
|
18
22
|
|
19
|
-
<div id="
|
23
|
+
<div id="pagewrapper">
|
20
24
|
<div id="topbar">
|
25
|
+
<a id="close-sidebar" class="fa fa-bars" aria-hidden="true" href="javascript:toggleSidebar();"></a>
|
21
26
|
<span id="slideSource">
|
22
27
|
<label>Source:</label>
|
23
28
|
<% if @request.host == 'localhost' %>
|
@@ -40,7 +45,6 @@
|
|
40
45
|
</span>
|
41
46
|
<span>
|
42
47
|
<a id="slaveWindow" href="javascript:toggleSlave();" title="Enable the display window.">Display Window <i class="fa fa-clone"></i></a>
|
43
|
-
<a id="notesWindow" href="javascript:toggleNotes();" title="Enable the popout notes window.">Notes Window <i class="fa fa-clone"></i></a>
|
44
48
|
</span>
|
45
49
|
<span>
|
46
50
|
<a id="printSlides" href="javascript:printSlides();" title="Print slides using a new window.">Print Slides <i class="fa fa-print"></i></a>
|
@@ -63,82 +67,88 @@
|
|
63
67
|
<p><a href="javascript:chooseLayout('default');">cancel</a><input type="button" onClick="javascript:openNext();" value="Open Window" /></p>
|
64
68
|
</div>
|
65
69
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
70
|
+
<div id="main">
|
71
|
+
<div id="sidebar">
|
72
|
+
<div id="timerSection">
|
73
|
+
<input type="button" id="pauseTimer" value="Pause" />
|
74
|
+
<input type="button" id="stopTimer" value="Cancel" />
|
75
|
+
<span id="timerLabel">Timer:</span>
|
76
|
+
<span id="minStart">
|
77
|
+
<input type="text" size="8" id="timerMinutes"/> min
|
78
|
+
<input type="button" id="startTimer" value="Start" />
|
79
|
+
</span>
|
80
|
+
<div id="timerDisplay"></div>
|
81
|
+
</div>
|
82
|
+
<div id="feedbackPace">
|
83
|
+
<span id="paceSlow">Speed Up!</span>
|
84
|
+
<span id="paceFast">Slow Down!</span>
|
85
|
+
<img id="paceMarker" src="<%= @asset_path %>/css/paceMarker.png" />
|
86
|
+
</div>
|
87
|
+
<div id="navigation" class="submenu"></div>
|
88
|
+
<div id="navigationHover"></div>
|
89
|
+
<div id="questions">
|
90
|
+
<h3>Audience Questions</h3>
|
91
|
+
<ol id="unanswered"></ol>
|
92
|
+
<ol id="answered"></ol>
|
93
|
+
</div>
|
94
|
+
</div>
|
95
|
+
|
96
|
+
<div id="presenter">
|
97
|
+
<div id="frame">
|
98
|
+
<div id="preview">
|
99
|
+
<img id="disconnected" src="<%= @asset_path %>/css/disconnected-large.png" />
|
100
|
+
<div id="prevSlide" class="thumb"><div class="container"></div><h3 class="label">Previous</h3></div>
|
101
|
+
<div id="nextSlide" class="thumb"><div class="container"></div><h3 class="label">Next</h3></div>
|
102
|
+
<div id="preso">loading presentation...</div>
|
77
103
|
</div>
|
78
|
-
<div id="
|
79
|
-
<
|
80
|
-
|
81
|
-
|
104
|
+
<div id="annotationToolbar">
|
105
|
+
<label>Tools</label>
|
106
|
+
<i class="fa fa-pencil tool default active" data-action="draw" aria-hidden="true"></i>
|
107
|
+
<i class="fa fa-arrow-right tool" data-action="rightArrow" aria-hidden="true"></i>
|
108
|
+
<i class="fa fa-arrow-left tool" data-action="leftArrow" aria-hidden="true"></i>
|
109
|
+
<i class="fa fa-bullseye tool" data-action="highlight" aria-hidden="true"></i>
|
110
|
+
<i class="fa fa-eraser tool" data-action="erase" aria-hidden="true"></i>
|
111
|
+
<label>Lines</label>
|
112
|
+
<i class="fa fa-square-o lines color1 active" aria-hidden="true"></i>
|
113
|
+
<i class="fa fa-square-o lines color2" aria-hidden="true"></i>
|
114
|
+
<i class="fa fa-square-o lines color3" aria-hidden="true"></i>
|
115
|
+
<i class="fa fa-square-o lines color4" aria-hidden="true"></i>
|
116
|
+
<label>Shapes</label>
|
117
|
+
<i class="fa fa-square shapes color1" aria-hidden="true"></i>
|
118
|
+
<i class="fa fa-square shapes color2" aria-hidden="true"></i>
|
119
|
+
<i class="fa fa-square shapes color3 active" aria-hidden="true"></i>
|
120
|
+
<i class="fa fa-square shapes color4" aria-hidden="true"></i>
|
82
121
|
</div>
|
83
|
-
<div id="navigation" class="submenu"></div>
|
84
|
-
<div id="navigationHover"></div>
|
85
122
|
</div>
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
<
|
95
|
-
<label>
|
96
|
-
<i class="fa fa-pencil tool default active" data-action="draw" aria-hidden="true"></i>
|
97
|
-
<i class="fa fa-arrow-right tool" data-action="rightArrow" aria-hidden="true"></i>
|
98
|
-
<i class="fa fa-arrow-left tool" data-action="leftArrow" aria-hidden="true"></i>
|
99
|
-
<i class="fa fa-bullseye tool" data-action="highlight" aria-hidden="true"></i>
|
100
|
-
<i class="fa fa-eraser tool" data-action="erase" aria-hidden="true"></i>
|
101
|
-
<label>Lines</label>
|
102
|
-
<i class="fa fa-square-o lines color1 active" aria-hidden="true"></i>
|
103
|
-
<i class="fa fa-square-o lines color2" aria-hidden="true"></i>
|
104
|
-
<i class="fa fa-square-o lines color3" aria-hidden="true"></i>
|
105
|
-
<i class="fa fa-square-o lines color4" aria-hidden="true"></i>
|
106
|
-
<label>Shapes</label>
|
107
|
-
<i class="fa fa-square shapes color1" aria-hidden="true"></i>
|
108
|
-
<i class="fa fa-square shapes color2" aria-hidden="true"></i>
|
109
|
-
<i class="fa fa-square shapes color3 active" aria-hidden="true"></i>
|
110
|
-
<i class="fa fa-square shapes color4" aria-hidden="true"></i>
|
111
|
-
</div>
|
112
|
-
</div>
|
113
|
-
<div id="statusbar">
|
114
|
-
<span id="progress">
|
115
|
-
Slide: <span id="slideInfo"></span>
|
116
|
-
</span>
|
117
|
-
<div id="debugInfo"></div>
|
118
|
-
<span id="enableRemote" title="Enables tracking of other presenters.">
|
119
|
-
<label for="remoteToggle">Enable Remote</label><input type="checkbox" id="remoteToggle" autocomplete="off" checked />
|
123
|
+
|
124
|
+
<div id="statusbar">
|
125
|
+
<span id="progress" class="no-mobile">
|
126
|
+
Slide: <span id="slideInfo"></span>
|
127
|
+
</span>
|
128
|
+
<div id="debugInfo"></div>
|
129
|
+
|
130
|
+
<div class="controls">
|
131
|
+
<span id="enableAnnotations" title="Enable the annotation system." class="no-mobile">
|
132
|
+
<label for="annotationsToggle">Annotations</label><input type="checkbox" id="annotationsToggle" autocomplete="off" />
|
120
133
|
</span>
|
121
134
|
<span id="enableFollower" title="Send slide change notifications.">
|
122
135
|
<label for="followerToggle">Update Follower</label><input type="checkbox" id="followerToggle" autocomplete="off" checked />
|
123
136
|
</span>
|
124
|
-
<span id="
|
125
|
-
<label for="
|
137
|
+
<span id="enableRemote" title="Enables tracking of other presenters.">
|
138
|
+
<label for="remoteToggle">Enable Remote</label><input type="checkbox" id="remoteToggle" autocomplete="off" checked />
|
126
139
|
</span>
|
140
|
+
<a class="no-mobile fa fa-external-link-square" aria-hidden="true" href="javascript:toggleNotes();"></a>
|
141
|
+
<i class="no-mobile fa fa-bars notes-grippy ui-resizable-handle ui-resizable-n" aria-hidden="true"></i>
|
127
142
|
</div>
|
128
|
-
</div>
|
129
|
-
</div>
|
130
143
|
|
131
|
-
|
144
|
+
</div>
|
132
145
|
<div id="buttonNav">
|
133
146
|
<div id="buttonPrev"><i class="fa fa-chevron-left fa-lg"></i> Previous</div><div id="buttonNext">Next <i class="fa fa-chevron-right fa-lg"></i></div>
|
134
147
|
</div>
|
135
|
-
|
136
|
-
<h3>Audience Questions</h3>
|
137
|
-
<ol id="unanswered"></ol>
|
138
|
-
<ol id="answered"></ol>
|
139
|
-
</div>
|
148
|
+
|
140
149
|
<div id="notes"></div>
|
141
150
|
</div>
|
151
|
+
|
142
152
|
</div>
|
143
153
|
|
144
154
|
<div id="slides" class="offscreen" <%= 'style="display:none;"' if @slides %>>
|