showoff 0.17.2 → 0.18.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.
data/locales/pt.yml ADDED
@@ -0,0 +1,160 @@
1
+ pt:
2
+ name: Apresentação Showoff
3
+ menu:
4
+ title: Menu Showoff
5
+ table_of_contents: Índice
6
+ downloads: Downloads
7
+ feedback: Enviando...
8
+ pace:
9
+ label: O palestrante deve...
10
+ slower: Ir mais devagar
11
+ faster: Ir mais rapido
12
+ question:
13
+ label: Faça uma pergunta
14
+ placeholder: Faça uma pergunta...
15
+ feedback:
16
+ label: Envie comentários
17
+ description: Este slide é...
18
+ worst: Ruim
19
+ best: Bom
20
+ why: Por quê...?
21
+ send: Enviar
22
+ edit: Editar Slide Atual
23
+ clear_annotations: Apagar Anotações
24
+ language: Idioma do conteúdo
25
+ close: Fechar
26
+ help: Digite <code>?</code> para ajuda.
27
+ anonymous: Todo conteúdo é anonimo.
28
+ navigation:
29
+ next: Próximo
30
+ previous: Anterior
31
+ loading: carregando apresentação...
32
+ activity_complete: Atividade completada
33
+ follow:
34
+ label: "Modo Seguidor:"
35
+ refresh: "Você tem certeza que quer atualizar o conteúdo do slide?\n\n(Use o `RELOAD` para recarregar completamente a UI inteira)"
36
+ reload: Você tem certeza que quer reiniciar Showoff?
37
+ preshow:
38
+ prompt: Em quanto minutos começar?
39
+ resume: "Resumindo em:"
40
+
41
+ downloads:
42
+ title: Arquivos de Downloads
43
+
44
+ help:
45
+ title: Ajuda
46
+ next: Ir para o próximo slide.
47
+ prev: Ir para o slide anterior.
48
+ contents: Mostrar o Índice.
49
+ follow: Alternar modo seguidor.
50
+ help: Mostrar esta ajuda.
51
+ refresh: Atualizar conteúdo do slide.
52
+ reload: Recarregar Showoff completamente.
53
+ blank: Tela vazia.
54
+ footer: Alternar o rodapé.
55
+ notes: Alternar anotaçōes.
56
+ clear: Limpar resultados de execução do código.
57
+ pause: Pausar a apresentação.
58
+ preshow: Mostrar images de slideshow <tt>preshow</tt> em crônometro.
59
+ execute: Executar o primeiro block de código visível.
60
+ debug: Mostrar informação de debugging.
61
+ close: Fechar
62
+
63
+ stats:
64
+ title: Visualizando Estatísticas
65
+ stray: audiência visualizando slides diferentes do seu.
66
+ idle: audiência não participativa.
67
+ current: Slides que estão sendo visualizados no momento
68
+ elapsed: Tempo gasto em cada slide
69
+ nodata: Nenhum dado a mostrar.
70
+ allcurrent: Toda a audiência esta visualizando o slide do palestrante.
71
+
72
+ forms:
73
+ display: Mostrar Resultados
74
+ save: Salvar
75
+
76
+ presenter:
77
+ topbar:
78
+ annotations: Anotacoōes
79
+ edit: Editar Slide
80
+ report: Relatar Problema com Slide
81
+ stats: Visualizando Estatísticas
82
+ downloads: Downloads
83
+ display: Tela de Apresentação
84
+ print: Imprimir Slides
85
+ settings: Configuraçoōes
86
+ newpage: Abrir em uma nova pagina...
87
+ tooltip:
88
+ annotations: Permitir anotaçōes de subsistema.
89
+ edit: Editar slide atual em uma nova janela.
90
+ report: Relatar Problema com o slide atual.
91
+ stats: Visualizar slides com os quais sua audiência está interagindo.
92
+ downloads: Abrir os arquivos de download em um menu ou nova página.
93
+ display: Permitir Tela de Apresentacão; você deve usá-la no projetor.
94
+ print: Imprimir slides usando uma nova janela.
95
+ settings: Abrir tela de Configuraçōes.
96
+ preview:
97
+ next: Próximo
98
+ previous: Anterior
99
+ mobile:
100
+ update: Atualizar
101
+ notes:
102
+ label: Anotaçoōes Showoff
103
+ personal: Anotaçoōes Pessoais
104
+ timer:
105
+ label: "Cronômetro:"
106
+ start: Iniciar
107
+ pause: Pausar
108
+ resume: Resumir
109
+ cancel: Cancelar
110
+ unit: mminutos
111
+ pace:
112
+ faster: Acelere!
113
+ slower: Desacelere!
114
+ questions: Perguntas da Audiência
115
+ annotation:
116
+ tools: Ferramentas
117
+ lines: Linhas
118
+ shapes: Formas
119
+ status:
120
+ label: "Slides:"
121
+ settings:
122
+ label: Configuracoōes
123
+ close: Fechar
124
+ follower:
125
+ label: Rastreamento de Atualizaçōes
126
+ tooltip: Enviar notificaçōes de alteração de slide.
127
+ description: Quando esta função estiver habilitada, o server do Showoff irá rastrear toda a alteração de slide. Desabilite esta função para visualizar a apresentação sem alterá-la inadvertidamente.
128
+ remote:
129
+ label: Permitir Controle Remoto
130
+ tooltip: Habilita o uso de outros controles.
131
+ description: Quando esta função esta habilitada, você pode carregar o controle em outro navegador (geralmente seu celular) para controlar a apresentação.
132
+ layout:
133
+ label: Layout
134
+ default: Layout Padrão
135
+ thumbs: Mostrar ícone miniatura do slide anterior e do próximo slide.
136
+ beside: Mostrar próximo slide na tela principal do palestrante.
137
+ floating: Abrir o próximo slide em uma nova janela.
138
+ confirmation: As configuraçoōes de segurança do seu navegador requer confirmaçaão antes de abrir uma nova janela.
139
+ open: Abrir Janela
140
+ cancel: Cancelar
141
+ reset:
142
+ label: Limpar configuraçoōes do Showoff.
143
+ tooltip: Reseta configuraçoōes do Showoff UI para os valores padrão.
144
+ language:
145
+ label: Idioma do Conteúdo
146
+ tooltip: Selecione traducoōes ou auto-selecione com base nas configuracoōes de seu navegador.
147
+ description: Esta apresentação esta disponível em outros idiomas. Escolha o idioma que você gostaria de visualizar ou deixe em <tt>automatic</tt> para usar as configuraçōes do seu navegador.
148
+ print:
149
+ label: Escolha o tipo de visualizaçao de anotaçōes
150
+ description: Selecione o conteúdo que voceêê gostaria de mostrar abaixo dos slides.
151
+ none: Não incluir anotaçōes
152
+ notes: Anotaçōes do Palestrante
153
+ handouts: Brochura para Audiência
154
+
155
+ language:
156
+ auto: Automática
157
+ disable: Desabilitar Traduçōes
158
+
159
+ error:
160
+ file_not_found: Arquivo nao Encontrado!
@@ -40,6 +40,10 @@
40
40
  #topbar a,
