showoff 0.15.4 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -59,20 +59,23 @@ $(document).ready(function(){
59
59
  });
60
60
  }
61
61
 
62
- // wait until the presentation is loaded to hook up the previews.
63
- // TODO: If we decide to implement this for the audience display, we can move it later
64
- $("body").bind("showoff:loaded", function (event) {
65
- $('#navigation li a.navItem').hover(function() {
66
- var position = $(this).position();
67
- $('#navigationHover').css({top: position.top, left: position.left + $('#navigation').width() + 5})
68
- $('#navigationHover').html(slides.eq($(this).attr('rel')).html());
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(postSlide, 500);
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
- $('#notesWindow').addClass('enabled');
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
- $('#notesWindow').removeClass('enabled');
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
- // Update presenter view, if we spawned one
560
- if (updatepv && 'presenterView' in window) {
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
- pv.update();
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="main">
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
- <div id="center">
67
- <div id="sidebar">
68
- <div id="timerSection">
69
- <input type="button" id="pauseTimer" value="Pause" />
70
- <input type="button" id="stopTimer" value="Cancel" />
71
- <span id="timerLabel">Timer:</span>
72
- <span id="minStart">
73
- <input type="text" size="8" id="timerMinutes"/> min
74
- <input type="button" id="startTimer" value="Start" />
75
- </span>
76
- <div id="timerDisplay"></div>
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="feedbackPace">
79
- <span id="paceSlow">Speed Up!</span>
80
- <span id="paceFast">Slow Down!</span>
81
- <img id="paceMarker" src="<%= @asset_path %>/css/paceMarker.png" />
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
- <div id="presenter">
87
- <div id="frame">
88
- <div id="preview">
89
- <img id="disconnected" src="<%= @asset_path %>/css/disconnected-large.png" />
90
- <div id="prevSlide" class="thumb"><div class="container"></div><h3 class="label">Previous</h3></div>
91
- <div id="nextSlide" class="thumb"><div class="container"></div><h3 class="label">Next</h3></div>
92
- <div id="preso">loading presentation...</div>
93
- </div>
94
- <div id="annotationToolbar">
95
- <label>Tools</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="enableAnnotations" title="Enable the annotation system.">
125
- <label for="annotationsToggle">Annotations</label><input type="checkbox" id="annotationsToggle" autocomplete="off" />
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
- <div id="bottom">
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
- <div id="questions">
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 %>>