showoff 0.14.3 → 0.15.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.
@@ -208,7 +208,7 @@ jQuery.fn.extend({
208
208
 
209
209
  // let the annotation overlay own mouse events.
210
210
  // This means that clicking links or copying text will not work.
211
- $(this).css('pointer-events', 'initial');
211
+ $(this).css('pointer-events', 'auto');
212
212
 
213
213
  $(this).unbind( "mousedown" );
214
214
  $(this).mousedown(function(e){
File without changes
@@ -1,3 +1,4 @@
1
+ /* https://github.com/smparkes/jquery.print/blob/master/src/jquery.print.js */
1
2
  (function($) {
2
3
 
3
4
  function print_array(obj, opts) {
@@ -60,7 +61,7 @@
60
61
  '\\': '\\\\'
61
62
  };
62
63
  var r = /["\\\x00-\x1f\x7f-\x9f]/g;
63
-
64
+
64
65
  var str = r.test(value)
65
66
  ? value.replace(r, function (a) {
66
67
  var c = character_substitutions[a];
@@ -106,4 +107,4 @@
106
107
  return obj.toString().replace(/\n\s*/g, '');
107
108
  }
108
109
 
109
- })(jQuery);
110
+ })(jQuery);
@@ -1,3 +1,4 @@
1
+ /* https://github.com/technoweenie/jquery.doubletap */
1
2
  (function($) {
2
3
  var touchStatus = function(target, touch) {
3
4
  this.target = $(target);
@@ -31,7 +32,7 @@
31
32
 
32
33
  touchStatus.prototype.checkForDoubleTap = function() {
33
34
  if(touchStatus.latestTap) {
34
- if((new Date() - touchStatus.latestTap) < 400)
35
+ if((new Date() - touchStatus.latestTap) < 400)
35
36
  this.eventType = 'doubletap'
36
37
  }
37
38
  if(!this.eventType) this.eventType = 'tap'
@@ -102,4 +103,4 @@
102
103
  if(callback) this.bind('touch', callback)
103
104
  return this;
104
105
  }
105
- })(jQuery);
106
+ })(jQuery);
@@ -1,2 +1,3 @@
1
+ /* https://github.com/rapportive-oss/jquery-parsequery */
1
2
  (function($){$.parseQuery=function(options){var config={query:window.location.search||""},params={};if(typeof options==='string'){options={query:options};}
2
3
  $.extend(config,$.parseQuery,options);config.query=config.query.replace(/^\?/,'');$.each(config.query.split(config.separator),function(i,param){var pair=param.split('='),key=config.decode(pair.shift(),null).toString(),value=config.decode(pair.length?pair.join('='):null,key);if(config.array_keys(key)){params[key]=params[key]||[];params[key].push(value);}else{params[key]=value;}});return params;};$.parseQuery.decode=$.parseQuery.default_decode=function(string){return decodeURIComponent((string||"").replace('+',' '));};$.parseQuery.array_keys=function(){return false;};$.parseQuery.separator="&";}(jQuery));
@@ -1,6 +1,6 @@
1
1
  // presenter js
2
2
  var slaveWindow = null;
3
- var nextWindow = null;
3
+ var nextWindow = null;
4
4
  var notesWindow = null;
5
5
 
6
6
  var paceData = [];
@@ -9,7 +9,7 @@ section = 'notes'; // which section the presenter has chosen to view
9
9
 
10
10
  $(document).ready(function(){
11
11
  // set up the presenter modes
12
- mode = { track: true, follow: true, update: true, slave: false, next: false, notes: false, annotations: false};
12
+ mode = { track: true, follow: true, update: true, slave: false, notes: false, annotations: false, layout: 'default'};
13
13
 
14
14
  // attempt to open another window for the presentation if the mode defaults
15
15
  // to enabling this. It does not by default, so this is likely a no-op.
@@ -32,6 +32,10 @@ $(document).ready(function(){
32
32
  $('#downloadslink').click(function(e) {
33
33
  presenterPopupToggle('/download', e);
34
34
  });
35
+ $('#layoutSelector').change(function(e) {
36
+ chooseLayout(e.target.value);
37
+ });
38
+
35
39
 
36
40
  // Bind events for mobile viewing
37
41
  if( mobile() ) {
@@ -54,6 +58,20 @@ $(document).ready(function(){
54
58
  });
55
59
  }
56
60
 
61
+ // wait until the presentation is loaded to hook up the previews.
62
+ // TODO: If we decide to implement this for the audience display, we can move it later
63
+ $("body").bind("showoff:loaded", function (event) {
64
+ $('#navigation li a.navItem').hover(function() {
65
+ var position = $(this).position();
66
+ $('#navigationHover').css({top: position.top, left: position.left + $('#navigation').width() + 5})
67
+ $('#navigationHover').html(slides.eq($(this).attr('rel')).html());
68
+ $('#navigationHover').show();
69
+ },function() {
70
+ $('#navigationHover').hide();
71
+ });
72
+ });
73
+
74
+
57
75
  // Hide with js so jquery knows what display property to assign when showing
58
76
  toggleAnnotations();
59
77
 
@@ -143,7 +161,7 @@ function presenterPopupToggle(page, event) {
143
161
 
144
162
  content.attr('id', page.substring(1, page.length));
145
163
  content.append(link);
146
- /* use .sibliings() because of how jquery formats $(data) */
164
+ /* use .siblings() because of how jquery formats $(data) */
147
165
  content.append($(data).siblings('#wrapper').html());
148
166
  popup.append(content);
149
167
 
@@ -175,16 +193,26 @@ function openEditor() {
175
193
  $.get(link);
176
194
  }
177
195
 
196
+ function windowIsClosed(window)
197
+ {
198
+ return(window == null || typeof(window) == 'undefined' || window.closed);
199
+ }
200
+
201
+ function windowIsOpen(window) {
202
+ return (window && typeof(window) != 'undefined' && !window.closed)
203
+ }
204
+
178
205
  function toggleSlave() {
179
206
  mode.slave = !mode.slave;
180
207
  openSlave();
181
208
  }
182
209
 
210
+ // Open, or maintain connection & reopen slave window.
183
211
  function openSlave()
184
212
  {
185
213
  if (mode.slave) {
186
214
  try {
187
- if(slaveWindow == null || typeof(slaveWindow) == 'undefined' || slaveWindow.closed){
215
+ if(windowIsClosed(slaveWindow)){
188
216
  slaveWindow = window.open('/' + window.location.hash, 'toolbar');
189
217
  }
190
218
  else if(slaveWindow.location.hash != window.location.hash) {
@@ -223,65 +251,21 @@ function openSlave()
223
251
 
224
252
  function nextSlideNum(url) {
225
253
  // Some fudging because the first slide is slide[0] but numbered 1 in the URL
226
- console.log(typeof(url));
227
254
  var snum;
228
255
  if (typeof(url) == 'undefined') { snum = currentSlideFromParams()+1; }
229
256
  else { snum = currentSlideFromParams()+2; }
230
257
  return snum;
231
258
  }
232
259
 
233
- function toggleNext() {
234
- mode.next = !mode.next;
235
- openNext();
236
- }
237
-
238
- function openNext()
239
- {
240
- if (mode.next) {
241
- try {
242
- if(nextWindow == null || typeof(nextWindow) == 'undefined' || nextWindow.closed){
243
- nextWindow = window.open('/?track=false&feedback=false&next=true#' + nextSlideNum(true),'','width=320,height=300');
244
- }
245
- else if(nextWindow.location.hash != '#' + nextSlideNum(true)) {
246
- // maybe we need to reset content?
247
- nextWindow.location.href = '/?track=false&feedback=false&next=true#' + nextSlideNum(true);
248
- }
249
-
250
- // maintain the pointer back to the parent.
251
- nextWindow.presenterView = window;
252
- nextWindow.mode = { track: false, next: true, follow: true };
253
-
254
- $('#nextWindow').addClass('enabled');
255
- }
256
- catch(e) {
257
- console.log('Failed to open or connect next window. Popup blocker?');
258
- }
259
- }
260
- else {
261
- try {
262
- nextWindow && nextWindow.close();
263
- $('#nextWindow').removeClass('enabled');
264
- }
265
- catch (e) {
266
- console.log('Next window failed to close properly.');
267
- }
268
- }
269
- }
270
260
 
271
261
  function toggleNotes() {
272
262
  mode.notes = !mode.notes;
273
- openNotes();
274
- }
275
263
 
276
- function openNotes()
277
- {
278
264
  if (mode.notes) {
279
265
  try {
280
- if(notesWindow == null || typeof(notesWindow) == 'undefined' || notesWindow.closed){
281
- // yes, the explicit address is needed. Because Chrome.
282
- notesWindow = window.open('about:blank', '', 'width=350,height=450');
283
- notesWindow.document.title = "Showoff Notes";
284
- postSlide();
266
+ if(windowIsClosed(notesWindow)){
267
+ notesWindow = blankStyledWindow("Showoff Notes", 'width=350,height=450', 'notes', true);
268
+ window.setTimeout(postSlide, 500);
285
269
  }
286
270
  $('#notesWindow').addClass('enabled');
287
271
  }
@@ -300,6 +284,40 @@ function openNotes()
300
284
  }
301
285
  }
302
286
 
287
+ function blankStyledWindow(title, dimensions, classes, resizable) {
288
+ // yes, the explicit address is needed. Because Chrome.
289
+ var opts = "status=0,toolbar=0,location=0,menubar=0,"+dimensions;
290
+ if(resizable) {
291
+ opts += ",resizable=1,scrollbars=1";
292
+ }
293
+ newWindow = window.open('about:blank','', opts);
294
+
295
+ // allow time for the window to load for Firefox and IE
296
+ window.setTimeout(function() {
297
+ newWindow.document.title = title;
298
+
299
+ // IE is terrible and will explode if you try to add a DOM element to another
300
+ // document. Instead, serialize everything into STRINGS and let jquery rebuild
301
+ // them into elements again in the context of the other document.
302
+ // Because IE.
303
+
304
+ $(newWindow.document.head).append('<base href="' + window.location.origin + '"/>');
305
+ $('link[rel="stylesheet"]').each(function() {
306
+ var href = $(this).attr('href');
307
+ var style = '<link rel="stylesheet" type="text/css" href="' + href + '">'
308
+ $(newWindow.document.head).append(style);
309
+ });
310
+
311
+ $(newWindow.document.body).addClass('floating');
312
+ if(classes) {
313
+ $(newWindow.document.body).addClass(classes);
314
+ }
315
+
316
+ }, 500);
317
+
318
+ return newWindow;
319
+ }
320
+
303
321
  function printSlides()
304
322
  {
305
323
  try {
@@ -422,7 +440,7 @@ function markCompleted(questionID) {
422
440
  function update() {
423
441
  if(mode.update) {
424
442
  var slideName = $("#slideFile").text();
425
- ws.send(JSON.stringify({ message: 'update', slide: slidenum, name: slideName}));
443
+ ws.send(JSON.stringify({ message: 'update', slide: slidenum, name: slideName, increment: incrCurr}));
426
444
  }
427
445
  }
428
446
 
@@ -499,7 +517,18 @@ function postSlide() {
499
517
  $('#notes').prepend(ul);
500
518
  }
501
519
 
502
- if (notesWindow && typeof(notesWindow) != 'undefined' && !notesWindow.closed) {
520
+ var nextIndex = slidenum + 1;
521
+ var nextSlide = (nextIndex >= slides.size()) ? '' : slides.eq(nextIndex).html();
522
+ var prevSlide = (slidenum > 0) ? slides.eq(slidenum - 1).html() : ''
523
+
524
+ $('#nextSlide .container').html(nextSlide);
525
+ $('#prevSlide .container').html(prevSlide);
526
+
527
+ if (windowIsOpen(nextWindow)) {
528
+ $(nextWindow.document.body).html(nextSlide);
529
+ }
530
+
531
+ if (windowIsOpen(notesWindow)) {
503
532
  $(notesWindow.document.body).html(notes);
504
533
  }
505
534
 
@@ -522,18 +551,19 @@ function presenterKeyDown(event){
522
551
  }
523
552
 
524
553
  switch(getAction(event)) {
525
- case 'DEBUG': toggleDebug(); break;
526
- case 'PREV': presPrevStep(); break; // Watch that this uses presPrevStep and not prevStep
527
- case 'NEXT': presNextStep(); break; // Same here
528
- case 'RELOAD': reloadSlides(); break;
529
- case 'CONTENTS': toggleContents(); break;
530
- case 'HELP': toggleHelp(); break;
531
- case 'BLANK': blankScreen(); break;
532
- case 'FOOTER': toggleFooter(); break;
533
- case 'FOLLOW': toggleFollow(); break;
534
- case 'NOTES': toggleNotes(); break;
535
- case 'PAUSE': togglePause(); break;
536
- case 'PRESHOW': togglePreShow(); break;
554
+ case 'DEBUG': toggleDebug(); break;
555
+ case 'PREV': presPrevStep(); break; // Watch that this uses presPrevStep and not prevStep
556
+ case 'NEXT': presNextStep(); break; // Same here
557
+ case 'REFRESH': reloadSlides(); break;
558
+ case 'RELOAD': reloadSlides(true); break;
559
+ case 'CONTENTS': toggleContents(); break;
560
+ case 'HELP': toggleHelp(); break;
561
+ case 'BLANK': blankScreen(); break;
562
+ case 'FOOTER': toggleFooter(); break;
563
+ case 'FOLLOW': toggleFollow(); break;
564
+ case 'NOTES': toggleNotes(); break;
565
+ case 'PAUSE': togglePause(); break;
566
+ case 'PRESHOW': togglePreShow(); break;
537
567
  case 'CLEAR':
538
568
  removeResults();
539
569
  try {
@@ -722,3 +752,100 @@ function toggleAnnotations()
722
752
  $('canvas.annotations').hide();
723
753
  }
724
754
  }
755
+
756
+ function openNext() {
757
+ $("#nextWindowConfirmation").slideUp(125);
758
+ try {
759
+ if(windowIsClosed(nextWindow)){
760
+ nextWindow = blankStyledWindow("Next Slide Preview", 'width=320,height=300', 'next');
761
+
762
+ // Firefox doesn't load content properly unless we delay it slightly. Yay for race conditions.
763
+ // nextWindow.addEventListener("unload", function() {
764
+ window.setTimeout(function() {
765
+ // call back and update the parent presenter if the window is closed
766
+ nextWindow.onunload = function(e) {
767
+ nextWindow.opener.chooseLayout('default');
768
+ };
769
+
770
+ postSlide();
771
+ }, 500);
772
+
773
+ }
774
+ }
775
+ catch(e) {
776
+ console.log(e);
777
+ console.log('Failed to open or connect next window. Popup blocker?');
778
+ }
779
+ }
780
+
781
+ /********************
782
+ Layout selection incorporates previews and the old next window
783
+ ********************/
784
+ function chooseLayout(layout)
785
+ {
786
+ // in case we're being called externally, make the UI match
787
+ $('#layoutSelector').val(layout);
788
+ $("#nextWindowConfirmation").slideUp(125);
789
+ console.log("Setting layout to " + layout);
790
+
791
+ // change focus so we don't inadvertently change layout again by changing slides
792
+ $("#preview").focus();
793
+ $("#layoutSelector").blur();
794
+
795
+ // what we are switching *from*
796
+ switch(mode.layout) {
797
+ case 'thumbs':
798
+ $('#preview').removeClass('thumbs');
799
+ $('#preview .thumb').hide();
800
+ break;
801
+
802
+ case 'beside':
803
+ $('#preview').removeClass('beside');
804
+ $('#preview #nextSlide .container').removeAttr("style");
805
+ $('#preview #nextSlide').hide();
806
+ break;
807
+
808
+ case 'floating':
809
+ try {
810
+ if (nextWindow) {
811
+ // unregister the event so we don't accidentally double-fire
812
+ nextWindow.window.onunload = null;
813
+ nextWindow.close();
814
+ }
815
+ }
816
+ catch (e) {
817
+ console.log(e);
818
+ console.log('Next window failed to close properly.');
819
+ }
820
+ break;
821
+
822
+ default:
823
+
824
+ }
825
+
826
+ // what we are switching *to*
827
+ switch(layout) {
828
+ case 'thumbs':
829
+ $('#preview').addClass('thumbs');
830
+ $('#preview .thumb').show();
831
+ break;
832
+
833
+ case 'beside':
834
+ $('#preview').addClass('beside');
835
+ $('#preview #nextSlide').show();
836
+
837
+ var w = $('#nextSlide .container').width();
838
+ $('#nextSlide .container').height(w*.75)
839
+ break;
840
+
841
+ case 'floating':
842
+ $("#nextWindowConfirmation").slideDown(125);
843
+ break;
844
+
845
+ default:
846
+
847
+ }
848
+
849
+ mode.layout = layout;
850
+ zoom(true);
851
+ }