41
41
  #topbar .ui-widget {
42
42
  text-decoration: none;
43
+ -webkit-user-select: none;
44
+ -moz-user-select: none;
45
+ -ms-user-select: none;
46
+ user-select: none;
43
47
  }
44
48
 
45
49
  #topbar a i {
@@ -50,6 +54,11 @@
50
54
  #topbar .ui-widget:hover {
51
55
  background-color: #263238;
52
56
  }
57
+ #topbar a:active,
58
+ #topbar a.enabled:active,
59
+ #topbar .ui-widget:active {
60
+ background-color: #2e424c;
61
+ }
53
62
 
54
63
  #close-sidebar {
55
64
  padding: .25em;
@@ -106,13 +115,14 @@
106
115
  display: none;
107
116
  position: absolute;
108
117
  z-index: 2147483647;
109
- top: 3em;
118
+ top: 2.95em;
110
119
  left: 25%;
111
120
  max-height: 80%;
112
121
  width: 50%;
113
122
  padding-bottom: 1em;
114
123
  border-radius: 0 0 .5em .5em;
115
124
  overflow: auto;
125
+ background-color: #263238;
116
126
  }
117
127
 
118
128
  #presenterPopup a {
@@ -176,6 +186,9 @@
176
186
  margin: 2px 0px;
177
187
  }
178
188
 
189
+ #timerSection #startTimer {
190
+ float: right;
191
+ }
179
192
  #timerSection #pauseTimer {
180
193
  float: left;
181
194
  display: none;
@@ -97,8 +97,14 @@ pre code {
97
97
  z-index: 2147483647; /* max, see http://www.puidokas.com/max-z-index/ */
98
98
  display: none;
99
99
  }
100
+ #footer .container {
101
+ border: 1px solid #ccc;
102
+ padding: 2px 6px;
103
+ margin: 0 3px;
104
+ border-radius: 3px;
105
+ }
100
106
  #followMode {
101
- display: none;
107
+ font-weight: bold;
102
108
  }
103
109
  #pauseScreen {
104
110
  background: rgba(0, 0, 0, 0.85);
@@ -151,7 +157,8 @@ pre code {
151
157
  margin: 2em;
152
158
  }
153
159
 
154
- .content img {
160
+ .content img,
161
+ .content svg {
155
162
  display:block;
156
163
  margin-left:auto;
157
164
  margin-right:auto;
@@ -265,8 +272,7 @@ pre code {
265
272
 
266
273
  .offscreen { position:absolute; top:0; left:-9999px; overflow:hidden; }
267
274
 
268
- #debugInfo,
269
- #slideFilename {
275
+ body.presenter #debugInfo {
270
276
  margin-left: 30px;
271
277
  }
272
278
 
@@ -386,10 +392,15 @@ img#disconnected {
386
392
  clear: both;
387
393
  }
388
394
 
395
+ .optionWrapper,
389
396
  .buttonWrapper {
390
397
  line-height: 48px;
391
398
  padding: 0 16px;
392
399
  font-weight: bold;
400
+ -webkit-user-select: none;
401
+ -moz-user-select: none;
402
+ -ms-user-select: none;
403
+ user-select: none;
393
404
  }
394
405
 
395
406
  .buttonWrapper:hover,
@@ -508,6 +519,10 @@ img#disconnected {
508
519
  text-decoration: line-through;
509
520
  color: #ccc;
510
521
  }
522
+ #languageMenu {
523
+ line-height: 2em;
524
+ }
525
+
511
526
 
512
527
  /* End Sidebar styling */
513
528
 
@@ -754,6 +769,36 @@ form .element {
754
769
  display: none;
755
770
  }
756
771
 
772
+ /**********************************
773
+ *** form answer key ***
774
+ **********************************/
775
+
776
+ /* no, the option styling will likely not do anything */
777
+ .slide.answerkey form option.incorrect,
778
+ .slide.answerkey form label.incorrect {
779
+ text-decoration: line-through;
780
+ font-weight: 100;
781
+ opacity: .7;
782
+ }
783
+ .slide.answerkey form label.correct,
784
+ .slide.answerkey form option.correct {
785
+ font-weight: 900;
786
+ }
787
+ /* Be careful with order here; these rules depend on cascading order */
788
+ .slide.answerkey input + option,
789
+ .slide.answerkey input + label.incorrect,
790
+ .slide.answerkey input:checked + label.correct,
791
+ .slide.answerkey input:checked + option.correct {
792
+ color: #00AA00; /* green */
793
+ }
794
+ .slide.answerkey input:checked + option,
795
+ .slide.answerkey input:checked + label.incorrect,
796
+ .slide.answerkey input + label.correct,
797
+ .slide.answerkey input + option.correct {
798
+ color: #e74c3c; /* red */
799
+ }
800
+
801
+
757
802
  /*****************
758
803
  *** modals ***
759
804
  *****************/
@@ -1253,6 +1298,11 @@ h1.section_title {
1253
1298
  margin-right:auto;
1254
1299
  }
1255
1300
 
1301
+ /* keep the activity toggle from showing in printed output */
1302
+ .slide.activity .activityToggle {
1303
+ display: none;
1304
+ }
1305
+
1256
1306
  /* Styling to make the handout notes appear in the printed output. */
1257
1307
  .notes-section {
1258
1308
  display: block;
@@ -11,10 +11,6 @@ $(document).ready(function(){
11
11
  // set up the presenter modes
12
12
  mode = { track: true, follow: true, update: true, slave: false, notes: false, annotations: false, layout: 'default'};
13
13
 
14
- // attempt to open another window for the presentation if the mode defaults
15
- // to enabling this. It does not by default, so this is likely a no-op.
16
- openSlave();
17
-
18
14
  // the presenter window doesn't need the reload on resize bit
19
15
  $(window).unbind('resize');
20
16
 
@@ -26,7 +22,7 @@ $(document).ready(function(){
26
22
  // browser security causes a click event to react differently than an actual user click. Even though they're the same damn thing.
27
23
  // $("#report").click( function() { reportIssue() });
28
24
  $("#slaveWindow").click( function() { toggleSlave() });
29
- $("#printSlides").click( function() { printSlides() });
25
+ $("#printSlides").click( function() { printDialog() });
30
26
  $("#settings").click( function() { $("#settings-modal").dialog("open"); });
31
27
  $("#slideSource a").click( function() { openEditor() });
32
28
  $("#notesToggle").click( function() { toggleNotes() });
@@ -51,10 +47,16 @@ $(document).ready(function(){
51
47
  $('#downloadslink').click(function(e) { presenterPopupToggle('/download', e); });
52
48
 
53
49
  $('#layoutSelector').change(function(e) { chooseLayout(e.target.value); });
54
-
55
50
  chooseLayout(null);
56
51
 
57
- $("#settings-modal").dialog({
52
+ // the language selector is configured in showoff.js
53
+
54
+ // must be defined using [] syntax for a variable button name on IE.
55
+ var closeLabel = I18n.t('presenter.settings.close');
56
+ var buttons = {};
57
+ buttons[closeLabel] = function() { $(this).dialog( "close" ); };
58
+
59
+ $("#settings-modal, #print-modal").dialog({
58
60
  autoOpen: false,
59
61
  dialogClass: "no-close",
60
62
  draggable: false,
@@ -62,11 +64,7 @@ $(document).ready(function(){
62
64
  modal: true,
63
65
  resizable: false,
64
66
  width: 400,
65
- buttons: {
66
- Close: function() {
67
- $( this ).dialog( "close" );
68
- }
69
- }
67
+ buttons: buttons
70
68
  });
71
69
 
72
70
  $("#annotationsToggle").checkboxradio({
@@ -152,6 +150,7 @@ $(document).ready(function(){
152
150
  $('#followerToggle').change( toggleUpdater );
153
151
  $('#annotationsToggle').change( toggleAnnotations );
154
152
 
153
+ initializeSettings();
155
154
  setInterval(function() { updatePace() }, 1000);
156
155
 
157
156
  setInterval(function() {
@@ -159,7 +158,7 @@ $(document).ready(function(){
159
158
  var percent = json['stray_p'];
160
159
  if(percent > 25) {
161
160
  $('#topbar #statslink').addClass('warning');
162
- $('#topbar #statslink').attr('title', percent + "% of your audience is not viewing the same slide you are.");
161
+ $('#topbar #statslink').attr('title', percent + '%' + I18n.t('stats.stray'));
163
162
  }
164
163
  else {
165
164
  $('#stray').hide(); // in case the popup is open
@@ -200,12 +199,17 @@ $(document).ready(function(){
200
199
 
201
200
  function presenterPopupToggle(page, event) {
202
201
  event.preventDefault();
202
+ // remove class from both so we don't lose an active state if user clicks the wrong item
203
+ $('#statslink').removeClass('enabled');
204
+ $('#downloadslink').removeClass('enabled');
205
+
203
206
  var popup = $('#presenterPopup');
204
207
  if (popup.length > 0) {
205
208
  popup.slideUp(200, function () {
206
209
  popup.remove();
207
210
  });
208
211
  } else {
212
+ $(event.target).addClass('enabled');
209
213
  popup = $('<div>');
210
214
  popup.attr('id', 'presenterPopup');
211
215
  $.get(page, function(data) {
@@ -216,7 +220,7 @@ function presenterPopupToggle(page, event) {
216
220
  href: page,
217
221
  target: '_new'
218
222
  });
219
- link.text('Open in a new page...');
223
+ link.text(I18n.t('presenter.topbar.newpage'));
220
224
 
221
225
  content.attr('id', page.substring(1, page.length));
222
226
  content.append(link);
@@ -261,22 +265,27 @@ function windowIsOpen(window) {
261
265
 
262
266
  function toggleSlave() {
263
267
  mode.slave = !mode.slave;
264
- openSlave();
268
+ if (mode.slave) {
269
+ openSlave();
270
+ } else {
271
+ closeSlave();
272
+ }
265
273
  }
266
274
 
267
275
  // Open, or maintain connection & reopen slave window.
268
276
  function openSlave()
269
277
  {
270
- if (mode.slave) {
271
- try {
272
- if(windowIsClosed(slaveWindow)){
273
- slaveWindow = window.open('/' + window.location.hash, 'toolbar');
274
- }
275
- else if(slaveWindow.location.hash != window.location.hash) {
276
- // maybe we need to reset content?
277
- slaveWindow.location.href = '/' + window.location.hash;
278
- }
278
+ try {
279
+ if(windowIsClosed(slaveWindow)){
280
+ slaveWindow = window.open('/' + window.location.hash, 'toolbar');
281
+ }
282
+ else if(slaveWindow.location.hash != window.location.hash) {
283
+ // maybe we need to reset content?
284
+ slaveWindow.location.href = '/' + window.location.hash;
285
+ }
279
286
 
287
+ // give the window time to load before poking at it
288
+ window.setTimeout(function() {
280
289
  // maintain the pointer back to the parent.
281
290
  slaveWindow.presenterView = window;
282
291
  slaveWindow.mode = { track: false, slave: true, follow: false };
@@ -284,26 +293,41 @@ function openSlave()
284
293
  // Add a class to differentiate from the audience view
285
294
  slaveWindow.document.getElementById("preso").className = 'display';
286
295
 
287
- $('#slaveWindow').addClass('enabled');
288
- }
289
- catch(e) {
290
- console.log('Failed to open or connect display window. Popup blocker?');
291
- }
296
+ // call back and update the parent presenter if the window is closed
297
+ slaveWindow.onunload = function(e) {
298
+ slaveWindow.opener.closeSlave(true);
299
+ };
300
+ }, 500);
292
301
 
293
- // Set up a maintenance loop to keep the connection between windows. I wish there were a cleaner way to do this.
294
- if (typeof maintainSlave == 'undefined') {
295
- maintainSlave = setInterval(openSlave, 1000);
296
- }
302
+ $('#slaveWindow').addClass('enabled');
297
303
  }
298
- else {
299
- try {
304
+ catch(e) {
305
+ console.log('Failed to open or connect display window. Popup blocker?');
306
+ }
307
+ }
308
+
309
+ function closeSlave(calledByChild) {
310
+ try {
311
+ mode.slave = false;
312
+ $('#slaveWindow').removeClass('enabled');
313
+
314
+ if(calledByChild) {
315
+ // if this is called by the display view, we don't want to try to close it again.
316
+ // browsers are the worst. If the user hit *refresh*, then this should reconnect the display view
317
+ window.setTimeout(function() {
318
+ if(! windowIsClosed(slaveWindow)) {
319
+ openSlave();
320
+ }
321
+ }, 500);
322
+ } else {
323
+ // called normally and close the display view
300
324
  slaveWindow && slaveWindow.close();
301
- $('#slaveWindow').removeClass('enabled');
302
- }
303
- catch (e) {
304
- console.log('Display window failed to close properly.');
305
325
  }
306
326
  }
327
+ catch (e) {
328
+ console.log('Display window failed to close properly.');
329
+ }
330
+
307
331
  }
308
332
 
309
333
  function nextSlideNum(url) {
@@ -357,7 +381,7 @@ function toggleNotes() {
357
381
  if (mode.notes) {
358
382
  try {
359
383
  if(windowIsClosed(notesWindow)){
360
- notesWindow = blankStyledWindow("Showoff Notes", 'width=350,height=450', 'notes', true);
384
+ notesWindow = blankStyledWindow(I18n.t('notes.label'), 'width=350,height=450', 'notes', true);
361
385
  window.setTimeout(function() {
362
386
  // call back and update the parent presenter if the window is closed
363
387
  notesWindow.onunload = function(e) {
@@ -438,15 +462,53 @@ function blankStyledWindow(title, dimensions, classes, resizable) {
438
462
  return newWindow;
439
463
  }
440
464
 
441
- function printSlides()
465
+ function printDialog() {
466
+ var list = $('#print-modal #print-sections');
467
+
468
+ if(! list.hasClass('processed')) {
469
+ sections = getAllSections()
470
+ sections.unshift('') // add the "none" option
471
+ sections.forEach(function(section) {
472
+ var link = $('<a>');
473
+ var item = $('<li>');
474
+ link.attr('href', '#');
475
+ link.click(function(){
476
+ printSlides(section);
477
+ });
478
+
479
+ switch(section) {
480
+ case '':
481
+ link.text(I18n.t('presenter.print.none'));
482
+ break;
483
+ case 'notes':
484
+ link.text(I18n.t('presenter.print.notes'));
485
+ break;
486
+ case 'handouts':
487
+ link.text(I18n.t('presenter.print.handouts'));
488
+ break;
489
+ default:
490
+ link.text(section);
491
+ }
492
+
493
+ item.append(link);
494
+ list.append(item);
495
+ });
496
+ list.addClass('processed');
497
+ }
498
+
499
+ $("#print-modal").dialog("open");
500
+ }
501
+
502
+ function printSlides(section)
442
503
  {
443
504
  try {
444
- var printWindow = window.open('/print');
505
+ var printWindow = window.open('/print/'+section);
445
506
  printWindow.window.print();
446
507
  }
447
508
  catch(e) {
448
509
  console.log('Failed to open print window. Popup blocker?');
449
510
  }
511
+ $("#print-modal").dialog("close");
450
512
  }
451
513
 
452
514
  function postQuestion(question, questionID) {
@@ -551,7 +613,7 @@ gotoSlide = function (slideNum)
551
613
  if ( !mobile() ) {
552
614
  $("#navigation li li").get(slidenum).scrollIntoView();
553
615
  }
554
- postSlide()
616
+ postSlide();
555
617
  }
556
618
 
557
619
  // override with an alternate implementation.
@@ -657,14 +719,19 @@ function postSlide() {
657
719
  }
658
720
 
659
721
  var nextIndex = slidenum + 1;
660
- var nextSlide = (nextIndex >= slides.size()) ? '' : slides.eq(nextIndex).html();
661
- var prevSlide = (slidenum > 0) ? slides.eq(slidenum - 1).html() : ''
722
+ var nextSlide = (nextIndex >= slides.size()) ? $('') : slides.eq(nextIndex);
723
+ var nextThumb = $('#nextSlide .container');
724
+ var prevSlide = (slidenum > 0) ? slides.eq(slidenum - 1) : $('');
725
+ var prevThumb = $('#prevSlide .container');
726
+
727
+ nextThumb.html(nextSlide.html());
728
+ prevThumb.html(prevSlide.html());
662
729
 
663
- $('#nextSlide .container').html(nextSlide);
664
- $('#prevSlide .container').html(prevSlide);
730
+ copyBackground(nextSlide, nextThumb);
731
+ copyBackground(prevSlide, prevThumb);
665
732
 
666
733
  if (windowIsOpen(nextWindow)) {
667
- $(nextWindow.document.body).html(nextSlide);
734
+ $(nextWindow.document.body).html(nextSlide.html());
668
735
  }
669
736
 
670
737
  if (windowIsOpen(notesWindow)) {
@@ -674,7 +741,7 @@ function postSlide() {
674
741
  var fileName = currentSlide.children('div').first().attr('ref');
675
742
  $('#slideFile').text(fileName);
676
743
  $('#progress').progressbar({ max: slideTotal })
677
- .progressbar('value', slidenum);
744
+ .progressbar('value', slidenum+1);
678
745
 
679
746
  $("#notes div.form.wrapper").each(function(e) {
680
747
  renderFormInterval = renderFormWatcher($(this));
@@ -870,6 +937,12 @@ function stopTimer() {
870
937
  unpinSidebar('timer');
871
938
  }
872
939
 
940
+ function initializeSettings() {
941
+ // enable this if we are the "master" presenter
942
+ $("#followerToggle").prop("checked", master);
943
+ mode.update = $("#followerToggle").prop("checked");
944
+ }
945
+
873
946
  /********************
874
947
  Follower Code
875
948
  ********************/