<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Slides | Ben Dêivide</title>
    <link>http://bendeivide.github.io/slides/</link>
      <atom:link href="http://bendeivide.github.io/slides/index.xml" rel="self" type="application/rss+xml" />
    <description>Slides</description>
    <generator>Wowchemy (https://wowchemy.com)</generator><language>pt</language><lastBuildDate>Tue, 05 Feb 2019 00:00:00 +0000</lastBuildDate>
    <item>
      <title>R como uma ferramenta acadêmica</title>
      <link>http://bendeivide.github.io/slides/ramb-academico/</link>
      <pubDate>Tue, 05 Feb 2019 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/ramb-academico/</guid>
      <description>&lt;h1 id=&#34;r-como-uma-ferramenta-acadêmica&#34;&gt;R como uma ferramenta acadêmica&lt;/h1&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Ben Dêivide&lt;/a&gt; | &lt;a href=&#34;https://www.ufsj.edu.br/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;UFSJ&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;apresentação-com-selo-dc&#34;&gt;Apresentação com selo DC&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/dc/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/ramb-academico/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_57f4d021c573f1cdb22f5303fccfacd9.webp 400w,
               /slides/ramb-academico/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_e3124639f3c96b16d12396d9954194c3.webp 760w,
               /slides/ramb-academico/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/ramb-academico/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_57f4d021c573f1cdb22f5303fccfacd9.webp&#34;
               width=&#34;385&#34;
               height=&#34;406&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;acesso-ao-material-dessa-apresentação&#34;&gt;Acesso ao material dessa apresentação&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/bendeivide/palestras/tree/master/ramb-academico&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/ramb-academico/folder_hu84ae0d30d5154d1e73aaf9945c348d03_20466_620e1c48e451842e2f4135b7117821ad.webp 400w,
               /slides/ramb-academico/folder_hu84ae0d30d5154d1e73aaf9945c348d03_20466_81e4eb609876936d8a5e708f395fd9b9.webp 760w,
               /slides/ramb-academico/folder_hu84ae0d30d5154d1e73aaf9945c348d03_20466_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/ramb-academico/folder_hu84ae0d30d5154d1e73aaf9945c348d03_20466_620e1c48e451842e2f4135b7117821ad.webp&#34;
               width=&#34;607&#34;
               height=&#34;471&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;nota&#34;&gt;Nota&lt;/h2&gt;
&lt;p&gt;Essa apresentação terá um viés, pois apesar do poder que a ambiente &lt;code&gt;R&lt;/code&gt; tem, muitos dos exemplos estarão dentro das minhas necessidades/limitações pessoais e profissionais. Portanto, um resultado do que experimento e venho experienciando!&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;histórico-sobre-o-ambiente-r&#34;&gt;Histórico sobre o ambiente &lt;code&gt;R&lt;/code&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Criadores Ross Ihaka e por Robert Gentleman (Nova Zelândia), 1993&lt;/li&gt;
&lt;li&gt;Baseado na linguagem S, criado por John Chambers e colaboradores (Primeira versão 1976)&lt;/li&gt;
&lt;li&gt;Atualmente é mantida por colaboradores voluntários em todo o mundo&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;histórico-sobre-o-ambiente-r-1&#34;&gt;Histórico sobre o ambiente &lt;code&gt;R&lt;/code&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Linguagem pode ser orientada a objetos, Código aberto, funcional, metapragmática, Licença GNU&lt;/li&gt;
&lt;li&gt;Repositório &lt;a href=&#34;https://cran.r-project.org/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;CRAN&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Popularidade com o &lt;a href=&#34;https://rstudio.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;RStudio&lt;/a&gt; (Joseph J. Allaire)&lt;/li&gt;
&lt;li&gt;Como instalar o R?
Como instalar o RStudio?&lt;/li&gt;
&lt;li&gt;Como usar o R?&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;curso-r-nível-básico&#34;&gt;Curso R (Nível Básico)&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/courses/cursor/nbasico/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;Nível Básico&#34; srcset=&#34;
               /slides/ramb-academico/cursor-nb_hu8cbf2d1b9b5244f1524037e4474c538e_69900_4b297cb8f0e33e442ebf99b215388034.webp 400w,
               /slides/ramb-academico/cursor-nb_hu8cbf2d1b9b5244f1524037e4474c538e_69900_f138ba75b6cb4eb62d1ecea4bcae0172.webp 760w,
               /slides/ramb-academico/cursor-nb_hu8cbf2d1b9b5244f1524037e4474c538e_69900_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/ramb-academico/cursor-nb_hu8cbf2d1b9b5244f1524037e4474c538e_69900_4b297cb8f0e33e442ebf99b215388034.webp&#34;
               width=&#34;593&#34;
               height=&#34;579&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;curso-r-ni&#34;&gt;Curso R (NI)&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/post/cursorni2/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;Nível Intermediário&#34; srcset=&#34;
               /slides/ramb-academico/cursor-ni_hua909e2f7dc5b7deac580280a2231351e_70067_01ee0fc5dca62b5827c4744b677401e2.webp 400w,
               /slides/ramb-academico/cursor-ni_hua909e2f7dc5b7deac580280a2231351e_70067_2be287ff636a8ea73ce5b5354154f128.webp 760w,
               /slides/ramb-academico/cursor-ni_hua909e2f7dc5b7deac580280a2231351e_70067_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/ramb-academico/cursor-ni_hua909e2f7dc5b7deac580280a2231351e_70067_01ee0fc5dca62b5827c4744b677401e2.webp&#34;
               width=&#34;593&#34;
               height=&#34;579&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;rapidinhas-do-r&#34;&gt;Rapidinhas do R&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/project/rapidinhasr/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/ramb-academico/rapidinhasr_huf4c584a0ea803c0b4fded9f2abc27f53_510973_df46483f285db6db6d908bc356b06e75.webp 400w,
               /slides/ramb-academico/rapidinhasr_huf4c584a0ea803c0b4fded9f2abc27f53_510973_db647e21fc70a6855b86924338dcb47a.webp 760w,
               /slides/ramb-academico/rapidinhasr_huf4c584a0ea803c0b4fded9f2abc27f53_510973_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/ramb-academico/rapidinhasr_huf4c584a0ea803c0b4fded9f2abc27f53_510973_df46483f285db6db6d908bc356b06e75.webp&#34;
               width=&#34;760&#34;
               height=&#34;374&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;ferramentas-do-r-além-do-fim-estatístico&#34;&gt;Ferramentas do &lt;code&gt;R&lt;/code&gt; além do fim Estatístico&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Análises Estatísticas ❌&lt;/li&gt;
&lt;li&gt;Criação e divulgação de materiais científicos:
&lt;ul&gt;
&lt;li&gt;Materiais Dinâmicos (HTML, JavaScript, CSS, &lt;code&gt;\(\LaTeX\)&lt;/code&gt;, &lt;code&gt;R&lt;/code&gt;, PDF) ✔️&lt;/li&gt;
&lt;li&gt;Materiais estatísticos (HTML, PDF, EPUB, WORD, SLIDES) ✔️&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;ferramentas-do-r-além-do-fim-estatístico-1&#34;&gt;Ferramentas do &lt;code&gt;R&lt;/code&gt; além do fim Estatístico&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Desenvolvimento de pacotes  ✔️
&lt;ul&gt;
&lt;li&gt;Criação de GUIs para pacotes (Pacotes &lt;code&gt;tcltk&lt;/code&gt;, &lt;code&gt;GTK+&lt;/code&gt;, &lt;code&gt;shiny&lt;/code&gt;) ✔️&lt;/li&gt;
&lt;li&gt;Documentação de pacotes (Vignettes, tutorial de pacote) ✔️&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Divulgação de todos esses materiais ✔️&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;o-que-será-necessário-para-usar-essas-ferramentas&#34;&gt;O que será necessário para usar essas ferramentas?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://youtu.be/Gei-gtBlMos&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Instalação do &lt;code&gt;R&lt;/code&gt;&lt;/a&gt; e &lt;a href=&#34;https://youtu.be/Gei-gtBlMos&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;RStudio/Pandoc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;No &lt;code&gt;R&lt;/code&gt; &lt;a href=&#34;https://youtu.be/YRSdoyfqp_g&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;instalar os pacotes&lt;/a&gt;:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;rmarkdown&lt;/code&gt; e &lt;code&gt;knitr&lt;/code&gt; - Pacotes mais importantes!&lt;/li&gt;
&lt;li&gt;&lt;code&gt;shiny&lt;/code&gt; - Pacote para criação de materiais dinâmicos&lt;/li&gt;
&lt;li&gt;&lt;code&gt;devtools&lt;/code&gt; e &lt;code&gt;usethis&lt;/code&gt; - kit de ferramentas&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rsconnect&lt;/code&gt; - Pacote para enviar seu arquivo para &lt;em&gt;shinyapps.io&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;o-que-será-necessário-para-usar-essas-ferramentas-1&#34;&gt;O que será necessário para usar essas ferramentas?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;No &lt;code&gt;R&lt;/code&gt; &lt;a href=&#34;https://youtu.be/YRSdoyfqp_g&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;instalar os pacotes&lt;/a&gt;:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;tinytex&lt;/code&gt; - Latex (Caso você não queira instalar o &lt;code&gt;\(\LaTeX\)&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rticles&lt;/code&gt; - Escrever Artigos&lt;/li&gt;
&lt;li&gt;&lt;code&gt;thesisdown&lt;/code&gt; - Escrever Teses&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bookdown&lt;/code&gt; - Escrever Livros (HTML, PDF, ePub, Kindle)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;o-que-será-necessário-para-usar-essas-ferramentas-2&#34;&gt;O que será necessário para usar essas ferramentas?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;No &lt;code&gt;R&lt;/code&gt; &lt;a href=&#34;https://youtu.be/YRSdoyfqp_g&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;instalar os pacotes&lt;/a&gt;:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;blogdown&lt;/code&gt; e &lt;code&gt;distill&lt;/code&gt; - Criação de blogs, websites&lt;/li&gt;
&lt;li&gt;&lt;code&gt;postcards&lt;/code&gt; - Criação de um cartão de visita&lt;/li&gt;
&lt;li&gt;&lt;code&gt;learnr&lt;/code&gt; - Criação de tutoriais para aprender R&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pkgdown&lt;/code&gt;(Documentação em HTML para pacotes R) e &lt;code&gt;usethis&lt;/code&gt; ou &lt;code&gt;rmarkdown&lt;/code&gt;(Criação de Vignettes)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;o-que-será-necessário-para-usar-essas-ferramentas-3&#34;&gt;O que será necessário para usar essas ferramentas?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;No &lt;code&gt;R&lt;/code&gt; &lt;a href=&#34;https://youtu.be/YRSdoyfqp_g&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;instalar os pacotes&lt;/a&gt;:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;tcltk&lt;/code&gt; (Existem muitos outros pacotes!) - GUI&amp;rsquo;s&lt;/li&gt;
&lt;li&gt;&lt;code&gt;manipulate&lt;/code&gt; e &lt;code&gt;shiny&lt;/code&gt; - gráficos interativos no RStudio e &lt;code&gt;scatterplot3d&lt;/code&gt; - Gráficos em 3d&lt;/li&gt;
&lt;li&gt;&lt;code&gt;exams&lt;/code&gt; - Criação de Provas para disciplinas + MOODLE&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;\(\LaTeX\)&lt;/code&gt;, MS Word (ou similares)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;r-markdown&#34;&gt;&lt;code&gt;R&lt;/code&gt; Markdown&lt;/h2&gt;
&lt;p&gt;Três componentes básicos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Metadados&lt;/strong&gt;: O corpo do documento&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Texto&lt;/strong&gt;: Assunto dissertado&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Código&lt;/strong&gt;: Linguagem de interesse&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;LEMBRETE&lt;/strong&gt;: A extensão de um arquivo R Markdown é: &lt;em&gt;.Rmd&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;material-de-apoio-ao-r-markdown&#34;&gt;Material de apoio ao &lt;code&gt;R&lt;/code&gt; Markdown&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/cdec/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/ramb-academico/cdec_hu891cdc650656200eb98f514c61f934c4_17480_48bcaa36767fa23207c27b820274c199.webp 400w,
               /slides/ramb-academico/cdec_hu891cdc650656200eb98f514c61f934c4_17480_d7c00888fc771d6909d650596147e429.webp 760w,
               /slides/ramb-academico/cdec_hu891cdc650656200eb98f514c61f934c4_17480_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/ramb-academico/cdec_hu891cdc650656200eb98f514c61f934c4_17480_48bcaa36767fa23207c27b820274c199.webp&#34;
               width=&#34;226&#34;
               height=&#34;364&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;material-de-apoio-ao-r-markdown-1&#34;&gt;Material de apoio ao &lt;code&gt;R&lt;/code&gt; Markdown&lt;/h2&gt;
&lt;p&gt;O básico no R Markdown:
&lt;a href=&#34;https://rmarkdown.rstudio.com/authoring_basics.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://rmarkdown.rstudio.com/authoring_basics.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A ideia dos pacotes nos documentos dinâmicos:
&lt;a href=&#34;https://jreduardo.github.io/semanest-ufpr2017/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://jreduardo.github.io/semanest-ufpr2017/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Para leitura:
&lt;a href=&#34;http://cursos.leg.ufpr.br/prr/capDocDin.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;http://cursos.leg.ufpr.br/prr/capDocDin.html&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;/media/boards.jpg&#34;
  &gt;

&lt;h2 id=&#34;r-markdown-documentos-estatísticos&#34;&gt;&lt;code&gt;R&lt;/code&gt; Markdown: Documentos estatísticos&lt;/h2&gt;
&lt;p&gt;Aplicações:&lt;/p&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/ramb-academico/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_0cd5d2661e8fc6dbb49dd886a81160b2.webp 400w,
               /slides/ramb-academico/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_5bd7ddd151c2f4da3fa79a2fa5972624.webp 760w,
               /slides/ramb-academico/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/ramb-academico/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_0cd5d2661e8fc6dbb49dd886a81160b2.webp&#34;
               width=&#34;170&#34;
               height=&#34;170&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;r-markdown-documentos-dinâmicos&#34;&gt;&lt;code&gt;R&lt;/code&gt; Markdown: Documentos dinâmicos&lt;/h2&gt;
&lt;p&gt;Recursos do Shiny:&lt;/p&gt;
&lt;p&gt;Exemplos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://shiny.estatistica.ccet.ufrn.br/srag/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Srag ou Covid-19 (UFRN)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://shiny.rstudio.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;em&gt;Trends&lt;/em&gt; do Google (RStudio)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://shiny.rstudio.com/gallery/didacting-modeling.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Processo de modelagem didática&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;criação-de-websites&#34;&gt;Criação de &lt;em&gt;Websites&lt;/em&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Website (pacote &lt;a href=&#34;https://rstudio.github.io/distill/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;distill&lt;/code&gt;&lt;/a&gt;): &lt;a href=&#34;https://youtu.be/FbTLrfYWQQw&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Rapidinhas do R&lt;/a&gt;, ex. &lt;a href=&#34;https://bendeivide.github.io/cursor/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Curso R&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Website via &lt;a href=&#34;https://pkgs.rstudio.com/blogdown/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;blogdown&lt;/code&gt;&lt;/a&gt; e &lt;a href=&#34;https://wowchemy.com/docs/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;Hugo&lt;/code&gt;&lt;/a&gt; (&lt;a href=&#34;https://wowchemy.com/templates/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;temas&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/ramb-academico/ben_hu96f6bd792b3af7602ac6cf7cef98b13a_17598_7e5abe44a987059ffc245fad5b802500.webp 400w,
               /slides/ramb-academico/ben_hu96f6bd792b3af7602ac6cf7cef98b13a_17598_7191e69c4c5b62592abfeed760168432.webp 760w,
               /slides/ramb-academico/ben_hu96f6bd792b3af7602ac6cf7cef98b13a_17598_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/ramb-academico/ben_hu96f6bd792b3af7602ac6cf7cef98b13a_17598_7e5abe44a987059ffc245fad5b802500.webp&#34;
               width=&#34;216&#34;
               height=&#34;217&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;exemplos-de-websites&#34;&gt;Exemplos de &lt;em&gt;Websites&lt;/em&gt;&lt;/h2&gt;
&lt;p&gt;Exemplos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://rmarkdown.rstudio.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;R Markdown no RStudio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Website pessoal de &lt;a href=&#34;https://robjhyndman.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Rob J Hyndman&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Website pessoal de &lt;a href=&#34;https://amber.rbind.io&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Amber Thomas&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Website pessoal de &lt;a href=&#34;https://emitanaka.github.io&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Emi Tanaka&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;exemplo-de-postcard&#34;&gt;Exemplo de &lt;em&gt;Postcard&lt;/em&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Exemplo: &lt;a href=&#34;https://bendeivide.github.io/cursor/about.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Ben Dêivide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;exemplo-de-dashboard&#34;&gt;Exemplo de Dashboard&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.shinyapps.io/RDashboards/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/ramb-academico/midrangeMCP_huf45dc9e9da53fa562b8e5b4d36571394_51649_39352c290d8c5e5a1804a131d2592ce5.webp 400w,
               /slides/ramb-academico/midrangeMCP_huf45dc9e9da53fa562b8e5b4d36571394_51649_40d47179797e8775f2210bae5d3f9b20.webp 760w,
               /slides/ramb-academico/midrangeMCP_huf45dc9e9da53fa562b8e5b4d36571394_51649_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/ramb-academico/midrangeMCP_huf45dc9e9da53fa562b8e5b4d36571394_51649_39352c290d8c5e5a1804a131d2592ce5.webp&#34;
               width=&#34;461&#34;
               height=&#34;534&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;outros-exemplos-de-dashboards&#34;&gt;Outros exemplos de Dashboards&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://eelloo.nl/groepsrapportages-met-infographics/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;eelloo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://jjallaire.shinyapps.io/shiny-crandash/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Exemplo usando o &lt;code&gt;shiny&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://shiny.estatistica.ccet.ufrn.br/DashboardDeputados/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Controle de gastos públicos&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://pkgs.rstudio.com/flexdashboard/articles/examples.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Material para usar Dashboards + Shiny&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;r-markdown-relatórios-programados&#34;&gt;R Markdown: Relatórios programados&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Exemplo: &lt;a href=&#34;https://rmarkdown.rstudio.com/articles_mail_merge.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Mine Çetinkaya-Rundel&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;/media/boards.jpg&#34;
  &gt;

&lt;h2 id=&#34;r-markdown-relatórios-programados-aplicação&#34;&gt;R Markdown: Relatórios programados (Aplicação)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Nomes dos professores do DEFIM/UFSJ e númerode suas salas;&lt;/li&gt;
&lt;li&gt;Vamos fazer um documento em PDF, cujo nome desses arquivos serão os nomes dos professores, com algum texto identificando as suas salas.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/ramb-academico/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_0cd5d2661e8fc6dbb49dd886a81160b2.webp 400w,
               /slides/ramb-academico/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_5bd7ddd151c2f4da3fa79a2fa5972624.webp 760w,
               /slides/ramb-academico/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/ramb-academico/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_0cd5d2661e8fc6dbb49dd886a81160b2.webp&#34;
               width=&#34;170&#34;
               height=&#34;170&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;r-markdown-livros&#34;&gt;R Markdown: Livros&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Site: &lt;a href=&#34;https://bookdown.org/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://bookdown.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Exemplo: &lt;a href=&#34;https://bendeivide.github.io/book-epaec/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;EPAEC&lt;/a&gt;, &lt;a href=&#34;https://bendeivide.github.io/book-eambr/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;EAMBR&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;r-markdown-artigos-e-teses&#34;&gt;R Markdown: Artigos e Teses&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Pacote &lt;code&gt;bookdown&lt;/code&gt; (Tese)&lt;/li&gt;
&lt;li&gt;Pacote &lt;code&gt;rticles&lt;/code&gt; (Artigo): &lt;code&gt;install.packages(&amp;quot;rticles&amp;quot;)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Pacote &lt;code&gt;thesisdown&lt;/code&gt; (Tese):&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;if (!require(&amp;quot;remotes&amp;quot;)) 
  install.packages(&amp;quot;remotes&amp;quot;, repos = &amp;quot;https://cran.rstudio.org&amp;quot;)
remotes::install_github(&amp;quot;rstudio/bookdown&amp;quot;)
remotes::install_github(&amp;quot;ismayc/thesisdown&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;/media/boards.jpg&#34;
  &gt;

&lt;h2 id=&#34;r-markdown-livros-aplicações&#34;&gt;R Markdown: Livros (Aplicações)&lt;/h2&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/ramb-academico/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_0cd5d2661e8fc6dbb49dd886a81160b2.webp 400w,
               /slides/ramb-academico/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_5bd7ddd151c2f4da3fa79a2fa5972624.webp 760w,
               /slides/ramb-academico/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/ramb-academico/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_0cd5d2661e8fc6dbb49dd886a81160b2.webp&#34;
               width=&#34;170&#34;
               height=&#34;170&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;/media/boards.jpg&#34;
  &gt;

&lt;h2 id=&#34;r-markdown-slides-aplicações&#34;&gt;R Markdown: Slides (Aplicações)&lt;/h2&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/ramb-academico/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_0cd5d2661e8fc6dbb49dd886a81160b2.webp 400w,
               /slides/ramb-academico/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_5bd7ddd151c2f4da3fa79a2fa5972624.webp 760w,
               /slides/ramb-academico/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/ramb-academico/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_0cd5d2661e8fc6dbb49dd886a81160b2.webp&#34;
               width=&#34;170&#34;
               height=&#34;170&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;documentação-para-pacotes&#34;&gt;Documentação para pacotes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Pacote &lt;a href=&#34;https://pkgdown.r-lib.org/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;pkgdown&lt;/code&gt;&lt;/a&gt;: ex.: &lt;a href=&#34;https://bendeivide.github.io/midrangeMCP/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;midrangeMCP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Vignettes (Pacote &lt;a href=&#34;https://usethis.r-lib.org/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;usethis&lt;/code&gt;&lt;/a&gt;): &lt;code&gt;usethis::use_vignette()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;interface-gráfica-ao-usuário&#34;&gt;Interface Gráfica ao Usuário&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Exemplo do pacote &lt;code&gt;tcltk&lt;/code&gt;: &lt;a href=&#34;https://bendeivide.github.io/project/mcptests/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;MCPtests&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34;
           src=&#34;http://bendeivide.github.io/slides/ramb-academico/MCPtests.gif&#34;
           loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Exemplo do pacote &lt;code&gt;shiny&lt;/code&gt;: &lt;a href=&#34;https://dreamrs.github.io/esquisse/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;esquisse&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;documentos-para-aprendizagem-do-r&#34;&gt;Documentos para aprendizagem do &lt;code&gt;R&lt;/code&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Pacote &lt;a href=&#34;https://rstudio.github.io/learnr/index.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;learnr&lt;/code&gt;&lt;/a&gt;: ex.: &lt;a href=&#34;http://bendeivide.shinyapps.io/Est_Exp/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Estatística Experimental&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;aplicação-de-provas-academia&#34;&gt;Aplicação de provas (Academia)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Pacote &lt;a href=&#34;http://r-exams.org/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;exams&lt;/code&gt;&lt;/a&gt; e uso no &lt;a href=&#34;https://moodle.org/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;MOODLE&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/ramb-academico/rexams&amp;#43;moodle_hu90e239b8805e1b03b777d53fd8bd0aea_63184_45a5acf0538bc5ef2ea0500c6d063fe2.webp 400w,
               /slides/ramb-academico/rexams&amp;#43;moodle_hu90e239b8805e1b03b777d53fd8bd0aea_63184_f19d123669d0c8ec3229ab58813739b8.webp 760w,
               /slides/ramb-academico/rexams&amp;#43;moodle_hu90e239b8805e1b03b777d53fd8bd0aea_63184_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/ramb-academico/rexams&amp;#43;moodle_hu90e239b8805e1b03b777d53fd8bd0aea_63184_45a5acf0538bc5ef2ea0500c6d063fe2.webp&#34;
               width=&#34;295&#34;
               height=&#34;155&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;/media/boards.jpg&#34;
  &gt;

&lt;h2 id=&#34;gráficos-3d-latex-e-r&#34;&gt;Gráficos 3D ($\LaTeX$ e &lt;code&gt;R&lt;/code&gt;)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Pacote &lt;code&gt;scatterplot3d&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;/media/boards.jpg&#34;
  &gt;

&lt;h2 id=&#34;tabelas-com-ilustrações-animadas--sweave&#34;&gt;Tabelas com ilustrações animadas + &lt;code&gt;Sweave&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/ramb-academico/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_0cd5d2661e8fc6dbb49dd886a81160b2.webp 400w,
               /slides/ramb-academico/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_5bd7ddd151c2f4da3fa79a2fa5972624.webp 760w,
               /slides/ramb-academico/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/ramb-academico/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_0cd5d2661e8fc6dbb49dd886a81160b2.webp&#34;
               width=&#34;170&#34;
               height=&#34;170&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;onde-publicamos-esses-materiais&#34;&gt;Onde publicamos esses materiais?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://rpubs.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;RPubs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://rpubs.com/cathydatascience/518692&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Como publicar!&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.shinyapps.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;shinyapp.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://bookdown.org/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Bookdown&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://marcusnunes.me/posts/como-instalar-o-shiny-em-seu-proprio-servidor/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Servidor próprio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gomesfellipe.github.io/post/2018-10-27-server-cloud/server-cloud/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Servidor online&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://https://github.com&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;GitHub&lt;/a&gt;, &lt;a href=&#34;https://bendeivide.github.io/project/rapidinhasr/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Rapidinhas do R 5 a 11&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.netlify.com&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Netlify&lt;/a&gt;, &lt;a href=&#34;https://bookdown.org/yihui/rmarkdown/blogdown-deploy.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Como publicar!&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h1 id=&#34;questões&#34;&gt;Questões?&lt;/h1&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Dúvidas e Sugestões&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/#contact&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Contato&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Slides</title>
      <link>http://bendeivide.github.io/slides/example/</link>
      <pubDate>Tue, 05 Feb 2019 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/example/</guid>
      <description>&lt;h1 id=&#34;create-slides-in-markdown-with-wowchemy&#34;&gt;Create slides in Markdown with Wowchemy&lt;/h1&gt;
&lt;p&gt;&lt;a href=&#34;https://wowchemy.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Wowchemy&lt;/a&gt; | &lt;a href=&#34;https://owchemy.com/docs/managing-content/#create-slides&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Documentation&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;features&#34;&gt;Features&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Efficiently write slides in Markdown&lt;/li&gt;
&lt;li&gt;3-in-1: Create, Present, and Publish your slides&lt;/li&gt;
&lt;li&gt;Supports speaker notes&lt;/li&gt;
&lt;li&gt;Mobile friendly slides&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;controls&#34;&gt;Controls&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Next: &lt;code&gt;Right Arrow&lt;/code&gt; or &lt;code&gt;Space&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Previous: &lt;code&gt;Left Arrow&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Start: &lt;code&gt;Home&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Finish: &lt;code&gt;End&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Overview: &lt;code&gt;Esc&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Speaker notes: &lt;code&gt;S&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Fullscreen: &lt;code&gt;F&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Zoom: &lt;code&gt;Alt + Click&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/hakimel/reveal.js#pdf-export&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;PDF Export&lt;/a&gt;: &lt;code&gt;E&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;code-highlighting&#34;&gt;Code Highlighting&lt;/h2&gt;
&lt;p&gt;Inline code: &lt;code&gt;variable&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Code block:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;porridge = &amp;quot;blueberry&amp;quot;
if porridge == &amp;quot;blueberry&amp;quot;:
    print(&amp;quot;Eating...&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2 id=&#34;math&#34;&gt;Math&lt;/h2&gt;
&lt;p&gt;In-line math: &lt;code&gt;\(x + y = z\)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Block math:&lt;/p&gt;
$$
f\left( x \right) = \;\frac{{2\left( {x + 4} \right)\left( {x - 4} \right)}}{{\left( {x + 4} \right)\left( {x + 1} \right)}}
$$
&lt;hr&gt;
&lt;h2 id=&#34;fragments&#34;&gt;Fragments&lt;/h2&gt;
&lt;p&gt;Make content appear incrementally&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{{% fragment %}} One {{% /fragment %}}
{{% fragment %}} **Two** {{% /fragment %}}
{{% fragment %}} Three {{% /fragment %}}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Press &lt;code&gt;Space&lt;/code&gt; to play!&lt;/p&gt;
&lt;span class=&#34;fragment &#34; &gt;
   One 
&lt;/span&gt;
&lt;span class=&#34;fragment &#34; &gt;
   **Two** 
&lt;/span&gt;
&lt;span class=&#34;fragment &#34; &gt;
   Three 
&lt;/span&gt;
&lt;hr&gt;
&lt;p&gt;A fragment can accept two optional parameters:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;class&lt;/code&gt;: use a custom style (requires definition in custom CSS)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;weight&lt;/code&gt;: sets the order in which a fragment appears&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;speaker-notes&#34;&gt;Speaker Notes&lt;/h2&gt;
&lt;p&gt;Add speaker notes to your presentation&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-markdown&#34;&gt;{{% speaker_note %}}
- Only the speaker can read these notes
- Press `S` key to view
{{% /speaker_note %}}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Press the &lt;code&gt;S&lt;/code&gt; key to view the speaker notes!&lt;/p&gt;
&lt;aside class=&#34;notes&#34;&gt;
  &lt;ul&gt;
&lt;li&gt;Only the speaker can read these notes&lt;/li&gt;
&lt;li&gt;Press &lt;code&gt;S&lt;/code&gt; key to view&lt;/li&gt;
&lt;/ul&gt;

&lt;/aside&gt;
&lt;hr&gt;
&lt;h2 id=&#34;themes&#34;&gt;Themes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;black: Black background, white text, blue links (default)&lt;/li&gt;
&lt;li&gt;white: White background, black text, blue links&lt;/li&gt;
&lt;li&gt;league: Gray background, white text, blue links&lt;/li&gt;
&lt;li&gt;beige: Beige background, dark text, brown links&lt;/li&gt;
&lt;li&gt;sky: Blue background, thin dark text, blue links&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;night: Black background, thick white text, orange links&lt;/li&gt;
&lt;li&gt;serif: Cappuccino background, gray text, brown links&lt;/li&gt;
&lt;li&gt;simple: White background, black text, blue links&lt;/li&gt;
&lt;li&gt;solarized: Cream-colored background, dark green text, blue links&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;/media/boards.jpg&#34;
  &gt;

&lt;h2 id=&#34;custom-slide&#34;&gt;Custom Slide&lt;/h2&gt;
&lt;p&gt;Customize the slide style and background&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-markdown&#34;&gt;{{&amp;lt; slide background-image=&amp;quot;/media/boards.jpg&amp;quot; &amp;gt;}}
{{&amp;lt; slide background-color=&amp;quot;#0000FF&amp;quot; &amp;gt;}}
{{&amp;lt; slide class=&amp;quot;my-style&amp;quot; &amp;gt;}}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2 id=&#34;custom-css-example&#34;&gt;Custom CSS Example&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s make headers navy colored.&lt;/p&gt;
&lt;p&gt;Create &lt;code&gt;assets/css/reveal_custom.css&lt;/code&gt; with:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-css&#34;&gt;.reveal section h1 {
  color: navy;
},
.reveal section h2,
.reveal section h3 {
  color: navy;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h1 id=&#34;questions&#34;&gt;Questions?&lt;/h1&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/wowchemy/wowchemy-hugo-modules/discussions&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Ask&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://wowchemy.com/docs/managing-content/#create-slides&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Documentation&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/cd-lingr/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/cd-lingr/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/cd-lingr/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/cd-lingr/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estexp/s07/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estexp/s07/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estexp/s07/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estexp/s07/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estexp/s08/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estexp/s08/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estexp/s08/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estexp/s08/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estexp/s10/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estexp/s10/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estexp/s10/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estexp/s10/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estexp/s12/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estexp/s12/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estexp/s12/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estexp/s12/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estexp/s14/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estexp/s14/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estexp/s14/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estexp/s14/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estexp/s16/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estexp/s16/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estexp/s16/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estexp/s16/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estexp/s18/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estexp/s18/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estexp/s18/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estexp/s18/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estexp/s19/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estexp/s19/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estexp/s19/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estexp/s19/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estexp/s20/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estexp/s20/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estexp/s20/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estexp/s20/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estexp/s22/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estexp/s22/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estexp/s22/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estexp/s22/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estexp/s31/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estexp/s31/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estexp/s31/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estexp/s31/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estgeo/slide02/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estgeo/slide02/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estgeo/slide02/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estgeo/slide02/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estgeo/slide03/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estgeo/slide03/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estgeo/slide03/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estgeo/slide03/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estgeo/slide04/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estgeo/slide04/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estgeo/slide04/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estgeo/slide04/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estgeo/slide05/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estgeo/slide05/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estgeo/slide05/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estgeo/slide05/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estgeo/slide06/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estgeo/slide06/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estgeo/slide06/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estgeo/slide06/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estgeo/slide07/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estgeo/slide07/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estgeo/slide07/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estgeo/slide07/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estprob/s01/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estprob/s01/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estprob/s01/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estprob/s01/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estprob/s02/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estprob/s02/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estprob/s02/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estprob/s02/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estprob/s03/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estprob/s03/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estprob/s03/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estprob/s03/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estprob/s04/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estprob/s04/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estprob/s04/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estprob/s04/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estprob/s05/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estprob/s05/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estprob/s05/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estprob/s05/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estprob/s06/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estprob/s06/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estprob/s06/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estprob/s06/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estprob/s07/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estprob/s07/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estprob/s07/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estprob/s07/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estprob/s08/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estprob/s08/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estprob/s08/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estprob/s08/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estprob/s09/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estprob/s09/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estprob/s09/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estprob/s09/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estprob/s11.2/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estprob/s11.2/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estprob/s11.2/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estprob/s11.2/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estprob/s11/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estprob/s11/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estprob/s11/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estprob/s11/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estprob/s12/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estprob/s12/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estprob/s12/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estprob/s12/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estprob/s13/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estprob/s13/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estprob/s13/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estprob/s13/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estprob/s14/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estprob/s14/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estprob/s14/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estprob/s14/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estprob/s15/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estprob/s15/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estprob/s15/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estprob/s15/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estprob/s16/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estprob/s16/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estprob/s16/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estprob/s16/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estprob/s17/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estprob/s17/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/estprob/s17/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estprob/s17/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/expagr/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/expagr/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/expagr/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/expagr/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/leem/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/leem/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/leem/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/leem/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/lrcd/s04/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/lrcd/s04/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/lrcd/s04/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/lrcd/s04/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/lrcd/s06/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/lrcd/s06/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/lrcd/s06/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/lrcd/s06/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/lrcd/s07/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/lrcd/s07/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/lrcd/s07/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/lrcd/s07/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/lrcd/s08/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/lrcd/s08/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/lrcd/s08/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/lrcd/s08/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/lancamento/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/lancamento/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/lancamento/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/lancamento/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/live01/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/live01/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/live01/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/live01/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/live02/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/live02/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/live02/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/live02/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/live03/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/live03/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/live03/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/live03/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide00/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide00/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide00/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide00/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide01/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide01/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide01/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide01/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide02/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide02/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide02/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide02/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide03/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide03/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide03/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide03/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide04/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide04/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide04/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide04/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide05/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide05/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide05/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide05/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide06/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide06/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide06/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide06/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide07/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide07/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide07/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide07/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide08/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide08/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide08/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide08/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide09/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide09/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide09/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide09/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide10/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide10/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide10/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide10/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide11/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide11/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide11/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide11/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide12/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide12/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide12/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide12/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide13/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide13/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide13/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide13/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide14/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide14/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide14/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide14/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide15/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide15/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide15/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide15/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide16/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide16/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide16/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide16/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide17/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide17/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide17/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide17/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide18/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide18/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide18/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide18/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide19/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide19/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide19/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide19/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide20/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide20/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide20/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide20/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide21/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide21/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide21/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide21/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide22/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide22/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide22/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide22/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide23/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide23/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide23/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide23/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide24/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide24/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide24/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide24/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide25/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide25/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico/slide25/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico/slide25/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/lancamento/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/lancamento/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/lancamento/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/lancamento/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide00/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide00/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide00/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide00/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide01/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide01/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide01/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide01/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide02/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide02/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide02/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide02/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide03/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide03/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide03/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide03/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide04/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide04/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide04/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide04/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide05/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide05/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide05/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide05/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide06/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide06/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide06/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide06/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide07/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide07/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide07/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide07/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide08/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide08/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide08/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide08/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide09/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide09/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide09/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide09/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide10/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide10/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide10/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide10/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide11/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide11/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide11/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide11/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide12/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide12/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide12/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide12/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide13/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide13/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide13/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide13/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide14/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide14/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide14/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide14/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide15/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide15/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide15/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide15/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide16/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide16/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide16/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide16/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide17/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide17/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide17/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide17/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide18/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide18/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide18/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide18/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide19/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide19/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide19/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide19/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide20/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide20/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide20/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide20/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide21/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide21/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide21/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide21/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide22/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide22/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide22/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide22/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide23/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide23/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide23/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide23/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide24/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide24/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide24/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide24/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide25/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide25/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/rbasico2024/slide25/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/rbasico2024/slide25/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/semanact/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/semanact/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/semanact/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/semanact/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/sematxii/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/sematxii/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/sematxii/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/sematxii/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/sicxxii/index_files/libs/revealjs/plugin/notes/speaker-view/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/sicxxii/index_files/libs/revealjs/plugin/notes/speaker-view/</guid>
      <description>
&lt;html lang=&#34;en&#34;&gt;
	&lt;head&gt;
		&lt;meta charset=&#34;utf-8&#34;&gt;

		&lt;title&gt;reveal.js - Speaker View&lt;/title&gt;

		&lt;style&gt;
			body {
				font-family: Helvetica;
				font-size: 18px;
			}

			#current-slide,
			#upcoming-slide,
			#speaker-controls {
				padding: 6px;
				box-sizing: border-box;
				-moz-box-sizing: border-box;
			}

			#current-slide iframe,
			#upcoming-slide iframe {
				width: 100%;
				height: 100%;
				border: 1px solid #ddd;
			}

			#current-slide .label,
			#upcoming-slide .label {
				position: absolute;
				top: 10px;
				left: 10px;
				z-index: 2;
			}

			#connection-status {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				z-index: 20;
				padding: 30% 20% 20% 20%;
				font-size: 18px;
				color: #222;
				background: #fff;
				text-align: center;
				box-sizing: border-box;
				line-height: 1.4;
			}

			.overlay-element {
				height: 34px;
				line-height: 34px;
				padding: 0 10px;
				text-shadow: none;
				background: rgba( 220, 220, 220, 0.8 );
				color: #222;
				font-size: 14px;
			}

			.overlay-element.interactive:hover {
				background: rgba( 220, 220, 220, 1 );
			}

			#current-slide {
				position: absolute;
				width: 60%;
				height: 100%;
				top: 0;
				left: 0;
				padding-right: 0;
			}

			#upcoming-slide {
				position: absolute;
				width: 40%;
				height: 40%;
				right: 0;
				top: 0;
			}

			/* Speaker controls */
			#speaker-controls {
				position: absolute;
				top: 40%;
				right: 0;
				width: 40%;
				height: 60%;
				overflow: auto;
				font-size: 18px;
			}

				.speaker-controls-time.hidden,
				.speaker-controls-notes.hidden {
					display: none;
				}

				.speaker-controls-time .label,
				.speaker-controls-pace .label,
				.speaker-controls-notes .label {
					text-transform: uppercase;
					font-weight: normal;
					font-size: 0.66em;
					color: #666;
					margin: 0;
				}

				.speaker-controls-time, .speaker-controls-pace {
					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%;
				}

				.speaker-controls-time .timer,
				.speaker-controls-time .clock,
				.speaker-controls-time .pacing .hours-value,
				.speaker-controls-time .pacing .minutes-value,
				.speaker-controls-time .pacing .seconds-value {
					font-size: 1.9em;
				}

				.speaker-controls-time .timer {
					float: left;
				}

				.speaker-controls-time .clock {
					float: right;
					text-align: right;
				}

				.speaker-controls-time span.mute {
					opacity: 0.3;
				}

				.speaker-controls-time .pacing-title {
					margin-top: 5px;
				}

				.speaker-controls-time .pacing.ahead {
					color: blue;
				}

				.speaker-controls-time .pacing.on-track {
					color: green;
				}

				.speaker-controls-time .pacing.behind {
					color: red;
				}

				.speaker-controls-notes {
					padding: 10px 16px;
				}

				.speaker-controls-notes .value {
					margin-top: 5px;
					line-height: 1.4;
					font-size: 1.2em;
				}

			/* Layout selector */
			#speaker-layout {
				position: absolute;
				top: 10px;
				right: 10px;
				color: #222;
				z-index: 10;
			}
				#speaker-layout select {
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					border: 0;
					box-shadow: 0;
					cursor: pointer;
					opacity: 0;

					font-size: 1em;
					background-color: transparent;

					-moz-appearance: none;
					-webkit-appearance: none;
					-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
				}

				#speaker-layout select:focus {
					outline: none;
					box-shadow: none;
				}

			.clear {
				clear: both;
			}

			/* Speaker layout: Wide */
			body[data-speaker-layout=&#34;wide&#34;] #current-slide,
			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				width: 50%;
				height: 45%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;wide&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;wide&#34;] #upcoming-slide {
				top: 0;
				left: 50%;
			}

			body[data-speaker-layout=&#34;wide&#34;] #speaker-controls {
				top: 45%;
				left: 0;
				width: 100%;
				height: 50%;
				font-size: 1.25em;
			}

			/* Speaker layout: Tall */
			body[data-speaker-layout=&#34;tall&#34;] #current-slide,
			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				width: 45%;
				height: 50%;
				padding: 6px;
			}

			body[data-speaker-layout=&#34;tall&#34;] #current-slide {
				top: 0;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #upcoming-slide {
				top: 50%;
				left: 0;
			}

			body[data-speaker-layout=&#34;tall&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 45%;
				width: 55%;
				height: 100%;
				font-size: 1.25em;
			}

			/* Speaker layout: Notes only */
			body[data-speaker-layout=&#34;notes-only&#34;] #current-slide,
			body[data-speaker-layout=&#34;notes-only&#34;] #upcoming-slide {
				display: none;
			}

			body[data-speaker-layout=&#34;notes-only&#34;] #speaker-controls {
				padding-top: 40px;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				font-size: 1.25em;
			}

			@media screen and (max-width: 1080px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 16px;
				}
			}

			@media screen and (max-width: 900px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 14px;
				}
			}

			@media screen and (max-width: 800px) {
				body[data-speaker-layout=&#34;default&#34;] #speaker-controls {
					font-size: 12px;
				}
			}

		&lt;/style&gt;
	&lt;/head&gt;

	&lt;body&gt;

		&lt;div id=&#34;connection-status&#34;&gt;Loading speaker view...&lt;/div&gt;

		&lt;div id=&#34;current-slide&#34;&gt;&lt;/div&gt;
		&lt;div id=&#34;upcoming-slide&#34;&gt;&lt;span class=&#34;overlay-element label&#34;&gt;Upcoming&lt;/span&gt;&lt;/div&gt;
		&lt;div id=&#34;speaker-controls&#34;&gt;
			&lt;div class=&#34;speaker-controls-time&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Time &lt;span class=&#34;reset-button&#34;&gt;Click to Reset&lt;/span&gt;&lt;/h4&gt;
				&lt;div class=&#34;clock&#34;&gt;
					&lt;span class=&#34;clock-value&#34;&gt;0:00 AM&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;timer&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
				&lt;div class=&#34;clear&#34;&gt;&lt;/div&gt;

				&lt;h4 class=&#34;label pacing-title&#34; style=&#34;display: none&#34;&gt;Pacing – Time to finish current slide&lt;/h4&gt;
				&lt;div class=&#34;pacing&#34; style=&#34;display: none&#34;&gt;
					&lt;span class=&#34;hours-value&#34;&gt;00&lt;/span&gt;&lt;span class=&#34;minutes-value&#34;&gt;:00&lt;/span&gt;&lt;span class=&#34;seconds-value&#34;&gt;:00&lt;/span&gt;
				&lt;/div&gt;
			&lt;/div&gt;

			&lt;div class=&#34;speaker-controls-notes hidden&#34;&gt;
				&lt;h4 class=&#34;label&#34;&gt;Notes&lt;/h4&gt;
				&lt;div class=&#34;value&#34;&gt;&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
		&lt;div id=&#34;speaker-layout&#34; class=&#34;overlay-element interactive&#34;&gt;
			&lt;span class=&#34;speaker-layout-label&#34;&gt;&lt;/span&gt;
			&lt;select class=&#34;speaker-layout-dropdown&#34;&gt;&lt;/select&gt;
		&lt;/div&gt;

		&lt;script&gt;

			(function() {

				var notes,
					notesValue,
					currentState,
					currentSlide,
					upcomingSlide,
					layoutLabel,
					layoutDropdown,
					pendingCalls = {},
					lastRevealApiCallId = 0,
					connected = false,
					whitelistedWindows = [window.opener];

				var SPEAKER_LAYOUTS = {
					&#39;default&#39;: &#39;Default&#39;,
					&#39;wide&#39;: &#39;Wide&#39;,
					&#39;tall&#39;: &#39;Tall&#39;,
					&#39;notes-only&#39;: &#39;Notes only&#39;
				};

				setupLayout();

				var connectionStatus = document.querySelector( &#39;#connection-status&#39; );
				var connectionTimeout = setTimeout( function() {
					connectionStatus.innerHTML = &#39;Error connecting to main window.&lt;br&gt;Please try closing and reopening the speaker view.&#39;;
				}, 5000 );
;
				window.addEventListener( &#39;message&#39;, function( event ) {

					// Validate the origin of this message to prevent XSS
					if( window.location.origin !== event.origin &amp;&amp; whitelistedWindows.indexOf( event.source ) === -1 ) {
						return;
					}

					clearTimeout( connectionTimeout );
					connectionStatus.style.display = &#39;none&#39;;

					var data = JSON.parse( event.data );

					// The overview mode is only useful to the reveal.js instance
					// where navigation occurs so we don&#39;t sync it
					if( data.state ) delete data.state.overview;

					// Messages sent by the notes plugin inside of the main window
					if( data &amp;&amp; data.namespace === &#39;reveal-notes&#39; ) {
						if( data.type === &#39;connect&#39; ) {
							handleConnectMessage( data );
						}
						else if( data.type === &#39;state&#39; ) {
							handleStateMessage( data );
						}
						else if( data.type === &#39;return&#39; ) {
							pendingCalls[data.callId](data.result);
							delete pendingCalls[data.callId];
						}
					}
					// Messages sent by the reveal.js inside of the current slide preview
					else if( data &amp;&amp; data.namespace === &#39;reveal&#39; ) {
						if( /ready/.test( data.eventName ) ) {
							// Send a message back to notify that the handshake is complete
							window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;connected&#39;} ), &#39;*&#39; );
						}
						else if( /slidechanged|fragmentshown|fragmenthidden|paused|resumed/.test( data.eventName ) &amp;&amp; currentState !== JSON.stringify( data.state ) ) {

							dispatchStateToMainWindow( data.state );

						}
					}

				} );

				/**
				 * Updates the presentation in the main window to match the state
				 * of the presentation in the notes window.
				 */
				const dispatchStateToMainWindow = debounce(( state ) =&gt; {
					window.opener.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ state ]} ), &#39;*&#39; );
				}, 500);

				/**
				 * Asynchronously calls the Reveal.js API of the main frame.
				 */
				function callRevealApi( methodName, methodArguments, callback ) {

					var callId = ++lastRevealApiCallId;
					pendingCalls[callId] = callback;
					window.opener.postMessage( JSON.stringify( {
						namespace: &#39;reveal-notes&#39;,
						type: &#39;call&#39;,
						callId: callId,
						methodName: methodName,
						arguments: methodArguments
					} ), &#39;*&#39; );

				}

				/**
				 * Called when the main window is trying to establish a
				 * connection.
				 */
				function handleConnectMessage( data ) {

					if( connected === false ) {
						connected = true;

						setupIframes( data );
						setupKeyboard();
						setupNotes();
						setupTimer();
						setupHeartbeat();
					}

				}

				/**
				 * 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( &#39;hidden&#39; );
						notesValue.style.whiteSpace = data.whitespace;
						if( data.markdown ) {
							notesValue.innerHTML = marked( data.notes );
						}
						else {
							notesValue.innerHTML = data.notes;
						}
					}
					else {
						notes.classList.add( &#39;hidden&#39; );
					}

					// Update the note slides
					currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;setState&#39;, args: [ data.state ] }), &#39;*&#39; );
					upcomingSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;next&#39; }), &#39;*&#39; );

				}

				// 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&#39;t set on the current slide iframe.
				 *
				 * Block F5 default handling, it reloads and disconnects
				 * the speaker notes window.
				 */
				function setupKeyboard() {

					document.addEventListener( &#39;keydown&#39;, function( event ) {
						if( event.keyCode === 116 || ( event.metaKey &amp;&amp; event.keyCode === 82 ) ) {
							event.preventDefault();
							return false;
						}
						currentSlide.contentWindow.postMessage( JSON.stringify({ method: &#39;triggerKey&#39;, args: [ event.keyCode ] }), &#39;*&#39; );
					} );

				}

				/**
				 * Creates the preview iframes.
				 */
				function setupIframes( data ) {

					var params = [
						&#39;receiver&#39;,
						&#39;progress=false&#39;,
						&#39;history=false&#39;,
						&#39;transition=none&#39;,
						&#39;autoSlide=0&#39;,
						&#39;backgroundTransition=none&#39;
					].join( &#39;&amp;&#39; );

					var urlSeparator = /\?/.test(data.url) ? &#39;&amp;&#39; : &#39;?&#39;;
					var hash = &#39;#/&#39; + data.state.indexh + &#39;/&#39; + data.state.indexv;
					var currentURL = data.url + urlSeparator + params + &#39;&amp;postMessageEvents=true&#39; + hash;
					var upcomingURL = data.url + urlSeparator + params + &#39;&amp;controls=false&#39; + hash;

					currentSlide = document.createElement( &#39;iframe&#39; );
					currentSlide.setAttribute( &#39;width&#39;, 1280 );
					currentSlide.setAttribute( &#39;height&#39;, 1024 );
					currentSlide.setAttribute( &#39;src&#39;, currentURL );
					document.querySelector( &#39;#current-slide&#39; ).appendChild( currentSlide );

					upcomingSlide = document.createElement( &#39;iframe&#39; );
					upcomingSlide.setAttribute( &#39;width&#39;, 640 );
					upcomingSlide.setAttribute( &#39;height&#39;, 512 );
					upcomingSlide.setAttribute( &#39;src&#39;, upcomingURL );
					document.querySelector( &#39;#upcoming-slide&#39; ).appendChild( upcomingSlide );

					whitelistedWindows.push( currentSlide.contentWindow, upcomingSlide.contentWindow );

				}

				/**
				 * Setup the notes UI.
				 */
				function setupNotes() {

					notes = document.querySelector( &#39;.speaker-controls-notes&#39; );
					notesValue = document.querySelector( &#39;.speaker-controls-notes .value&#39; );

				}

				/**
				 * We send out a heartbeat at all times to ensure we can
				 * reconnect with the main presentation window after reloads.
				 */
				function setupHeartbeat() {

					setInterval( () =&gt; {
						window.opener.postMessage( JSON.stringify({ namespace: &#39;reveal-notes&#39;, type: &#39;heartbeat&#39;} ), &#39;*&#39; );
					}, 1000 );

				}

				function getTimings( callback ) {

					callRevealApi( &#39;getSlidesAttributes&#39;, [], function ( slideAttributes ) {
						callRevealApi( &#39;getConfig&#39;, [], function ( config ) {
							var totalTime = config.totalTime;
							var minTimePerSlide = config.minimumTimePerSlide || 0;
							var defaultTiming = config.defaultTiming;
							if ((defaultTiming == null) &amp;&amp; (totalTime == null)) {
								callback(null);
								return;
							}
							// Setting totalTime overrides defaultTiming
							if (totalTime) {
								defaultTiming = 0;
							}
							var timings = [];
							for ( var i in slideAttributes ) {
								var slide = slideAttributes[ i ];
								var timing = defaultTiming;
								if( slide.hasOwnProperty( &#39;data-timing&#39; )) {
									var t = slide[ &#39;data-timing&#39; ];
									timing = parseInt(t);
									if( isNaN(timing) ) {
										console.warn(&#34;Could not parse timing &#39;&#34; + t + &#34;&#39; of slide &#34; + i + &#34;; using default of &#34; + defaultTiming);
										timing = defaultTiming;
									}
								}
								timings.push(timing);
							}
							if ( totalTime ) {
								// After we&#39;ve allocated time to individual slides, we summarize it and
								// subtract it from the total time
								var remainingTime = totalTime - timings.reduce( function(a, b) { return a + b; }, 0 );
								// The remaining time is divided by the number of slides that have 0 seconds
								// allocated at the moment, giving the average time-per-slide on the remaining slides
								var remainingSlides = (timings.filter( function(x) { return x == 0 }) ).length
								var timePerSlide = Math.round( remainingTime / remainingSlides, 0 )
								// And now we replace every zero-value timing with that average
								timings = timings.map( function(x) { return (x==0 ? timePerSlide : x) } );
							}
							var slidesUnderMinimum = timings.filter( function(x) { return (x &lt; minTimePerSlide) } ).length
							if ( slidesUnderMinimum ) {
								message = &#34;The pacing time for &#34; + slidesUnderMinimum + &#34; slide(s) is under the configured minimum of &#34; + minTimePerSlide + &#34; seconds. Check the data-timing attribute on individual slides, or consider increasing the totalTime or minimumTimePerSlide configuration options (or removing some slides).&#34;;
								alert(message);
							}
							callback( timings );
						} );
					} );

				}

				/**
				 * Return the number of seconds allocated for presenting
				 * all slides up to and including this one.
				 */
				function getTimeAllocated( timings, callback ) {

					callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
						var allocated = 0;
						for (var i in timings.slice(0, currentSlide + 1)) {
							allocated += timings[i];
						}
						callback( allocated );
					} );

				}

				/**
				 * Create the timer and clock and start updating them
				 * at an interval.
				 */
				function setupTimer() {

					var start = new Date(),
					timeEl = document.querySelector( &#39;.speaker-controls-time&#39; ),
					clockEl = timeEl.querySelector( &#39;.clock-value&#39; ),
					hoursEl = timeEl.querySelector( &#39;.hours-value&#39; ),
					minutesEl = timeEl.querySelector( &#39;.minutes-value&#39; ),
					secondsEl = timeEl.querySelector( &#39;.seconds-value&#39; ),
					pacingTitleEl = timeEl.querySelector( &#39;.pacing-title&#39; ),
					pacingEl = timeEl.querySelector( &#39;.pacing&#39; ),
					pacingHoursEl = pacingEl.querySelector( &#39;.hours-value&#39; ),
					pacingMinutesEl = pacingEl.querySelector( &#39;.minutes-value&#39; ),
					pacingSecondsEl = pacingEl.querySelector( &#39;.seconds-value&#39; );

					var timings = null;
					getTimings( function ( _timings ) {

						timings = _timings;
						if (_timings !== null) {
							pacingTitleEl.style.removeProperty(&#39;display&#39;);
							pacingEl.style.removeProperty(&#39;display&#39;);
						}

						// Update once directly
						_updateTimer();

						// Then update every second
						setInterval( _updateTimer, 1000 );

					} );


					function _resetTimer() {

						if (timings == null) {
							start = new Date();
							_updateTimer();
						}
						else {
							// Reset timer to beginning of current slide
							getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
								var slideEndTiming = slideEndTimingSeconds * 1000;
								callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
									var currentSlideTiming = timings[currentSlide] * 1000;
									var previousSlidesTiming = slideEndTiming - currentSlideTiming;
									var now = new Date();
									start = new Date(now.getTime() - previousSlidesTiming);
									_updateTimer();
								} );
							} );
						}

					}

					timeEl.addEventListener( &#39;click&#39;, function() {
						_resetTimer();
						return false;
					} );

					function _displayTime( hrEl, minEl, secEl, time) {

						var sign = Math.sign(time) == -1 ? &#34;-&#34; : &#34;&#34;;
						time = Math.abs(Math.round(time / 1000));
						var seconds = time % 60;
						var minutes = Math.floor( time / 60 ) % 60 ;
						var hours = Math.floor( time / ( 60 * 60 )) ;
						hrEl.innerHTML = sign + zeroPadInteger( hours );
						if (hours == 0) {
							hrEl.classList.add( &#39;mute&#39; );
						}
						else {
							hrEl.classList.remove( &#39;mute&#39; );
						}
						minEl.innerHTML = &#39;:&#39; + zeroPadInteger( minutes );
						if (hours == 0 &amp;&amp; minutes == 0) {
							minEl.classList.add( &#39;mute&#39; );
						}
						else {
							minEl.classList.remove( &#39;mute&#39; );
						}
						secEl.innerHTML = &#39;:&#39; + zeroPadInteger( seconds );
					}

					function _updateTimer() {

						var diff, hours, minutes, seconds,
						now = new Date();

						diff = now.getTime() - start.getTime();

						clockEl.innerHTML = now.toLocaleTimeString( &#39;en-US&#39;, { hour12: true, hour: &#39;2-digit&#39;, minute:&#39;2-digit&#39; } );
						_displayTime( hoursEl, minutesEl, secondsEl, diff );
						if (timings !== null) {
							_updatePacing(diff);
						}

					}

					function _updatePacing(diff) {

						getTimeAllocated( timings, function ( slideEndTimingSeconds ) {
							var slideEndTiming = slideEndTimingSeconds * 1000;

							callRevealApi( &#39;getSlidePastCount&#39;, [], function ( currentSlide ) {
								var currentSlideTiming = timings[currentSlide] * 1000;
								var timeLeftCurrentSlide = slideEndTiming - diff;
								if (timeLeftCurrentSlide &lt; 0) {
									pacingEl.className = &#39;pacing behind&#39;;
								}
								else if (timeLeftCurrentSlide &lt; currentSlideTiming) {
									pacingEl.className = &#39;pacing on-track&#39;;
								}
								else {
									pacingEl.className = &#39;pacing ahead&#39;;
								}
								_displayTime( pacingHoursEl, pacingMinutesEl, pacingSecondsEl, timeLeftCurrentSlide );
							} );
						} );
					}

				}

				/**
				 * Sets up the speaker view layout and layout selector.
				 */
				function setupLayout() {

					layoutDropdown = document.querySelector( &#39;.speaker-layout-dropdown&#39; );
					layoutLabel = document.querySelector( &#39;.speaker-layout-label&#39; );

					// Render the list of available layouts
					for( var id in SPEAKER_LAYOUTS ) {
						var option = document.createElement( &#39;option&#39; );
						option.setAttribute( &#39;value&#39;, id );
						option.textContent = SPEAKER_LAYOUTS[ id ];
						layoutDropdown.appendChild( option );
					}

					// Monitor the dropdown for changes
					layoutDropdown.addEventListener( &#39;change&#39;, function( event ) {

						setLayout( layoutDropdown.value );

					}, false );

					// Restore any currently persisted layout
					setLayout( getLayout() );

				}

				/**
				 * Sets a new speaker view layout. The layout is persisted
				 * in local storage.
				 */
				function setLayout( value ) {

					var title = SPEAKER_LAYOUTS[ value ];

					layoutLabel.innerHTML = &#39;Layout&#39; + ( title ? ( &#39;: &#39; + title ) : &#39;&#39; );
					layoutDropdown.value = value;

					document.body.setAttribute( &#39;data-speaker-layout&#39;, value );

					// Persist locally
					if( supportsLocalStorage() ) {
						window.localStorage.setItem( &#39;reveal-speaker-layout&#39;, value );
					}

				}

				/**
				 * Returns the ID of the most recently set speaker layout
				 * or our default layout if none has been set.
				 */
				function getLayout() {

					if( supportsLocalStorage() ) {
						var layout = window.localStorage.getItem( &#39;reveal-speaker-layout&#39; );
						if( layout ) {
							return layout;
						}
					}

					// Default to the first record in the layouts hash
					for( var id in SPEAKER_LAYOUTS ) {
						return id;
					}

				}

				function supportsLocalStorage() {

					try {
						localStorage.setItem(&#39;test&#39;, &#39;test&#39;);
						localStorage.removeItem(&#39;test&#39;);
						return true;
					}
					catch( e ) {
						return false;
					}

				}

				function zeroPadInteger( num ) {

					var str = &#39;00&#39; + 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 &gt; ms ) {
							fn.apply( context, args );
							lastTime = Date.now();
						}
						else {
							timeout = setTimeout( function() {
								fn.apply( context, args );
								lastTime = Date.now();
							}, ms - timeSinceLastCall );
						}

					}

				}

			})();

		&lt;/script&gt;
	&lt;/body&gt;
&lt;/html&gt;</description>
    </item>
    
    <item>
      <title></title>
      <link>http://bendeivide.github.io/slides/sicxxii/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/sicxxii/index_files/libs/revealjs/plugin/reveal-chalkboard/readme/</guid>
      <description>&lt;h1 id=&#34;chalkboard&#34;&gt;Chalkboard&lt;/h1&gt;
&lt;p&gt;With this plugin you can add a chalkboard to reveal.js. The plugin provides two possibilities to include handwritten notes to your presentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you can make notes directly on the slides, e.g. to comment on certain aspects,&lt;/li&gt;
&lt;li&gt;you can open a chalkboard or whiteboard on which you can make notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main use case in mind when implementing the plugin is classroom usage in which you may want to explain some course content and quickly need to make some notes.&lt;/p&gt;
&lt;p&gt;The plugin records all drawings made so that they can be play backed using the &lt;code&gt;autoSlide&lt;/code&gt; feature or the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rajgoel.github.io/reveal.js-demos/chalkboard-demo.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Check out the live demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The chalkboard effect is based on &lt;a href=&#34;https://github.com/mmoustafa/Chalkboard&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chalkboard&lt;/a&gt; by Mohamed Moustafa.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;Copy the file &lt;code&gt;plugin.js&lt;/code&gt; and the  &lt;code&gt;img&lt;/code&gt; directory into the plugin folder of your reveal.js presentation, i.e. &lt;code&gt;plugin/chalkboard&lt;/code&gt; and load the plugin as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;script src=&amp;quot;plugin/chalkboard/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;plugin/customcontrols/plugin.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;script&amp;gt;
    Reveal.initialize({
        // ...
        plugins: [ RevealChalkboard, RevealCustomControls ],
        // ...
    });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following stylesheet&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/chalkboard/style.css&amp;quot;&amp;gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;plugin/customcontrols/style.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has to be included to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;p&gt;In order to include buttons for opening and closing the notes canvas or the chalkboard you should make sure that &lt;code&gt;font-awesome&lt;/code&gt; is available. The easiest way is to include&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to the &lt;code&gt;head&lt;/code&gt; section of you HTML-file.&lt;/p&gt;
&lt;h2 id=&#34;usage&#34;&gt;Usage&lt;/h2&gt;
&lt;h3 id=&#34;mouse-or-touch&#34;&gt;Mouse or touch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Click on the pen symbols at the bottom left to toggle the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click on the color picker at the left to change the color (the color picker is only visible if the notes canvas or chalkboard is active)&lt;/li&gt;
&lt;li&gt;Click on the up/down arrows on the left to the switch among multiple chalkboardd (the up/down arrows are only available for the chlakboard)&lt;/li&gt;
&lt;li&gt;Click the left mouse button and drag to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Click the right mouse button and drag to wipe away previous drawings&lt;/li&gt;
&lt;li&gt;Touch and move to write on notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Touch and hold for half a second, then move to wipe away previous drawings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;keyboard&#34;&gt;Keyboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Press the &amp;lsquo;BACKSPACE&amp;rsquo; key to delete all chalkboard drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;DEL&amp;rsquo; key to clear the notes canvas or chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;c&amp;rsquo; key to toggle the notes canvas&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;b&amp;rsquo; key to toggle the chalkboard&lt;/li&gt;
&lt;li&gt;Press the &amp;rsquo;d&amp;rsquo; key to download drawings&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;x&amp;rsquo; key to cycle colors forward&lt;/li&gt;
&lt;li&gt;Press the &amp;lsquo;y&amp;rsquo; key to cycle colors backward&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;playback&#34;&gt;Playback&lt;/h2&gt;
&lt;p&gt;If the &lt;code&gt;autoSlide&lt;/code&gt; feature is set or if the &lt;code&gt;audio-slideshow&lt;/code&gt; plugin is used, pre-recorded chalkboard drawings can be played. The slideshow plays back the user interaction with the chalkboard in the same way as it was conducted when recording the data.&lt;/p&gt;
&lt;h2 id=&#34;multiplexing&#34;&gt;Multiplexing&lt;/h2&gt;
&lt;p&gt;The plugin supports multiplexing via the &lt;a href=&#34;https://github.com/reveal/multiplex&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;multiplex&lt;/code&gt; plugin&lt;/a&gt; or the &lt;a href=&#34;https://github.com/rajgoel/reveal.js-plugins/tree/master/seminar&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;seminar&lt;/code&gt; plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pdf-export&#34;&gt;PDF-Export&lt;/h2&gt;
&lt;p&gt;If the slideshow is opened in &lt;a href=&#34;https://revealjs.com/pdf-export/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;print mode&lt;/a&gt;, the chalkboard drawings in the session storage (see &lt;code&gt;storage&lt;/code&gt; option - print version must be opened in the same tab or window as the original slideshow) or provided in a file (see &lt;code&gt;src&lt;/code&gt; option) are included in the PDF-file. Each drawing on the chalkboard is added after the slide that was shown when opening the chalkboard. Drawings on the notes canvas are not included in the PDF-file.&lt;/p&gt;
&lt;h2 id=&#34;configuration&#34;&gt;Configuration&lt;/h2&gt;
&lt;p&gt;The plugin has several configuration options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;boardmarkerWidth&lt;/code&gt;: an integer, the drawing width of the boardmarker; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkWidth&lt;/code&gt;: an integer, the drawing width of the chalk; larger values draw thicker lines.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalkEffect&lt;/code&gt;: a float in the range &lt;code&gt;[0.0, 1.0]&lt;/code&gt;, the intesity of the chalk effect on the chalk board. Full effect (default) &lt;code&gt;1.0&lt;/code&gt;, no effect &lt;code&gt;0.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;storage&lt;/code&gt;: Optional variable name for session storage of drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;: Optional filename for pre-recorded drawings.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readOnly&lt;/code&gt;: Configuation option allowing to prevent changes to existing drawings. If set to &lt;code&gt;true&lt;/code&gt; no changes can be made, if set to false &lt;code&gt;false&lt;/code&gt; changes can be made, if unset or set to &lt;code&gt;undefined&lt;/code&gt; no changes to the drawings can be made after returning to a slide or fragment for which drawings had been recorded before. In any case the recorded drawings for a slide or fragment can be cleared by pressing the &amp;lsquo;DEL&amp;rsquo; key (i.e. by using the &lt;code&gt;RevealChalkboard.clear()&lt;/code&gt; function).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transition&lt;/code&gt;: Gives the duration (in milliseconds) of the transition for a slide change, so that the notes canvas is drawn after the transition is completed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;theme&lt;/code&gt;: Can be set to either &lt;code&gt;&amp;quot;chalkboard&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;whiteboard&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following configuration options allow to change the appearance of the notes canvas and the chalkboard. All of these options require two values, the first gives the value for the notes canvas, the second for the chalkboard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;background&lt;/code&gt;: The first value expects a (semi-)transparent color which is used to provide visual feedback that the notes canvas is enabled, the second value expects a filename to a background image for the chalkboard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grid&lt;/code&gt;: By default whiteboard and chalkboard themes include a grid pattern on the background. This pattern can be modified by setting the color, the distance between lines, and the line width, e.g. &lt;code&gt;{ color: &#39;rgb(127,127,255,0.1)&#39;, distance: 40, width: 2}&lt;/code&gt;. Alternatively, the grid can be removed by setting the value to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;eraser&lt;/code&gt;: An image path and radius for the eraser.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;boardmarkers&lt;/code&gt;: A list of boardmarkers with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chalks&lt;/code&gt;: A list of chalks with given color and cursor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rememberColor&lt;/code&gt;: Whether to remember the last selected color for the slide canvas or the board.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of the configurations are optional and the default values shown below are used if the options are not provided.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-javascript&#34;&gt;Reveal.initialize({
	// ...
    chalkboard: {
        boardmarkerWidth: 3,
        chalkWidth: 7,
        chalkEffect: 1.0,
        storage: null,
        src: null,
        readOnly: undefined,
        transition: 800,
        theme: &amp;quot;chalkboard&amp;quot;,
        background: [ &#39;rgba(127,127,127,.1)&#39; , path + &#39;img/blackboard.png&#39; ],
        grid: { color: &#39;rgb(50,50,10,0.5)&#39;, distance: 80, width: 2},
        eraser: { src: path + &#39;img/sponge.png&#39;, radius: 20},
        boardmarkers : [
                { color: &#39;rgba(100,100,100,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-black.png), auto&#39;},
                { color: &#39;rgba(30,144,255, 1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-blue.png), auto&#39;},
                { color: &#39;rgba(220,20,60,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-red.png), auto&#39;},
                { color: &#39;rgba(50,205,50,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-green.png), auto&#39;},
                { color: &#39;rgba(255,140,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-orange.png), auto&#39;},
                { color: &#39;rgba(150,0,20150,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,1)&#39;, cursor: &#39;url(&#39; + path + &#39;img/boardmarker-yellow.png), auto&#39;}
        ],
        chalks: [
                { color: &#39;rgba(255,255,255,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-white.png), auto&#39;},
                { color: &#39;rgba(96, 154, 244, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-blue.png), auto&#39;},
                { color: &#39;rgba(237, 20, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-red.png), auto&#39;},
                { color: &#39;rgba(20, 237, 28, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-green.png), auto&#39;},
                { color: &#39;rgba(220, 133, 41, 0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-orange.png), auto&#39;},
                { color: &#39;rgba(220,0,220,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-purple.png), auto&#39;},
                { color: &#39;rgba(255,220,0,0.5)&#39;, cursor: &#39;url(&#39; + path + &#39;img/chalk-yellow.png), auto&#39;}
        ]
    },
    customcontrols: {
  		controls: [
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen-square&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle chalkboard (B)&#39;,
  			  action: &#39;RevealChalkboard.toggleChalkboard();&#39;
  			},
  			{ icon: &#39;&amp;lt;i class=&amp;quot;fa fa-pen&amp;quot;&amp;gt;&amp;lt;/i&amp;gt;&#39;,
  			  title: &#39;Toggle notes canvas (C)&#39;,
  			  action: &#39;RevealChalkboard.toggleNotesCanvas();&#39;
  			}
  		]
    },
    // ...

});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;license&#34;&gt;License&lt;/h2&gt;
&lt;p&gt;MIT licensed&lt;/p&gt;
&lt;p&gt;Copyright (C) 2021 Asvin Goel&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Ambiente R  além das análises estatísticas</title>
      <link>http://bendeivide.github.io/slides/ramb-alem-das-analises-estat/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/ramb-alem-das-analises-estat/</guid>
      <description>
&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;curso_verao.png&#34;
  &gt;

&lt;h1 id=&#34;ambiente-r--além-das-análises-estatísticas&#34;&gt;Ambiente R  além das análises estatísticas&lt;/h1&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Ben Dêivide&lt;/a&gt; | &lt;a href=&#34;https://www.ufsj.edu.br/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;UFSJ&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;selo-dc&#34;&gt;Selo DC&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/dc/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/ramb-alem-das-analises-estat/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_57f4d021c573f1cdb22f5303fccfacd9.webp 400w,
               /slides/ramb-alem-das-analises-estat/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_e3124639f3c96b16d12396d9954194c3.webp 760w,
               /slides/ramb-alem-das-analises-estat/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/ramb-alem-das-analises-estat/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_57f4d021c573f1cdb22f5303fccfacd9.webp&#34;
               width=&#34;385&#34;
               height=&#34;406&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;acesso-a-todo-material&#34;&gt;Acesso a todo material&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/bendeivide/palestras/tree/master/ramb-alem-das-analises-estatisticas&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/ramb-alem-das-analises-estat/folder_hu84ae0d30d5154d1e73aaf9945c348d03_20466_620e1c48e451842e2f4135b7117821ad.webp 400w,
               /slides/ramb-alem-das-analises-estat/folder_hu84ae0d30d5154d1e73aaf9945c348d03_20466_81e4eb609876936d8a5e708f395fd9b9.webp 760w,
               /slides/ramb-alem-das-analises-estat/folder_hu84ae0d30d5154d1e73aaf9945c348d03_20466_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/ramb-alem-das-analises-estat/folder_hu84ae0d30d5154d1e73aaf9945c348d03_20466_620e1c48e451842e2f4135b7117821ad.webp&#34;
               width=&#34;607&#34;
               height=&#34;471&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;nota&#34;&gt;Nota&lt;/h2&gt;
&lt;p&gt;Essa apresentação terá um viés, pois apesar do poder que a ambiente &lt;code&gt;R&lt;/code&gt; tem, muitos dos exemplos estarão dentro das minhas necessidades/limitações pessoais e profissionais. Portanto, um resultado do que experimento e venho experienciando!&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;histórico-sobre-o-ambiente-r&#34;&gt;Histórico sobre o ambiente R&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Criadores Ross Ihaka e por Robert Gentleman (Nova Zelândia), 1993&lt;/li&gt;
&lt;li&gt;Baseado na linguagem S, criado por John Chambers e colaboradores (Primeira versão 1976)&lt;/li&gt;
&lt;li&gt;Atualmente é mantida por colaboradores voluntários em todo o mundo&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;histórico-sobre-o-ambiente-r-1&#34;&gt;Histórico sobre o ambiente R&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Linguagem pode ser orientada a objetos, Código aberto, funcional, metapragmática, Licença GNU&lt;/li&gt;
&lt;li&gt;Repositório &lt;a href=&#34;https://cran.r-project.org/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;CRAN&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Popularidade com o &lt;a href=&#34;https://rstudio.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;RStudio&lt;/a&gt; (Joseph J. Allaire)&lt;/li&gt;
&lt;li&gt;Como instalar o R?&lt;/li&gt;
&lt;li&gt;Como instalar o RStudio?&lt;/li&gt;
&lt;li&gt;Como usar o R?&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;curso-r-nível-básico&#34;&gt;Curso R (Nível Básico)&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/courses/cursor/nbasico/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;Nível Básico&#34; srcset=&#34;
               /slides/ramb-alem-das-analises-estat/cursor-nb_hu8cbf2d1b9b5244f1524037e4474c538e_69900_4b297cb8f0e33e442ebf99b215388034.webp 400w,
               /slides/ramb-alem-das-analises-estat/cursor-nb_hu8cbf2d1b9b5244f1524037e4474c538e_69900_f138ba75b6cb4eb62d1ecea4bcae0172.webp 760w,
               /slides/ramb-alem-das-analises-estat/cursor-nb_hu8cbf2d1b9b5244f1524037e4474c538e_69900_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/ramb-alem-das-analises-estat/cursor-nb_hu8cbf2d1b9b5244f1524037e4474c538e_69900_4b297cb8f0e33e442ebf99b215388034.webp&#34;
               width=&#34;593&#34;
               height=&#34;579&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;curso-r-ni&#34;&gt;Curso R (NI)&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/post/cursorni2/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;Nível Intermediário&#34; srcset=&#34;
               /slides/ramb-alem-das-analises-estat/cursor-ni_hua909e2f7dc5b7deac580280a2231351e_70067_01ee0fc5dca62b5827c4744b677401e2.webp 400w,
               /slides/ramb-alem-das-analises-estat/cursor-ni_hua909e2f7dc5b7deac580280a2231351e_70067_2be287ff636a8ea73ce5b5354154f128.webp 760w,
               /slides/ramb-alem-das-analises-estat/cursor-ni_hua909e2f7dc5b7deac580280a2231351e_70067_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/ramb-alem-das-analises-estat/cursor-ni_hua909e2f7dc5b7deac580280a2231351e_70067_01ee0fc5dca62b5827c4744b677401e2.webp&#34;
               width=&#34;593&#34;
               height=&#34;579&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;rapidinhas-do-r&#34;&gt;Rapidinhas do R&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/project/rapidinhasr/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/ramb-alem-das-analises-estat/rapidinhasr_huf4c584a0ea803c0b4fded9f2abc27f53_510973_df46483f285db6db6d908bc356b06e75.webp 400w,
               /slides/ramb-alem-das-analises-estat/rapidinhasr_huf4c584a0ea803c0b4fded9f2abc27f53_510973_db647e21fc70a6855b86924338dcb47a.webp 760w,
               /slides/ramb-alem-das-analises-estat/rapidinhasr_huf4c584a0ea803c0b4fded9f2abc27f53_510973_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/ramb-alem-das-analises-estat/rapidinhasr_huf4c584a0ea803c0b4fded9f2abc27f53_510973_df46483f285db6db6d908bc356b06e75.webp&#34;
               width=&#34;760&#34;
               height=&#34;374&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;coleção-estudando-o-ambiente-r&#34;&gt;Coleção Estudando o Ambiente R&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/book-eambr01&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/ramb-alem-das-analises-estat/hardcover01_hu6fd2f9a5af792bfbcb973270ac465a56_130113_f7ee7ac1bcb38885ed43ff6283f91281.webp 400w,
               /slides/ramb-alem-das-analises-estat/hardcover01_hu6fd2f9a5af792bfbcb973270ac465a56_130113_f8257eabb142099dedb529c07f030721.webp 760w,
               /slides/ramb-alem-das-analises-estat/hardcover01_hu6fd2f9a5af792bfbcb973270ac465a56_130113_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/ramb-alem-das-analises-estat/hardcover01_hu6fd2f9a5af792bfbcb973270ac465a56_130113_f7ee7ac1bcb38885ed43ff6283f91281.webp&#34;
               width=&#34;248&#34;
               height=&#34;351&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;
















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/ramb-alem-das-analises-estat/hardcover02_hu6fd2f9a5af792bfbcb973270ac465a56_140122_45f619095959daf2295f20cedc96666e.webp 400w,
               /slides/ramb-alem-das-analises-estat/hardcover02_hu6fd2f9a5af792bfbcb973270ac465a56_140122_bf2cc9d0d398d7bc6c1078f0736f1b29.webp 760w,
               /slides/ramb-alem-das-analises-estat/hardcover02_hu6fd2f9a5af792bfbcb973270ac465a56_140122_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/ramb-alem-das-analises-estat/hardcover02_hu6fd2f9a5af792bfbcb973270ac465a56_140122_45f619095959daf2295f20cedc96666e.webp&#34;
               width=&#34;248&#34;
               height=&#34;351&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;

















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/ramb-alem-das-analises-estat/hardcover03_hu6fd2f9a5af792bfbcb973270ac465a56_132421_5d2480d8e0e7c78bda916b4e31c58e8b.webp 400w,
               /slides/ramb-alem-das-analises-estat/hardcover03_hu6fd2f9a5af792bfbcb973270ac465a56_132421_2a3fcd56ea738f0fa720cfa8ecc1caf6.webp 760w,
               /slides/ramb-alem-das-analises-estat/hardcover03_hu6fd2f9a5af792bfbcb973270ac465a56_132421_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/ramb-alem-das-analises-estat/hardcover03_hu6fd2f9a5af792bfbcb973270ac465a56_132421_5d2480d8e0e7c78bda916b4e31c58e8b.webp&#34;
               width=&#34;248&#34;
               height=&#34;351&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;ferramentas-do-r-além-do-fim-estatístico&#34;&gt;Ferramentas do R além do fim Estatístico&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Análises Estatísticas ❌&lt;/li&gt;
&lt;li&gt;Criação e divulgação de materiais científicos:
&lt;ul&gt;
&lt;li&gt;Materiais Dinâmicos (HTML, JavaScript, CSS, &lt;code&gt;\(\LaTeX\)&lt;/code&gt;, &lt;code&gt;R&lt;/code&gt;, PDF) ✔️&lt;/li&gt;
&lt;li&gt;Materiais estatísticos (HTML, PDF, EPUB, WORD, SLIDES) ✔️&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;ferramentas-do-r-além-do-fim-estatístico-1&#34;&gt;Ferramentas do R além do fim Estatístico&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Desenvolvimento de pacotes  ✔️
&lt;ul&gt;
&lt;li&gt;Criação de GUIs para pacotes (Pacotes &lt;code&gt;tcltk&lt;/code&gt;, &lt;code&gt;GTK+&lt;/code&gt;, &lt;code&gt;shiny&lt;/code&gt;) ✔️&lt;/li&gt;
&lt;li&gt;Documentação de pacotes (Vignettes, tutorial de pacote) ✔️&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;ferramentas-do-r-além-do-fim-estatístico-2&#34;&gt;Ferramentas do R além do fim Estatístico&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Websites ✔️&lt;/li&gt;
&lt;li&gt;Blogs ✔️&lt;/li&gt;
&lt;li&gt;Postcards ✔️&lt;/li&gt;
&lt;li&gt;Currículos ✔️&lt;/li&gt;
&lt;li&gt;Dashboards ✔️&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;o-que-será-necessário-para-usar-essas-ferramentas&#34;&gt;O que será necessário para usar essas ferramentas?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://youtu.be/Gei-gtBlMos&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Instalação do &lt;code&gt;R&lt;/code&gt;&lt;/a&gt; e &lt;a href=&#34;https://youtu.be/Gei-gtBlMos&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;RStudio/Pandoc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;No &lt;code&gt;R&lt;/code&gt; &lt;a href=&#34;https://youtu.be/YRSdoyfqp_g&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;instalar os pacotes&lt;/a&gt;:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;rmarkdown&lt;/code&gt; e &lt;code&gt;knitr&lt;/code&gt; - Pacotes mais importantes!&lt;/li&gt;
&lt;li&gt;&lt;code&gt;shiny&lt;/code&gt; - Pacote para criação de materiais dinâmicos&lt;/li&gt;
&lt;li&gt;&lt;code&gt;devtools&lt;/code&gt; e &lt;code&gt;usethis&lt;/code&gt; - kit de ferramentas&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rsconnect&lt;/code&gt; - Envio para &lt;em&gt;shinyapps.io&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;o-que-será-necessário-para-usar-essas-ferramentas-1&#34;&gt;O que será necessário para usar essas ferramentas?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;No &lt;code&gt;R&lt;/code&gt; &lt;a href=&#34;https://youtu.be/YRSdoyfqp_g&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;instalar os pacotes&lt;/a&gt;:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;tinytex&lt;/code&gt; - Latex (Caso você não queira instalar o &lt;code&gt;\(\LaTeX\)&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rticles&lt;/code&gt; - Escrever Artigos&lt;/li&gt;
&lt;li&gt;&lt;code&gt;thesisdown&lt;/code&gt; - Escrever Teses&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bookdown&lt;/code&gt; - Escrever Livros (HTML, PDF, ePub, Kindle)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;o-que-será-necessário-para-usar-essas-ferramentas-2&#34;&gt;O que será necessário para usar essas ferramentas?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;No &lt;code&gt;R&lt;/code&gt; &lt;a href=&#34;https://youtu.be/YRSdoyfqp_g&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;instalar os pacotes&lt;/a&gt;:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;blogdown&lt;/code&gt; e &lt;code&gt;distill&lt;/code&gt; - Criação de blogs, websites&lt;/li&gt;
&lt;li&gt;&lt;code&gt;postcards&lt;/code&gt; - Criação de um cartão de visita&lt;/li&gt;
&lt;li&gt;&lt;code&gt;learnr&lt;/code&gt; - Criação de tutoriais para aprender R&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pkgdown&lt;/code&gt;(Documentação para pacotes R) e &lt;code&gt;usethis&lt;/code&gt; ou &lt;code&gt;rmarkdown&lt;/code&gt;(Criação de Vignettes)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;o-que-será-necessário-para-usar-essas-ferramentas-3&#34;&gt;O que será necessário para usar essas ferramentas?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;No &lt;code&gt;R&lt;/code&gt; &lt;a href=&#34;https://youtu.be/YRSdoyfqp_g&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;instalar os pacotes&lt;/a&gt;:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;tcltk&lt;/code&gt; (Existem muitos outros pacotes!) - GUI&amp;rsquo;s&lt;/li&gt;
&lt;li&gt;&lt;code&gt;manipulate&lt;/code&gt; e &lt;code&gt;shiny&lt;/code&gt; - gráficos interativos no RStudio e &lt;code&gt;scatterplot3d&lt;/code&gt; - Gráficos em 3d&lt;/li&gt;
&lt;li&gt;&lt;code&gt;exams&lt;/code&gt; - Criação de Provas para disciplinas + MOODLE&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;\(\LaTeX\)&lt;/code&gt;, MS Word (ou similares)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;r-markdown&#34;&gt;R Markdown&lt;/h2&gt;
&lt;p&gt;Três componentes básicos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Metadados&lt;/strong&gt;: O corpo do documento&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Texto&lt;/strong&gt;: Assunto dissertado&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Código&lt;/strong&gt;: Linguagem de interesse&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;LEMBRETE&lt;/strong&gt;: A extensão de um arquivo R Markdown é: &lt;em&gt;.Rmd&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;material-de-apoio-ao-r-markdown&#34;&gt;Material de apoio ao R Markdown&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/cdec/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/ramb-alem-das-analises-estat/cdec_hu891cdc650656200eb98f514c61f934c4_17480_48bcaa36767fa23207c27b820274c199.webp 400w,
               /slides/ramb-alem-das-analises-estat/cdec_hu891cdc650656200eb98f514c61f934c4_17480_d7c00888fc771d6909d650596147e429.webp 760w,
               /slides/ramb-alem-das-analises-estat/cdec_hu891cdc650656200eb98f514c61f934c4_17480_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/ramb-alem-das-analises-estat/cdec_hu891cdc650656200eb98f514c61f934c4_17480_48bcaa36767fa23207c27b820274c199.webp&#34;
               width=&#34;226&#34;
               height=&#34;364&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;material-de-apoio-ao-r-markdown-1&#34;&gt;Material de apoio ao R Markdown&lt;/h2&gt;
&lt;!-- O básico no R Markdown: --&gt;
&lt;!-- &lt;https://rmarkdown.rstudio.com/authoring_basics.html&gt; --&gt;
&lt;!-- A ideia dos pacotes nos documentos dinâmicos: --&gt;
&lt;!-- &lt;https://jreduardo.github.io/semanest-ufpr2017/&gt; --&gt;
&lt;p&gt;Livros do RMarkdown (Yihui Xie et al):
&lt;a href=&#34;https://bookdown.org/yihui/rmarkdown/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://bookdown.org/yihui/rmarkdown/&lt;/a&gt;
&lt;a href=&#34;https://bookdown.org/yihui/rmarkdown-cookbook/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://bookdown.org/yihui/rmarkdown-cookbook/&lt;/a&gt;&lt;/p&gt;
&lt;!-- &lt;http://cursos.leg.ufpr.br/prr/capDocDin.html&gt; --&gt;
&lt;p&gt;Livro em desenvolvimento&lt;/p&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/ramb-alem-das-analises-estat/hardcover04_huc27295f1b46b005b1578c94370131f01_106286_67a3b1d67ee6b6d3910f5de48fe6dcac.webp 400w,
               /slides/ramb-alem-das-analises-estat/hardcover04_huc27295f1b46b005b1578c94370131f01_106286_cfe30f79f7393e50b5ff6820365d5d22.webp 760w,
               /slides/ramb-alem-das-analises-estat/hardcover04_huc27295f1b46b005b1578c94370131f01_106286_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/ramb-alem-das-analises-estat/hardcover04_huc27295f1b46b005b1578c94370131f01_106286_67a3b1d67ee6b6d3910f5de48fe6dcac.webp&#34;
               width=&#34;174&#34;
               height=&#34;246&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;/media/open-book3.jpg&#34;
  &gt;

&lt;h2 id=&#34;r-markdown-documentos-estatísticos&#34;&gt;R Markdown: Documentos estatísticos&lt;/h2&gt;
&lt;p&gt;Aplicações:&lt;/p&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/ramb-alem-das-analises-estat/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_0cd5d2661e8fc6dbb49dd886a81160b2.webp 400w,
               /slides/ramb-alem-das-analises-estat/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_5bd7ddd151c2f4da3fa79a2fa5972624.webp 760w,
               /slides/ramb-alem-das-analises-estat/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/ramb-alem-das-analises-estat/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_0cd5d2661e8fc6dbb49dd886a81160b2.webp&#34;
               width=&#34;170&#34;
               height=&#34;170&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;r-markdown-documentos-dinâmicos&#34;&gt;R Markdown: Documentos dinâmicos&lt;/h2&gt;
&lt;p&gt;Recursos do Shiny:&lt;/p&gt;
&lt;p&gt;Refêrencia:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://mastering-shiny.org/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://mastering-shiny.org/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Exemplos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://shiny.estatistica.ccet.ufrn.br/DashboardDeputados/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Reembolso de deputados (UFRN)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://shiny.rstudio.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;em&gt;Trends&lt;/em&gt; do Google (RStudio)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://shiny.rstudio.com/gallery/didacting-modeling.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Processo de modelagem didática&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;r-markdown-documentos-dinâmicos-1&#34;&gt;R Markdown: Documentos dinâmicos&lt;/h2&gt;
&lt;p&gt;Aplicações:&lt;/p&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/ramb-alem-das-analises-estat/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_0cd5d2661e8fc6dbb49dd886a81160b2.webp 400w,
               /slides/ramb-alem-das-analises-estat/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_5bd7ddd151c2f4da3fa79a2fa5972624.webp 760w,
               /slides/ramb-alem-das-analises-estat/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/ramb-alem-das-analises-estat/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_0cd5d2661e8fc6dbb49dd886a81160b2.webp&#34;
               width=&#34;170&#34;
               height=&#34;170&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;criação-de-websites&#34;&gt;Criação de &lt;em&gt;Websites&lt;/em&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Website (pacote &lt;a href=&#34;https://rstudio.github.io/distill/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;distill&lt;/code&gt;&lt;/a&gt;): &lt;a href=&#34;https://youtu.be/FbTLrfYWQQw&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Rapidinhas do R&lt;/a&gt;, ex. &lt;a href=&#34;https://bendeivide.github.io/cursor/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Curso R&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Website via &lt;a href=&#34;https://pkgs.rstudio.com/blogdown/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;blogdown&lt;/code&gt;&lt;/a&gt; e &lt;a href=&#34;https://wowchemy.com/docs/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;Hugo&lt;/code&gt;&lt;/a&gt; (&lt;a href=&#34;https://wowchemy.com/templates/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;temas&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/ramb-alem-das-analises-estat/ben_hu96f6bd792b3af7602ac6cf7cef98b13a_17598_7e5abe44a987059ffc245fad5b802500.webp 400w,
               /slides/ramb-alem-das-analises-estat/ben_hu96f6bd792b3af7602ac6cf7cef98b13a_17598_7191e69c4c5b62592abfeed760168432.webp 760w,
               /slides/ramb-alem-das-analises-estat/ben_hu96f6bd792b3af7602ac6cf7cef98b13a_17598_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/ramb-alem-das-analises-estat/ben_hu96f6bd792b3af7602ac6cf7cef98b13a_17598_7e5abe44a987059ffc245fad5b802500.webp&#34;
               width=&#34;216&#34;
               height=&#34;217&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;exemplos-de-websites&#34;&gt;Exemplos de &lt;em&gt;Websites&lt;/em&gt;&lt;/h2&gt;
&lt;p&gt;Exemplos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://bendeivide.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Ben Dêivide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://rmarkdown.rstudio.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;R Markdown no RStudio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Website pessoal de &lt;a href=&#34;https://robjhyndman.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Rob J Hyndman&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Website pessoal de &lt;a href=&#34;https://amber.rbind.io&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Amber Thomas&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Website pessoal de &lt;a href=&#34;https://emitanaka.github.io&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Emi Tanaka&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;exemplo-de-postcard&#34;&gt;Exemplo de &lt;em&gt;Postcard&lt;/em&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Exemplo: &lt;a href=&#34;https://bendeivide.github.io/cursor/about.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Ben Dêivide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;exemplo-de-dashboard&#34;&gt;Exemplo de Dashboard&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.shinyapps.io/RDashboards/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/ramb-alem-das-analises-estat/midrangeMCP_huf45dc9e9da53fa562b8e5b4d36571394_51649_39352c290d8c5e5a1804a131d2592ce5.webp 400w,
               /slides/ramb-alem-das-analises-estat/midrangeMCP_huf45dc9e9da53fa562b8e5b4d36571394_51649_40d47179797e8775f2210bae5d3f9b20.webp 760w,
               /slides/ramb-alem-das-analises-estat/midrangeMCP_huf45dc9e9da53fa562b8e5b4d36571394_51649_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/ramb-alem-das-analises-estat/midrangeMCP_huf45dc9e9da53fa562b8e5b4d36571394_51649_39352c290d8c5e5a1804a131d2592ce5.webp&#34;
               width=&#34;461&#34;
               height=&#34;534&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;outros-exemplos-de-dashboards&#34;&gt;Outros exemplos de Dashboards&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://eelloo.nl/groepsrapportages-met-infographics/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;eelloo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://jjallaire.shinyapps.io/shiny-crandash/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Pacotes populares&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://shiny.estatistica.ccet.ufrn.br/DashboardDeputados/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Controle de gastos públicos&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://pkgs.rstudio.com/flexdashboard/articles/examples.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Material para usar Dashboards + Shiny&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;r-markdown-relatórios-programados&#34;&gt;R Markdown: Relatórios programados&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Exemplo: &lt;a href=&#34;https://rmarkdown.rstudio.com/articles_mail_merge.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Mine Çetinkaya-Rundel&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;/media/open-book3.jpg&#34;
  &gt;

&lt;h2 id=&#34;r-markdown-relatórios-programados-aplicação&#34;&gt;R Markdown: Relatórios programados (Aplicação)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Nomes dos professores do DEFIM/UFSJ e númerode suas salas;&lt;/li&gt;
&lt;li&gt;Vamos fazer um documento em PDF: nomes dos professores, número de salas.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/ramb-alem-das-analises-estat/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_0cd5d2661e8fc6dbb49dd886a81160b2.webp 400w,
               /slides/ramb-alem-das-analises-estat/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_5bd7ddd151c2f4da3fa79a2fa5972624.webp 760w,
               /slides/ramb-alem-das-analises-estat/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/ramb-alem-das-analises-estat/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_0cd5d2661e8fc6dbb49dd886a81160b2.webp&#34;
               width=&#34;170&#34;
               height=&#34;170&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;r-markdown-livros&#34;&gt;R Markdown: Livros&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Site: &lt;a href=&#34;https://bookdown.org/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://bookdown.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Exemplo: &lt;a href=&#34;https://bendeivide.github.io/book-epaec/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;EPAEC&lt;/a&gt;, &lt;a href=&#34;https://bendeivide.github.io/book-eambr/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;EAMBR&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;r-markdown-artigos-e-teses&#34;&gt;R Markdown: Artigos e Teses&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Pacote &lt;code&gt;bookdown&lt;/code&gt; (Tese)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Pacote &lt;code&gt;rticles&lt;/code&gt; (Artigo): &lt;code&gt;install.packages(&amp;quot;rticles&amp;quot;)&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Pacote &lt;code&gt;thesisdown&lt;/code&gt; (Tese):&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;if (!require(&amp;quot;remotes&amp;quot;))
  install.packages(&amp;quot;remotes&amp;quot;, repos = &amp;quot;https://cran.rstudio.org&amp;quot;)
remotes::install_github(&amp;quot;rstudio/bookdown&amp;quot;)
remotes::install_github(&amp;quot;ismayc/thesisdown&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;/media/open-book3.jpg&#34;
  &gt;

&lt;h2 id=&#34;r-markdown-livros-aplicações&#34;&gt;R Markdown: Livros (Aplicações)&lt;/h2&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/ramb-alem-das-analises-estat/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_0cd5d2661e8fc6dbb49dd886a81160b2.webp 400w,
               /slides/ramb-alem-das-analises-estat/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_5bd7ddd151c2f4da3fa79a2fa5972624.webp 760w,
               /slides/ramb-alem-das-analises-estat/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/ramb-alem-das-analises-estat/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_0cd5d2661e8fc6dbb49dd886a81160b2.webp&#34;
               width=&#34;170&#34;
               height=&#34;170&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;/media/open-book3.jpg&#34;
  &gt;

&lt;h2 id=&#34;r-markdown-slides-aplicações&#34;&gt;R Markdown: Slides (Aplicações)&lt;/h2&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/ramb-alem-das-analises-estat/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_0cd5d2661e8fc6dbb49dd886a81160b2.webp 400w,
               /slides/ramb-alem-das-analises-estat/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_5bd7ddd151c2f4da3fa79a2fa5972624.webp 760w,
               /slides/ramb-alem-das-analises-estat/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/ramb-alem-das-analises-estat/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_0cd5d2661e8fc6dbb49dd886a81160b2.webp&#34;
               width=&#34;170&#34;
               height=&#34;170&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;documentação-para-pacotes&#34;&gt;Documentação para pacotes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Pacote &lt;a href=&#34;https://pkgdown.r-lib.org/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;pkgdown&lt;/code&gt;&lt;/a&gt;: ex.: &lt;a href=&#34;https://bendeivide.github.io/midrangeMCP/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;midrangeMCP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Vignettes (Pacote &lt;a href=&#34;https://usethis.r-lib.org/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;usethis&lt;/code&gt;&lt;/a&gt;): &lt;code&gt;usethis::use_vignette()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;interface-gráfica-ao-usuário&#34;&gt;Interface Gráfica ao Usuário&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Exemplo do pacote &lt;code&gt;tcltk&lt;/code&gt;: &lt;a href=&#34;https://bendeivide.github.io/project/mcptests/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;MCPtests&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34;
           src=&#34;http://bendeivide.github.io/slides/ramb-alem-das-analises-estat/MCPtests.gif&#34;
           loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Exemplo do pacote &lt;code&gt;shiny&lt;/code&gt;: &lt;a href=&#34;https://dreamrs.github.io/esquisse/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;esquisse&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;documentos-para-aprendizagem-do-r&#34;&gt;Documentos para aprendizagem do R&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Pacote &lt;a href=&#34;https://rstudio.github.io/learnr/index.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;learnr&lt;/code&gt;&lt;/a&gt;: ex.: &lt;a href=&#34;http://bendeivide.shinyapps.io/Est_Exp/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Estatística Experimental&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;aplicação-de-provas-academia&#34;&gt;Aplicação de provas (Academia)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Pacote &lt;a href=&#34;http://r-exams.org/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;code&gt;exams&lt;/code&gt;&lt;/a&gt; e uso no &lt;a href=&#34;https://moodle.org/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;MOODLE&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/ramb-alem-das-analises-estat/rexams&amp;#43;moodle_hu90e239b8805e1b03b777d53fd8bd0aea_63184_45a5acf0538bc5ef2ea0500c6d063fe2.webp 400w,
               /slides/ramb-alem-das-analises-estat/rexams&amp;#43;moodle_hu90e239b8805e1b03b777d53fd8bd0aea_63184_f19d123669d0c8ec3229ab58813739b8.webp 760w,
               /slides/ramb-alem-das-analises-estat/rexams&amp;#43;moodle_hu90e239b8805e1b03b777d53fd8bd0aea_63184_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/ramb-alem-das-analises-estat/rexams&amp;#43;moodle_hu90e239b8805e1b03b777d53fd8bd0aea_63184_45a5acf0538bc5ef2ea0500c6d063fe2.webp&#34;
               width=&#34;295&#34;
               height=&#34;155&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;/media/open-book3.jpg&#34;
  &gt;

&lt;h2 id=&#34;gráficos-3d-latex-e-r&#34;&gt;Gráficos 3D (&lt;code&gt;\(\LaTeX\)&lt;/code&gt; e &lt;code&gt;R&lt;/code&gt;)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Pacote &lt;code&gt;scatterplot3d&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;/media/open-book3.jpg&#34;
  &gt;

&lt;h2 id=&#34;tabelas-com-ilustrações-animadas--sweave&#34;&gt;Tabelas com ilustrações animadas + &lt;code&gt;Sweave&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/ramb-alem-das-analises-estat/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_0cd5d2661e8fc6dbb49dd886a81160b2.webp 400w,
               /slides/ramb-alem-das-analises-estat/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_5bd7ddd151c2f4da3fa79a2fa5972624.webp 760w,
               /slides/ramb-alem-das-analises-estat/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/ramb-alem-das-analises-estat/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_0cd5d2661e8fc6dbb49dd886a81160b2.webp&#34;
               width=&#34;170&#34;
               height=&#34;170&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;onde-publicamos-esses-materiais&#34;&gt;Onde publicamos esses materiais?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://rpubs.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;RPubs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://rpubs.com/cathydatascience/518692&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Como publicar!&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.shinyapps.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;shinyapp.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://bookdown.org/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Bookdown&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://marcusnunes.me/posts/como-instalar-o-shiny-em-seu-proprio-servidor/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Servidor próprio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gomesfellipe.github.io/post/2018-10-27-server-cloud/server-cloud/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Servidor online&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://https://github.com&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;GitHub&lt;/a&gt;, &lt;a href=&#34;https://bendeivide.github.io/project/rapidinhasr/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Rapidinhas do R 5 a 11&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.netlify.com&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Netlify&lt;/a&gt;, &lt;a href=&#34;https://bookdown.org/yihui/rmarkdown/blogdown-deploy.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Como publicar!&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h1 id=&#34;questões&#34;&gt;Questões?&lt;/h1&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Dúvidas e Sugestões&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/#contact&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Contato&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Como criar uma website via R</title>
      <link>http://bendeivide.github.io/slides/websiter/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/websiter/</guid>
      <description>
&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;EAR-rdoc-background.png&#34;
  &gt;

&lt;h1 id=&#34;como-criar-uma-website-via-r&#34;&gt;Como criar uma website via R&lt;/h1&gt;
&lt;p&gt;EAR: R Documentações
&lt;/br&gt;
&lt;/br&gt;

  &lt;i class=&#34;fas fa-user-tie  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;https://bendeivide.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Ben Dêivide&lt;/a&gt; | 
  &lt;i class=&#34;fas fa-school  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;https://www.ufsj.edu.br/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;UFSJ&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;EAR-rdoc-background.png&#34;
  &gt;

&lt;h2 id=&#34;encarte&#34;&gt;Encarte&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;verao2023ufla-ben.png&#34; 
width=&#34;400&#34; 
height=&#34;400&#34; /&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;EAR-rdoc-background.png&#34;
  &gt;

&lt;h2 id=&#34;filosofia-de-publicação-selo-dc&#34;&gt;Filosofia de publicação (Selo DC)&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/dc/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/websiter/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_57f4d021c573f1cdb22f5303fccfacd9.webp 400w,
               /slides/websiter/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_e3124639f3c96b16d12396d9954194c3.webp 760w,
               /slides/websiter/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/websiter/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_57f4d021c573f1cdb22f5303fccfacd9.webp&#34;
               width=&#34;385&#34;
               height=&#34;406&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;EAR-rdoc-background.png&#34;
  &gt;

&lt;section&gt;
&lt;h2&gt; Pré-requisitos &lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Ambiente R (&lt;a href=&#34;http://localhost:4321/courses/ear/rbasico/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;R básico&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Instalação de pacotes R:
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://pkgs.rstudio.com/blogdown/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;blogdown&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;R&amp;gt; install.packages(&amp;quot;blogdown&amp;quot;)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://posit.co/downloads/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;RStudio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Gerador de site (&lt;a href=&#34;https://gohugo.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Hugo&lt;/a&gt;) &lt;a href=&#34;https://github.com/yihui/hugo-lithium&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Lithium&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;R&amp;gt; blogdown::install_hugo()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt; Pré-requisitos &lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Conhecimento básico sobre a linguagem &lt;code&gt;YAML&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Conversor de documentos &lt;a href=&#34;https://pandoc.org&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Pandoc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;GitHub&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;RStudio e Github via &lt;a href=&#34;https://bendeivide.github.io/project/rapidinhasr/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Rapidinhas do R (5-16)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Pacote &lt;a href=&#34;&#34;&gt;usethis&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://rmarkdown.rstudio.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;RMarkdown&lt;/a&gt; e &lt;a href=&#34;https://www.markdownguide.org/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Markdown&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://pkgs.rstudio.com/bookdown/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Bookdown&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Use: &lt;code&gt;&amp;lt;&amp;gt;.Rmarkdown&lt;/code&gt; ao invés de &lt;code&gt;&amp;lt;&amp;gt;.rmd&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Diretório do projeto: &lt;code&gt;docs&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;hr&gt;
&lt;h2 id=&#34;material-de-apoio&#34;&gt;Material de apoio&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/bendeivide/websiter&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/websiter/folder_hu84ae0d30d5154d1e73aaf9945c348d03_20466_620e1c48e451842e2f4135b7117821ad.webp 400w,
               /slides/websiter/folder_hu84ae0d30d5154d1e73aaf9945c348d03_20466_81e4eb609876936d8a5e708f395fd9b9.webp 760w,
               /slides/websiter/folder_hu84ae0d30d5154d1e73aaf9945c348d03_20466_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/websiter/folder_hu84ae0d30d5154d1e73aaf9945c348d03_20466_620e1c48e451842e2f4135b7117821ad.webp&#34;
               width=&#34;607&#34;
               height=&#34;471&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;EAR-rdoc-background.png&#34;
  &gt;

&lt;h2 id=&#34;mão-na-massa&#34;&gt;Mão na massa!&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Criar uma página web apenas com o R (Hugo Lithium)&lt;/li&gt;
&lt;/ol&gt;
  &lt;ul&gt;
    &lt;ul&gt;
      &lt;li&gt;Melhor customização: HTML, CSS, JavaScript, etc (Fora do escopo!)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/ul&gt;
&lt;ol start=&#34;2&#34;&gt;
&lt;li&gt;Chamaremos via GitHub o projeto: Hugo Lithium&lt;/li&gt;
&lt;li&gt;Configurar a página criada&lt;/li&gt;
&lt;li&gt;Subiremos o projeto ao GitHub&lt;/li&gt;
&lt;li&gt;Ativar a página!&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;EAR-rdoc-background.png&#34;
  &gt;

&lt;h2 id=&#34;ideias-sobre-_website_-no-r&#34;&gt;Ideias sobre &lt;em&gt;website&lt;/em&gt; no R&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Páginas estáticas e Páginas dinâmicas&lt;/li&gt;
&lt;li&gt;Servidor local (Desenvolvimento)&lt;/li&gt;
&lt;li&gt;Servidor da página (GitHub)
&lt;ul&gt;
&lt;li&gt;Raiz (&lt;code&gt;./&lt;/code&gt;) ou &lt;code&gt;docs/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;index.html&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Arquivos YAML: &lt;code&gt;&amp;lt;&amp;gt;.yaml&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;EAR-rdoc-background.png&#34;
  &gt;

&lt;h2 id=&#34;projetos-de-páginas&#34;&gt;Projetos de páginas&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Padrão RStudio (Yihui Xie):
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/yihui/hugo-lithium&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Hugo-Lithium&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/wowchemy/starter-hugo-academic&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Hugo-Acadêmico&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/caressofsteel/hugo-story&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Hugo-Story&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Livro &lt;a href=&#34;https://pkgs.rstudio.com/bookdown/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;bookdown&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;EAR-rdoc-background.png&#34;
  &gt;

&lt;h2 id=&#34;referências-de-livros&#34;&gt;Referências de livros&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://bookdown.org/yihui/rmarkdown/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;R Markdown: The Definitive Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://bookdown.org/yihui/rmarkdown-cookbook/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;R Markdown Cookbook&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://pkgs.rstudio.com/bookdown/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Pacote bookdown&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- --- --&gt;
&lt;!-- 
&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;EAR-rdoc-background.png&#34;
  &gt;
 --&gt;
&lt;!-- ## Revisando o *RMarkdown* --&gt;
&lt;!-- &lt;img src=&#34;rmarkdown.png&#34;  --&gt;
&lt;!--      width=&#34;400&#34;  --&gt;
&lt;!--      height=&#34;400&#34; /&gt; --&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;EAR-rdoc-background.png&#34;
  &gt;

&lt;section&gt;
  &lt;h2&gt; Usando o blogdown &lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;blogdown.svg&#34; 
width=&#34;400&#34; 
height=&#34;400&#34; /&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section&gt;
  &lt;h2&gt; Usando o bookdown &lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;bookdown.png&#34; 
width=&#34;400&#34; 
height=&#34;400&#34; /&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;EAR-rdoc-background.png&#34;
  &gt;

&lt;section&gt;
 &lt;h2&gt; Github + RStudio + Pacote usethis &lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;github.png&#34; 
width=&#34;200&#34; 
height=&#34;200&#34; /&gt;
+
&lt;img src=&#34;rstudio.png&#34; 
width=&#34;200&#34; 
height=&#34;200&#34; /&gt;
+
&lt;img src=&#34;usethis.png&#34; 
width=&#34;200&#34; 
height=&#34;200&#34; /&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section&gt;
 &lt;h2&gt;&#34;Push&#34; ao Github&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;R&amp;gt; usethis::use_git()
R&amp;gt; usethis::use_github()
&lt;/code&gt;&lt;/pre&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;EAR-rdoc-background.png&#34;
  &gt;

&lt;h2 id=&#34;dicas&#34;&gt;Dicas&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Sites mais simples: pacote &lt;a href=&#34;https://rstudio.github.io/distill/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;distill&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Outros temas do Hugo:
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://themes.gohugo.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Temas Hugo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Sites para pacotes R: &lt;a href=&#34;https://pkgdown.r-lib.org/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;pkgdown&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;EAR-rdoc-background.png&#34;
  &gt;

&lt;h1 id=&#34;obrigado&#34;&gt;Obrigado!&lt;/h1&gt;
&lt;p&gt;Sugestões, perguntas, críticas&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;EAR-rdoc.png&#34; 
width=&#34;500&#34; 
height=&#34;400&#34; /&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Como desenvolver o primeiro pacote R</title>
      <link>http://bendeivide.github.io/slides/meupacoter-gems-ufs/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/meupacoter-gems-ufs/</guid>
      <description>
&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;hardcover.png&#34;
  &gt;

&lt;h2 id=&#34;como-desenvolver-o-primeiro-pacote-r&#34;&gt;Como desenvolver o primeiro pacote R&lt;/h2&gt;
&lt;p&gt;
  &lt;i class=&#34;fas fa-user-tie  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;https://bendeivide.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Ben Dêivide&lt;/a&gt; |

  &lt;i class=&#34;fas fa-school  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;https://www.ufsj.edu.br/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;UFSJ&lt;/a&gt;&lt;/p&gt;
&lt;img src=&#34;logo.png&#34; width=&#34;40%&#34; height=&#34;70%&#34; style=&#34;display: block; margin: auto;&#34; /&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;hardcover.png&#34;
  &gt;

&lt;h2 id=&#34;selo-dc&#34;&gt;Selo DC&lt;/h2&gt;
&lt;img src=&#34;SeloDC-branco.png&#34; width=&#34;40%&#34; height=&#34;70%&#34; style=&#34;display: block; margin: auto;&#34; /&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;hardcover.png&#34;
  &gt;

&lt;h2 id=&#34;livros-em-desenvolvimento&#34;&gt;Livros em desenvolvimento&lt;/h2&gt;
&lt;img src=&#34;livro.png&#34; width=&#34;100%&#34; height=&#34;100%&#34; style=&#34;display: block; margin: auto;&#34; /&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;hardcover.png&#34;
  &gt;

&lt;h2 id=&#34;pacotes-estatísticos-publicados&#34;&gt;Pacotes estatísticos publicados&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://doi.org/10.32614/RJ-2014-029&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;SMR&lt;/a&gt; (BATISTA; FERREIRA, 2014)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://bendeivide.github.io/midrangeMCP/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;midrangeMCP&lt;/a&gt; (BATISTA; FERREIRA; OLIVEIRA, 2020)
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://doi.org/10.1590/1413-7054202044008020&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Alternative Tukey test&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/bendeivide/MCPtests&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;MCPtests&lt;/a&gt; (BATISTA; FERREIRA; OLIVEIRA; SANTOS, 2020)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://rpubs.com/Henriqueufla/617206&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;TVMM&lt;/a&gt; (ALVES; FERREIRA; BATISTA, 2020)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://cran.r-project.org/web/packages/cppcor/index.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;cppcor&lt;/a&gt; (RIBEIRO; BATISTA; MARTINS; OLIVEIRA, 2020)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;hardcover.png&#34;
  &gt;

&lt;h2 id=&#34;pacotes-em-desenvolvimento&#34;&gt;Pacotes em desenvolvimento&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/bendeivide/leem&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;leem&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/bendeivide/statscience&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;statscience&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;hardcover.png&#34;
  &gt;

&lt;h2 id=&#34;o-que-é-necessário&#34;&gt;O que é necessário?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Conhecer o ambiente R (&lt;a href=&#34;https://bendeivide.github.io/books/eambr01/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;R básico&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;A linguagem R instalada:
&lt;ul&gt;
&lt;li&gt;Pacote &lt;a href=&#34;https://devtools.r-lib.org/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;devtools&lt;/a&gt; e &lt;a href=&#34;https://usethis.r-lib.org/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;usethis&lt;/a&gt; (Kit de ferramentas)&lt;/li&gt;
&lt;li&gt;Pacote &lt;a href=&#34;https://roxygen2.r-lib.org/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;roxygen2&lt;/a&gt; (Documentação R);&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;RStudio (Opcional) &lt;a href=&#34;https://rstudio.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://rstudio.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Rtools (Windows) &lt;a href=&#34;https://cran.r-project.org/bin/windows/Rtools/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://cran.r-project.org/bin/windows/Rtools/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;\(\LaTeX\)&lt;/code&gt; &lt;a href=&#34;https://miktex.org/download&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://miktex.org/download&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Alternativa: instalar o pacote &lt;a href=&#34;https://yihui.org/tinytex/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;tinytex&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;hardcover.png&#34;
  &gt;

&lt;h3 id=&#34;conhecendo-a-estrutura-básica-de-um-pacote&#34;&gt;Conhecendo a estrutura básica de um pacote&lt;/h3&gt;
&lt;img src=&#34;est_pacote01.png&#34; width=&#34;40%&#34; height=&#34;70%&#34; style=&#34;display: block; margin: auto;&#34; /&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;hardcover.png&#34;
  &gt;

&lt;h3 id=&#34;criando-um-pacote-com-o-rstudio&#34;&gt;Criando um pacote com o RStudio&lt;/h3&gt;
&lt;iframe width=&#34;660&#34; height=&#34;415&#34; src=&#34;https://www.youtube.com/embed/aq4OL8IDRJ0&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;hardcover.png&#34;
  &gt;

&lt;section&gt;
&lt;h2&gt;aritmetica.R &lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;# Operacoes basicas da matematica
aritmetica &amp;lt;- function (a, b, op) {
           # op: divisi, multi, soma, subtra
           if (op == &amp;quot;divisi&amp;quot;) x &amp;lt;- divisi(a, b)
           if (op == &amp;quot;multi&amp;quot;) x &amp;lt;- multi(a,b)
           if (op == &amp;quot;soma&amp;quot;) x &amp;lt;- soma(a,b)
           if (op == &amp;quot;subtra&amp;quot;) x &amp;lt;- subtra(a,b)
           return(x)
         }
&lt;/code&gt;&lt;/pre&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;auxiliar.R &lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;soma &amp;lt;- function (a, b) { # Soma
          calculo &amp;lt;- a + b
          return(calculo)}
subtra &amp;lt;- function (a, b) { #Subtracao
            calculo &amp;lt;- a - b
            return(calculo)}
multi &amp;lt;- function (a, b) { # Multiplicacao
           calculo &amp;lt;- a * b
           return(calculo)}
divisi &amp;lt;- function (a, b) { # Divisao
            calculo &amp;lt;- a / b
            return(calculo)}
&lt;/code&gt;&lt;/pre&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;hardcover.png&#34;
  &gt;

&lt;h3 id=&#34;local-para-inserir-aritmeticar-e-auxiliarr&#34;&gt;Local para inserir &lt;code&gt;aritmetica.R&lt;/code&gt; e &lt;code&gt;auxiliar.R&lt;/code&gt;&lt;/h3&gt;
&lt;img src=&#34;est_pacote02.png&#34; width=&#34;40%&#34; height=&#34;70%&#34; style=&#34;display: block; margin: auto;&#34; /&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;hardcover.png&#34;
  &gt;

&lt;section&gt;
&lt;h2&gt;Editando o DESCRIPTION&lt;/h2&gt;
&lt;img src=&#34;est_pacote03.png&#34; width=&#34;40%&#34; height=&#34;70%&#34; style=&#34;display: block; margin: auto;&#34; /&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Arquivo DESCRIPTION&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-{}&#34;&gt;Package: meupacoter
Type: Package
Title: Funcoes Aritmeticas Basicas
Version: 1.0
Date: 2022-11-18
Author: Ben Deivide
Maintainer: Ben Deivide &amp;lt;ben.deivide@ufsj.edu.br&amp;gt;
Description: Este pacote realiza operacoes aritmeticas basicas utilizando dois numeros.
License: GPL (&amp;gt;= 2)
Encoding: UTF-8
RoxygenNote: 7.1.2
&lt;/code&gt;&lt;/pre&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;hardcover.png&#34;
  &gt;

&lt;section&gt;
&lt;h2&gt;Editando o NAMESPACE&lt;/h2&gt;
&lt;img src=&#34;est_pacote04.png&#34; width=&#34;40%&#34; height=&#34;70%&#34; style=&#34;display: block; margin: auto;&#34; /&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Arquivo NAMESPACE&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-{}&#34;&gt;exportPattern(&amp;quot;^[[:alpha:]]+&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt; Importante &lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;O que nós vamos fazer é deletar o arquivo &lt;strong&gt;NAMESPACE&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Vamos deixar para que o pacote &lt;code&gt;roxygen2&lt;/code&gt; gere-o.&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;hardcover.png&#34;
  &gt;

&lt;h2 id=&#34;configurando-o-roxygen2&#34;&gt;Configurando o &lt;code&gt;roxygen2&lt;/code&gt;&lt;/h2&gt;
&lt;iframe width=&#34;560&#34; height=&#34;315&#34; src=&#34;https://www.youtube.com/embed/Nw8ZBlmy3Yw&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;hardcover.png&#34;
  &gt;

&lt;section&gt;
&lt;h2&gt;Criando a documentação básica do pacote&lt;/h2&gt;
&lt;iframe width=&#34;560&#34; height=&#34;315&#34; src=&#34;https://www.youtube.com/embed/YcPRWE6oD1E&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Estrutura da documentação&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-{}&#34;&gt;\name{meupacoter-package}
\alias{meupacoter-package}
\alias{meupacoter}
\docType{package}
\name{aritmetica}
\alias{aritmetica}
\title{Operacoes Matematicas Basicas}
\description{
O pacote resolve operacoes como: soma, subtracao, divisao e multiplicacao.
}
\usage{
aritmetica(a, b, op)
}
\arguments{
\item{a}{primeiro numero}
\item{b}{segundo numero}
\item{op}{operacao matematica}
}
\details{
A função \code{aritmetica} realiza as quatro operacoes basicas. A opcoes para o argumento
\code{op} sao &amp;quot;soma&amp;quot;, &amp;quot;divisi&amp;quot;, &amp;quot;multi&amp;quot;, &amp;quot;subtra&amp;quot;
}
\examples{
aritmetica(8, 4, op = &amp;quot;divisi&amp;quot;)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Usando o roxygen2 em aritmetica.R&lt;/h2&gt;
&lt;img src=&#34;est_pacote05.png&#34; width=&#34;40%&#34; height=&#34;70%&#34; style=&#34;display: block; margin: auto;&#34; /&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Estrutura da documentação pelo roxygen2&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;#&#39; Operacoes Matematicas Basicas
#&#39;
#&#39; \code{aritmetica} resolve operacoes como: soma, subtracao,
#&#39;     divisao e multiplicacao.
#&#39; @param a primeiro numero
#&#39; @param b segundo numero
#&#39; @param op operacao matematica
#&#39; @return A função \code{aritmetica} realiza as quatro operacoes basicas. A opcoes para o argumento
#&#39;     \code{op} sao &amp;quot;soma&amp;quot;, &amp;quot;divisi&amp;quot;, &amp;quot;multi&amp;quot;, &amp;quot;subtra&amp;quot;
#&#39; @examples
#&#39; # Loading package
#&#39; library(meupacoter)
#&#39; aritmetica(8, 4, op = &amp;quot;divisi&amp;quot;)
# @import &amp;quot;nomes de pacotes importados&amp;quot;
# @importFrom &amp;quot;Pacotes&amp;quot; &amp;quot;funcoes&amp;quot;
#&#39; @export
aritmetica &amp;lt;- function (a, b, op) {
           # op: divisi, multi, soma, subtra
           if (op == &amp;quot;divisi&amp;quot;) x &amp;lt;- divisi(a, b)
           if (op == &amp;quot;multi&amp;quot;) x &amp;lt;- multi(a,b)
           if (op == &amp;quot;soma&amp;quot;) x &amp;lt;- soma(a,b)
           if (op == &amp;quot;subtra&amp;quot;) x &amp;lt;- subtra(a,b)
           return(x)}
&lt;/code&gt;&lt;/pre&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;hardcover.png&#34;
  &gt;

&lt;h3 id=&#34;organizando-os-arquivos&#34;&gt;Organizando os arquivos&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Antes de compilarmos o pacote, vamos excluir o arquivo &lt;strong&gt;NAMESPACE&lt;/strong&gt;, e todos os arquivos &lt;strong&gt;./Man/~.Rd&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;O diretório do pacote ficará assim:&lt;/li&gt;
&lt;/ul&gt;
&lt;img src=&#34;est_pacote06.png&#34; width=&#34;40%&#34; height=&#34;70%&#34; style=&#34;display: block; margin: auto;&#34; /&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;hardcover.png&#34;
  &gt;

&lt;h3 id=&#34;atualizando-o-pacote-com-o-roxigen2&#34;&gt;Atualizando o pacote com o &lt;code&gt;roxigen2&lt;/code&gt;&lt;/h3&gt;
&lt;iframe width=&#34;560&#34; height=&#34;315&#34; src=&#34;https://www.youtube.com/embed/c7C9nSCGoPQ&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;hardcover.png&#34;
  &gt;

&lt;h3 id=&#34;checando-o-pacote&#34;&gt;Checando o pacote&lt;/h3&gt;
&lt;iframe width=&#34;560&#34; height=&#34;315&#34; src=&#34;https://www.youtube.com/embed/pv98iNiOgqg&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;hardcover.png&#34;
  &gt;

&lt;h3 id=&#34;submetendo-ao-cran&#34;&gt;Submetendo ao CRAN&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://cran.r-project.org/submit.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://cran.r-project.org/submit.html&lt;/a&gt;&lt;/p&gt;
&lt;iframe width=&#34;560&#34; height=&#34;315&#34; src=&#34;https://www.youtube.com/embed/ou20KCmxSZ0&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;hardcover.png&#34;
  &gt;

&lt;h1 id=&#34;obrigado&#34;&gt;Obrigado!&lt;/h1&gt;
&lt;p&gt;Sugestões, perguntas, críticas&amp;hellip;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Estatística Computacional</title>
      <link>http://bendeivide.github.io/slides/ceac/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/ceac/</guid>
      <description>
&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;ceac.png&#34;
  &gt;

&lt;h1 id=&#34;heading&#34;&gt;&lt;/h1&gt;
&lt;/br&gt;
&lt;/br&gt;
&lt;/br&gt;
&lt;/br&gt;
&lt;/br&gt;
&lt;/br&gt;
&lt;/br&gt;
&lt;/br&gt;
&lt;/br&gt;
&lt;/br&gt;
&lt;/br&gt;
&lt;div align=&#34;right&#34;&gt;
&lt;p&gt;
  &lt;i class=&#34;fab fa-instagram  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;https://www.instagram.com/ceac_ufsj/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;@ceac_ufsj&lt;/a&gt; | 
  &lt;i class=&#34;fas fa-school  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;https://www.ufsj.edu.br/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;UFSJ&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;ceac02.png&#34;
  &gt;

&lt;h2 id=&#34;quem-somos&#34;&gt;Quem somos?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Somos um projeto de Pesquisa, Ensino e Extensão&lt;/li&gt;
&lt;li&gt;Fundado em 2022&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;ceac02.png&#34;
  &gt;

&lt;h2 id=&#34;objetivos&#34;&gt;Objetivos&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Informar e conscientizar sobre uso de ferramentas computacionais&lt;/li&gt;
&lt;li&gt;Difundir o uso dessas ferramentas dentro das disciplinas do CAP&lt;/li&gt;
&lt;li&gt;Trabalhar com problemas práticos&lt;/li&gt;
&lt;li&gt;Experiência das ferramentas computacionais para a inserção no mercado de trabalho&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;ceac02.png&#34;
  &gt;

&lt;h2 id=&#34;membros&#34;&gt;Membros&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Tutores
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;bendeivide.github.io&#34;&gt;Ben Dêivide de O. Batista (DEFIM/UFSJ)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://lattes.cnpq.br/4378950347916839&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Gabriel de Castro Fonseca (DQBIO)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://lattes.cnpq.br/9870727668600291&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Jorge David Alguiar Bellido (DEQUI/UFSJ)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://lattes.cnpq.br/5150012010823776&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Pedro Mitsuo Shiroma (DTECH/UFSJ)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://lattes.cnpq.br/0704312140937009&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Telles Timóteo da Silva (DEFIM/UFSJ)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;ceac02.png&#34;
  &gt;

&lt;h2 id=&#34;membros-1&#34;&gt;Membros&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Alunos
&lt;ul&gt;
&lt;li&gt;Betania Drosdrocky Gonçalves&lt;/li&gt;
&lt;li&gt;Diego Henrique de Souza Lima Duarte&lt;/li&gt;
&lt;li&gt;Gabriel Loureiro Barbosa Aguiar&lt;/li&gt;
&lt;li&gt;Gabriela da Rocha Honorato&lt;/li&gt;
&lt;li&gt;José Osvaldo Maciel da Rocha Júnior&lt;/li&gt;
&lt;li&gt;Laís Braga Silva&lt;/li&gt;
&lt;li&gt;Larissa Emanuelle Lara Silva&lt;/li&gt;
&lt;li&gt;Letícia Lima Alves&lt;/li&gt;
&lt;li&gt;Marcos Gomes Machado&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;ceac02.png&#34;
  &gt;

&lt;h1 id=&#34;questões&#34;&gt;Questões?&lt;/h1&gt;
&lt;p&gt;Dúvidas e Críticas&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.instagram.com/ceac_ufsj/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Contato&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Estatística Computacional</title>
      <link>http://bendeivide.github.io/slides/estcomp/s01/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estcomp/s01/</guid>
      <description>
&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo03.jpg&#34;
  &gt;

&lt;h1 id=&#34;estatística-computacional&#34;&gt;Estatística computacional&lt;/h1&gt;
&lt;p&gt;Aula 01 - Apresentação do curso
&lt;/br&gt;&lt;/p&gt;
&lt;p&gt;
  &lt;i class=&#34;fas fa-user-tie  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;https://bendeivide.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Ben Dêivide&lt;/a&gt; | 
  &lt;i class=&#34;fas fa-school  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;https://www.ufsj.edu.br/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;UFSJ&lt;/a&gt;
&lt;/br&gt;

  &lt;i class=&#34;fas fa-book  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;http://bendeivide.github.io/courses/estcomp/&#34;&gt;Estatística Computacional&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;h2 id=&#34;selo-dc&#34;&gt;Selo DC&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/dc/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/estcomp/s01/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_57f4d021c573f1cdb22f5303fccfacd9.webp 400w,
               /slides/estcomp/s01/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_e3124639f3c96b16d12396d9954194c3.webp 760w,
               /slides/estcomp/s01/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/estcomp/s01/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_57f4d021c573f1cdb22f5303fccfacd9.webp&#34;
               width=&#34;385&#34;
               height=&#34;406&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;section data-background-iframe=&#34;/courses/estcomp&#34; data-background-interactive&gt;
	&lt;div style=&#34;position: absolute; width: 40%; right: 0; box-shadow: 0 1px 4px rgba(0,0,0,0.5), 0 5px 25px rgba(0,0,0,0.2); background-color: rgba(0, 0, 0, 0.9); color: #fff; padding: 20px; font-size: 20px; text-align: left;&#34;&gt;
		&lt;h2&gt;Material do curso&lt;/h2&gt;
		&lt;p&gt;Todo o material será disponível na página &lt;a href=&#34;https://bendeivide.github.io/courses/estcomp/&#34;&gt;Ben Dêivide&lt;/a&gt;.&lt;/p&gt;
	&lt;/div&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;h2 id=&#34;introdução-e-histórico-sobre-o-ambiente-r&#34;&gt;Introdução e histórico sobre o ambiente R&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Criadores Ross Ihaka e por Robert Gentleman (Nova Zelândia), 1993&lt;/li&gt;
&lt;li&gt;Baseado na linguagem S, criado por John Chambers e colaboradores (Primeira versão 1976)&lt;/li&gt;
&lt;li&gt;Atualmente é mantida por colaboradores voluntários em todo o mundo&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;h2 id=&#34;características-sobre-o-r&#34;&gt;Características sobre o R&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Linguagem pode ser orientada a objetos, Código aberto, funcional, metapragmática, Licença GNU&lt;/li&gt;
&lt;li&gt;Repositório &lt;a href=&#34;https://cran.r-project.org/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;CRAN&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Popularidade com o &lt;a href=&#34;https://rstudio.com/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;RStudio&lt;/a&gt; (Joseph J. Allaire)&lt;/li&gt;
&lt;li&gt;Como instalar o R?&lt;/li&gt;
&lt;li&gt;Como instalar o RStudio?&lt;/li&gt;
&lt;li&gt;Como usar o R?&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;section&gt;
&lt;h2&gt; Cursos e Playlists &lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/courses/cursor/nbasico/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;













&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/estcomp/s01/cursor-nb_hu8cbf2d1b9b5244f1524037e4474c538e_69900_4b297cb8f0e33e442ebf99b215388034.webp 400w,
               /slides/estcomp/s01/cursor-nb_hu8cbf2d1b9b5244f1524037e4474c538e_69900_f138ba75b6cb4eb62d1ecea4bcae0172.webp 760w,
               /slides/estcomp/s01/cursor-nb_hu8cbf2d1b9b5244f1524037e4474c538e_69900_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/estcomp/s01/cursor-nb_hu8cbf2d1b9b5244f1524037e4474c538e_69900_4b297cb8f0e33e442ebf99b215388034.webp&#34;
               width=&#34;350&#34;
               height=&#34;350&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/post/cursorni2/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;Nível Intermediário&#34; srcset=&#34;
               /slides/estcomp/s01/cursor-ni_hua909e2f7dc5b7deac580280a2231351e_70067_01ee0fc5dca62b5827c4744b677401e2.webp 400w,
               /slides/estcomp/s01/cursor-ni_hua909e2f7dc5b7deac580280a2231351e_70067_2be287ff636a8ea73ce5b5354154f128.webp 760w,
               /slides/estcomp/s01/cursor-ni_hua909e2f7dc5b7deac580280a2231351e_70067_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/estcomp/s01/cursor-ni_hua909e2f7dc5b7deac580280a2231351e_70067_01ee0fc5dca62b5827c4744b677401e2.webp&#34;
               width=&#34;593&#34;
               height=&#34;579&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/project/rapidinhasr/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/estcomp/s01/rapidinhasr_huf4c584a0ea803c0b4fded9f2abc27f53_510973_df46483f285db6db6d908bc356b06e75.webp 400w,
               /slides/estcomp/s01/rapidinhasr_huf4c584a0ea803c0b4fded9f2abc27f53_510973_db647e21fc70a6855b86924338dcb47a.webp 760w,
               /slides/estcomp/s01/rapidinhasr_huf4c584a0ea803c0b4fded9f2abc27f53_510973_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/estcomp/s01/rapidinhasr_huf4c584a0ea803c0b4fded9f2abc27f53_510973_df46483f285db6db6d908bc356b06e75.webp&#34;
               width=&#34;760&#34;
               height=&#34;374&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section data-background-video=&#34;est&amp;prob.mp4&#34; data-background-color=&#34;#000000&#34;&gt;
&lt;div style=&#34;background-color: rgba(0, 0, 0, 0.9); color: #fff; padding: 20px;&#34;&gt;
&lt;h2&gt;Playlist de Estatística e Probabilidade&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://www.youtube.com/playlist?list=PL-20Z1XFWKR2GatfNSFOwfRvPreZ-nW0D&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;
  &lt;i class=&#34;fab fa-youtube  pr-1 fa-fw&#34;&gt;&lt;/i&gt; youtube/bendeivide&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;section&gt;
&lt;h2&gt; Coleção Estudando o Ambiente R &lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/book-eambr01&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;













&lt;figure  id=&#34;figure-volume-i&#34;&gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;Volume I&#34; srcset=&#34;
               /slides/estcomp/s01/hardcover01_hu6fd2f9a5af792bfbcb973270ac465a56_130113_f7ee7ac1bcb38885ed43ff6283f91281.webp 400w,
               /slides/estcomp/s01/hardcover01_hu6fd2f9a5af792bfbcb973270ac465a56_130113_f8257eabb142099dedb529c07f030721.webp 760w,
               /slides/estcomp/s01/hardcover01_hu6fd2f9a5af792bfbcb973270ac465a56_130113_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/estcomp/s01/hardcover01_hu6fd2f9a5af792bfbcb973270ac465a56_130113_f7ee7ac1bcb38885ed43ff6283f91281.webp&#34;
               width=&#34;248&#34;
               height=&#34;351&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      Volume I
    &lt;/figcaption&gt;&lt;/figure&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;section&gt;














&lt;figure  id=&#34;figure-volume-ii&#34;&gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;Volume II&#34; srcset=&#34;
               /slides/estcomp/s01/hardcover02_hu6fd2f9a5af792bfbcb973270ac465a56_140122_45f619095959daf2295f20cedc96666e.webp 400w,
               /slides/estcomp/s01/hardcover02_hu6fd2f9a5af792bfbcb973270ac465a56_140122_bf2cc9d0d398d7bc6c1078f0736f1b29.webp 760w,
               /slides/estcomp/s01/hardcover02_hu6fd2f9a5af792bfbcb973270ac465a56_140122_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/estcomp/s01/hardcover02_hu6fd2f9a5af792bfbcb973270ac465a56_140122_45f619095959daf2295f20cedc96666e.webp&#34;
               width=&#34;248&#34;
               height=&#34;351&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      Volume II
    &lt;/figcaption&gt;&lt;/figure&gt;
&lt;/section&gt;
&lt;section&gt;














&lt;figure  id=&#34;figure-volume-iii&#34;&gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;Volume III&#34; srcset=&#34;
               /slides/estcomp/s01/hardcover03_hu6fd2f9a5af792bfbcb973270ac465a56_132421_5d2480d8e0e7c78bda916b4e31c58e8b.webp 400w,
               /slides/estcomp/s01/hardcover03_hu6fd2f9a5af792bfbcb973270ac465a56_132421_2a3fcd56ea738f0fa720cfa8ecc1caf6.webp 760w,
               /slides/estcomp/s01/hardcover03_hu6fd2f9a5af792bfbcb973270ac465a56_132421_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/estcomp/s01/hardcover03_hu6fd2f9a5af792bfbcb973270ac465a56_132421_5d2480d8e0e7c78bda916b4e31c58e8b.webp&#34;
               width=&#34;248&#34;
               height=&#34;351&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      Volume III
    &lt;/figcaption&gt;&lt;/figure&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;h1 id=&#34;questões&#34;&gt;Questões?&lt;/h1&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Dúvidas e Sugestões&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/#contact&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Contato&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;!-- https://revealjs.com/transitions/ --&gt;
&lt;section data-transition=&#34;zoom&#34;&gt;
  &lt;h1&gt;Próximas aulas...&lt;/h1&gt;
&lt;/section&gt;
&lt;section data-transition-speed=&#34;fast&#34;&gt;
&lt;p&gt;&lt;a href=&#34;http://bendeivide.github.io/courses/estcomp&#34;&gt;













&lt;figure  id=&#34;figure-bendeividegithubio&#34;&gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;bendeivide.github.io&#34; srcset=&#34;
               /slides/estcomp/s01/ben06_hu5bea5166adf08203812bfc1c9ed6c2df_379949_62d825484a795f0ad2a5c47f01253c0d.webp 400w,
               /slides/estcomp/s01/ben06_hu5bea5166adf08203812bfc1c9ed6c2df_379949_0c491b4ea3521509bc21790317b4794e.webp 760w,
               /slides/estcomp/s01/ben06_hu5bea5166adf08203812bfc1c9ed6c2df_379949_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/estcomp/s01/ben06_hu5bea5166adf08203812bfc1c9ed6c2df_379949_62d825484a795f0ad2a5c47f01253c0d.webp&#34;
               width=&#34;630&#34;
               height=&#34;480&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      bendeivide.github.io
    &lt;/figcaption&gt;&lt;/figure&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;!-- &lt;section&gt; --&gt;
&lt;!--   &lt;h2&gt;Some Slide&lt;/h2&gt; --&gt;
&lt;!--   &lt;aside class=&#34;notes&#34;&gt; --&gt;
&lt;!--     Anotações no Visualizador (Clique em S) 📝 --&gt;
&lt;!--   &lt;/aside&gt; --&gt;
&lt;!-- &lt;/section&gt; --&gt;
&lt;!-- ## Animação --&gt;
&lt;!-- &lt;section data-auto-animate&gt; --&gt;
&lt;!--   &lt;h1&gt;Auto-Animate&lt;/h1&gt; --&gt;
&lt;!-- &lt;/section&gt; --&gt;
&lt;!-- &lt;section data-auto-animate&gt; --&gt;
&lt;!--   &lt;h1 style=&#34;margin-top: 100px; color: red;&#34;&gt;Auto-Animate&lt;/h1&gt; --&gt;
&lt;!-- &lt;/section&gt; --&gt;
</description>
    </item>
    
    <item>
      <title>Estatística Computacional</title>
      <link>http://bendeivide.github.io/slides/estcomp/s02/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estcomp/s02/</guid>
      <description>
&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo03.jpg&#34;
  &gt;

&lt;h1 id=&#34;estatística-computacional&#34;&gt;Estatística Computacional&lt;/h1&gt;
&lt;p&gt;Aula 02 - Introdução ao ambiente R
&lt;/br&gt;&lt;/p&gt;
&lt;p&gt;
  &lt;i class=&#34;fas fa-user-tie  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;https://bendeivide.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Ben Dêivide&lt;/a&gt; | 
  &lt;i class=&#34;fas fa-school  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;https://www.ufsj.edu.br/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;UFSJ&lt;/a&gt;
&lt;/br&gt;

  &lt;i class=&#34;fas fa-book  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;http://bendeivide.github.io/courses/estcomp/&#34;&gt;Estatística Computacional&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;h2 id=&#34;selo-dc&#34;&gt;Selo DC&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/dc/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/estcomp/s02/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_57f4d021c573f1cdb22f5303fccfacd9.webp 400w,
               /slides/estcomp/s02/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_e3124639f3c96b16d12396d9954194c3.webp 760w,
               /slides/estcomp/s02/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/estcomp/s02/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_57f4d021c573f1cdb22f5303fccfacd9.webp&#34;
               width=&#34;385&#34;
               height=&#34;406&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;h2 id=&#34;acesso-a-todo-material&#34;&gt;Acesso a todo material&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;http://bendeivide.github.io/courses/estcomp/&#34;&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/estcomp/s02/folder_hu84ae0d30d5154d1e73aaf9945c348d03_20466_620e1c48e451842e2f4135b7117821ad.webp 400w,
               /slides/estcomp/s02/folder_hu84ae0d30d5154d1e73aaf9945c348d03_20466_81e4eb609876936d8a5e708f395fd9b9.webp 760w,
               /slides/estcomp/s02/folder_hu84ae0d30d5154d1e73aaf9945c348d03_20466_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/estcomp/s02/folder_hu84ae0d30d5154d1e73aaf9945c348d03_20466_620e1c48e451842e2f4135b7117821ad.webp&#34;
               width=&#34;607&#34;
               height=&#34;471&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;h2 id=&#34;instalação-do-r-e-rstudio&#34;&gt;Instalação do R e RStudio&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://bendeivide.github.io/cursor/#so-windows&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;SO Win&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://bendeivide.github.io/cursor/#so-linux-ubuntu&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;SO UNIX&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://bendeivide.github.io/cursor/#so-mac&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;SO MAC&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;!-- https://revealjs.com/transitions/ --&gt;
&lt;section data-transition=&#34;zoom&#34;&gt;
  &lt;h2&gt;Diferença entre o R e RStudio&lt;/h2&gt;
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  &lt;figure  &gt;
    &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
      &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
                 /slides/estcomp/s02/promptr_hu69ee0da2f97395ac428921f37b80459a_472001_9b85968bc29f885dace2270c24039079.webp 400w,
                 /slides/estcomp/s02/promptr_hu69ee0da2f97395ac428921f37b80459a_472001_6bda6b5a62566d76d4072feffbfb2d62.webp 760w,
                 /slides/estcomp/s02/promptr_hu69ee0da2f97395ac428921f37b80459a_472001_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
                 src=&#34;http://bendeivide.github.io/slides/estcomp/s02/promptr_hu69ee0da2f97395ac428921f37b80459a_472001_9b85968bc29f885dace2270c24039079.webp&#34;
                 width=&#34;730&#34;
                 height=&#34;380&#34;
                 loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
    &lt;/div&gt;&lt;/figure&gt;
&lt;/section&gt;
&lt;section data-transition-speed=&#34;fast&#34;&gt;
&lt;h2&gt;Diferença entre o R e RStudio&lt;/h2&gt;














&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/estcomp/s02/ide_rstudio_huab3737ec9cc2208441583b4930800e4d_307696_331fc9d22477f5928f2c04f7579e6c9c.webp 400w,
               /slides/estcomp/s02/ide_rstudio_huab3737ec9cc2208441583b4930800e4d_307696_df692b5b51b2b661dd286218b18ebe82.webp 760w,
               /slides/estcomp/s02/ide_rstudio_huab3737ec9cc2208441583b4930800e4d_307696_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/estcomp/s02/ide_rstudio_huab3737ec9cc2208441583b4930800e4d_307696_331fc9d22477f5928f2c04f7579e6c9c.webp&#34;
               width=&#34;730&#34;
               height=&#34;380&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;h2 id=&#34;como-o-r-trabalha&#34;&gt;Como o R trabalha&lt;/h2&gt;














&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/estcomp/s02/rworks_hu2a76007f72e3bedcabac0678f5e95e66_304968_a0d97525785d3775fe573c3d581d2b44.webp 400w,
               /slides/estcomp/s02/rworks_hu2a76007f72e3bedcabac0678f5e95e66_304968_92444b1f46d65a684a309aa5b4156881.webp 760w,
               /slides/estcomp/s02/rworks_hu2a76007f72e3bedcabac0678f5e95e66_304968_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/estcomp/s02/rworks_hu2a76007f72e3bedcabac0678f5e95e66_304968_a0d97525785d3775fe573c3d581d2b44.webp&#34;
               width=&#34;730&#34;
               height=&#34;480&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;section data-auto-animate&gt;
  &lt;h2 data-id=&#34;code-title&#34;&gt;Console e Prompt de comando&lt;/h2&gt;
	&lt;pre data-id=&#34;code-animation&#34;&gt;
	  &lt;code class=&#34;hljs&#34; data-trim data-line-numbers=&#34;|1|2-3&#34;&gt;
	    &lt;script type=&#34;text/template&#34;&gt;
        options(prompt = &#34;R&gt; &#34;)
        # Toda vez que o console iniciar, começarar por &#39;R&gt;&#39;
        10
	    &lt;/script&gt;
	  &lt;/code&gt;
	&lt;/pre&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2 data-id=&#34;code-title&#34;&gt;Resultado da execução&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;R&amp;gt; options(prompt = &amp;quot;R&amp;gt; &amp;quot;)
R&amp;gt; # Toda vez que o console iniciar, começarar por &#39;R&amp;gt;&#39;
R&amp;gt; 10
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 10
&lt;/code&gt;&lt;/pre&gt;
&lt;/section&gt;
&lt;hr&gt;
&lt;section&gt;
&lt;h2&gt; Comandos elementares &lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;10 + 15
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 25
&lt;/code&gt;&lt;/pre&gt;
&lt;/br&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;10,5 + 15,5
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## Error: &amp;lt;text&amp;gt;:1:3: &#39;,&#39; inesperado
## 1: 10,
##       ^
&lt;/code&gt;&lt;/pre&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt; Comandos elementares &lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;# Foi criado um objeto do tipo caractere e o nome &amp;quot;meu_nome&amp;quot; foi associado a ele
# O &#39;R&#39; avalia essa expressão, mas não imprime no console!
meu_nome &amp;lt;- &amp;quot;Ben&amp;quot;

# Para imprimir o resultado da expressão, digitamos o nome &amp;quot;meu_nome&amp;quot; no console
# e apertamos o botão ENTER do teclado!
meu_nome
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;Ben&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt; Nomes e objetos &lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Deve consistir em letras, dígitos, &lt;code&gt;.&lt;/code&gt; e &lt;code&gt;_&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Os nomes devem ser iniciado por uma letra ou um ponto não seguido de um número, isto é, Ex.: &lt;code&gt;.123&lt;/code&gt;, &lt;code&gt;1n&lt;/code&gt;, dentre outros;&lt;/li&gt;
&lt;li&gt;As letras maiúsculas se distinguem das letras minúsculas;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;ul&gt;
&lt;li&gt;Não pode inicia por &lt;code&gt;_&lt;/code&gt; ou dígito, é retornado um erro no console caso isso ocorra;&lt;/li&gt;
&lt;li&gt;Não pode usar qualquer uma das palavras reservadas pela linguagem, isto é, &lt;code&gt;TRUE&lt;/code&gt;, &lt;code&gt;FALSE&lt;/code&gt;, &lt;code&gt;if&lt;/code&gt;, &lt;code&gt;for&lt;/code&gt;, dentre outras, que pode ser consultado usando o comando &lt;code&gt;?Reserved()&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt; Nomes não sintáticos  &lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;# Nome nao sintatico
.123 &amp;lt;- 50
## Error in 0.123 &amp;lt;- 50 : lado esquerdo da atribuicao inválida (do_set)

# Qual a sugestao de nome sintatico para &#39;.123&#39;?
make.names(.123)
[1] &amp;quot;X0.123&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;/section&gt;
&lt;hr&gt;
&lt;section&gt;
&lt;h2&gt; Correção de comandos no R &lt;/h2&gt;
&lt;iframe width=&#34;560&#34; height=&#34;315&#34; src=&#34;https://www.youtube.com/embed/0MRPmVsPvk4&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt; Correção de comandos no RStudio &lt;/h2&gt;
&lt;iframe width=&#34;560&#34; height=&#34;315&#34; src=&#34;https://www.youtube.com/embed/KL3WAB_GFNI&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;section data-auto-animate&gt;
  &lt;h2 data-id=&#34;code-title&#34;&gt;Ambiente global&lt;/h2&gt;
	&lt;pre data-id=&#34;code-animation&#34;&gt;
	  &lt;code class=&#34;hljs&#34; data-trim data-line-numbers=&#34;|4&#34;&gt;
	    &lt;script type=&#34;text/template&#34;&gt;
       # Nomes criados no ambiente 
       x &lt;- 10 - 6; y &lt;- 10 + 4; w &lt;- &#34;Maria Isabel&#34;
       # Verificando o nomes contidos no ambiente global
       ls()
	    &lt;/script&gt;
	  &lt;/code&gt;
	&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;meu_nome&amp;quot; &amp;quot;w&amp;quot;        &amp;quot;x&amp;quot;        &amp;quot;y&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;h2 id=&#34;criando-e-salvando-um-script&#34;&gt;Criando e salvando um script&lt;/h2&gt;
&lt;iframe width=&#34;560&#34; height=&#34;315&#34; src=&#34;https://www.youtube.com/embed/ETreeG5HK60&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;hr&gt;
&lt;section&gt;
&lt;h2&gt; Objetos &lt;/h2&gt;
&lt;iframe width=&#34;560&#34; height=&#34;315&#34; src=&#34;https://www.youtube.com/embed/6t9h9zgWyTE&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;/section&gt;
&lt;section data-auto-animate&gt;
&lt;h2&gt; Entendimento dos nomes e objetos &lt;/h2&gt;
	&lt;pre data-id=&#34;code-animation&#34;&gt;
	  &lt;code class=&#34;hljs&#34; data-trim data-line-numbers=&#34;|2;5|3;6&#34;&gt;
	    &lt;script type=&#34;text/template&#34;&gt;
       x &lt;- 10
       lobstr::obj_addr(x)
       ## [1] &#34;0xf8a104fc20&#34;
       y &lt;- x
       lobstr::obj_addr(y)
       ## [1] &#34;0xf8a104fc20&#34;
	    &lt;/script&gt;
	  &lt;/code&gt;
	&lt;/pre&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt; Ilustração &lt;/h2&gt;














&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/estcomp/s02/y=x=10_hud064575b8f0af6084abdce16d604d280_35386_68692ec504b290b034f8c838fb8db20a.webp 400w,
               /slides/estcomp/s02/y=x=10_hud064575b8f0af6084abdce16d604d280_35386_15c6873244455d4c68831bc1ac435847.webp 760w,
               /slides/estcomp/s02/y=x=10_hud064575b8f0af6084abdce16d604d280_35386_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/estcomp/s02/y=x=10_hud064575b8f0af6084abdce16d604d280_35386_68692ec504b290b034f8c838fb8db20a.webp&#34;
               width=&#34;730&#34;
               height=&#34;380&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt; Objeto e Ambiente &lt;/h2&gt;














&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/estcomp/s02/objamb_hu90f54417d64275fdfd02177500a3edb8_84634_8708be3b7e9712bbc8c049d901b3c1d9.webp 400w,
               /slides/estcomp/s02/objamb_hu90f54417d64275fdfd02177500a3edb8_84634_1d82851f0dcb635bd55f6ee452d5eee4.webp 760w,
               /slides/estcomp/s02/objamb_hu90f54417d64275fdfd02177500a3edb8_84634_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/estcomp/s02/objamb_hu90f54417d64275fdfd02177500a3edb8_84634_8708be3b7e9712bbc8c049d901b3c1d9.webp&#34;
               width=&#34;730&#34;
               height=&#34;380&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt; Para um melhor entendimento sobre objetos &lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/cursor/nbasico#objetos&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://bendeivide.github.io/cursor/nbasico#objetos&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;hr&gt;
&lt;section&gt;
&lt;h2&gt; Importação de dados &lt;/h2&gt;
&lt;h3&gt; Importação de dados &lt;/h3&gt;














&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/estcomp/s02/banco_dados_huc3819529db37800b78a02d8eb7eb8279_171453_6ed62b943083b71130db9eee71cf9a53.webp 400w,
               /slides/estcomp/s02/banco_dados_huc3819529db37800b78a02d8eb7eb8279_171453_f8ddce6cd5fa1c36ecd612e3880a7e65.webp 760w,
               /slides/estcomp/s02/banco_dados_huc3819529db37800b78a02d8eb7eb8279_171453_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/estcomp/s02/banco_dados_huc3819529db37800b78a02d8eb7eb8279_171453_6ed62b943083b71130db9eee71cf9a53.webp&#34;
               width=&#34;730&#34;
               height=&#34;380&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h3&gt; Importação com o RStudio &lt;/h3&gt;














&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/estcomp/s02/imp-exp_hu77bdd3ae559bd0d5cfe81de54a95d707_438684_a040797377408cd5f5cb4680ad72ee9d.webp 400w,
               /slides/estcomp/s02/imp-exp_hu77bdd3ae559bd0d5cfe81de54a95d707_438684_eb481cfe9ee854986d2e2b1712450d6c.webp 760w,
               /slides/estcomp/s02/imp-exp_hu77bdd3ae559bd0d5cfe81de54a95d707_438684_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/estcomp/s02/imp-exp_hu77bdd3ae559bd0d5cfe81de54a95d707_438684_a040797377408cd5f5cb4680ad72ee9d.webp&#34;
               width=&#34;730&#34;
               height=&#34;380&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h3&gt; Importação com o RStudio &lt;/h3&gt;














&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/estcomp/s02/imp-exp2_hu98cf4e8ee59ff1990f444d22eaedaa94_816623_9112b4b050690be0f1170246382acae5.webp 400w,
               /slides/estcomp/s02/imp-exp2_hu98cf4e8ee59ff1990f444d22eaedaa94_816623_2b164ee7821541ca701386d6c25cf91f.webp 760w,
               /slides/estcomp/s02/imp-exp2_hu98cf4e8ee59ff1990f444d22eaedaa94_816623_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/estcomp/s02/imp-exp2_hu98cf4e8ee59ff1990f444d22eaedaa94_816623_9112b4b050690be0f1170246382acae5.webp&#34;
               width=&#34;730&#34;
               height=&#34;380&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h3&gt; Importação com o RStudio &lt;/h3&gt;














&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/estcomp/s02/imp-exp3_hub4dbf8caff413c56bff8d7d281046b85_563394_9ad9f2e3db95c6a2548cca980f103654.webp 400w,
               /slides/estcomp/s02/imp-exp3_hub4dbf8caff413c56bff8d7d281046b85_563394_f1dd18c67163caaecd156f9965d6727b.webp 760w,
               /slides/estcomp/s02/imp-exp3_hub4dbf8caff413c56bff8d7d281046b85_563394_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/estcomp/s02/imp-exp3_hub4dbf8caff413c56bff8d7d281046b85_563394_9ad9f2e3db95c6a2548cca980f103654.webp&#34;
               width=&#34;730&#34;
               height=&#34;380&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h3&gt; Importação com o RStudio &lt;/h3&gt;














&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/estcomp/s02/imp-exp4_hu996357d7207e85348fa9b50d37d1005a_661087_3b1f8b64bcf282599109480b14ea8d0e.webp 400w,
               /slides/estcomp/s02/imp-exp4_hu996357d7207e85348fa9b50d37d1005a_661087_5a34179815719ac31b3467f7cbdf9cac.webp 760w,
               /slides/estcomp/s02/imp-exp4_hu996357d7207e85348fa9b50d37d1005a_661087_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/estcomp/s02/imp-exp4_hu996357d7207e85348fa9b50d37d1005a_661087_3b1f8b64bcf282599109480b14ea8d0e.webp&#34;
               width=&#34;730&#34;
               height=&#34;380&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;h1 id=&#34;questões&#34;&gt;Questões?&lt;/h1&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Dúvidas e Sugestões&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/#contact&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Contato&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Estatística Computacional</title>
      <link>http://bendeivide.github.io/slides/estcomp/s03/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estcomp/s03/</guid>
      <description>
&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo03.jpg&#34;
  &gt;

&lt;h1 id=&#34;estatística-computacional&#34;&gt;Estatística Computacional&lt;/h1&gt;
&lt;p&gt;Aula 03 - Objetos em R
&lt;/br&gt;&lt;/p&gt;
&lt;p&gt;
  &lt;i class=&#34;fas fa-user-tie  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;https://bendeivide.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Ben Dêivide&lt;/a&gt; | 
  &lt;i class=&#34;fas fa-school  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;https://www.ufsj.edu.br/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;UFSJ&lt;/a&gt;
&lt;/br&gt;

  &lt;i class=&#34;fas fa-book  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;http://bendeivide.github.io/courses/estcomp/&#34;&gt;Estatística Computacional&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;h2 id=&#34;selo-dc&#34;&gt;Selo DC&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/dc/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/estcomp/s03/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_57f4d021c573f1cdb22f5303fccfacd9.webp 400w,
               /slides/estcomp/s03/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_e3124639f3c96b16d12396d9954194c3.webp 760w,
               /slides/estcomp/s03/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/estcomp/s03/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_57f4d021c573f1cdb22f5303fccfacd9.webp&#34;
               width=&#34;385&#34;
               height=&#34;406&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;h2 id=&#34;acesso-a-todo-material&#34;&gt;Acesso a todo material&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;http://bendeivide.github.io/courses/estcomp/&#34;&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/estcomp/s03/folder_hu84ae0d30d5154d1e73aaf9945c348d03_20466_620e1c48e451842e2f4135b7117821ad.webp 400w,
               /slides/estcomp/s03/folder_hu84ae0d30d5154d1e73aaf9945c348d03_20466_81e4eb609876936d8a5e708f395fd9b9.webp 760w,
               /slides/estcomp/s03/folder_hu84ae0d30d5154d1e73aaf9945c348d03_20466_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/estcomp/s03/folder_hu84ae0d30d5154d1e73aaf9945c348d03_20466_620e1c48e451842e2f4135b7117821ad.webp&#34;
               width=&#34;607&#34;
               height=&#34;471&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;h2 id=&#34;introdução&#34;&gt;Introdução&lt;/h2&gt;
&lt;p&gt;John Chambers (Criador da linguagem S) afirma:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Princípio do Objeto&lt;/strong&gt;: Tudo que existe em &lt;code&gt;R&lt;/code&gt; é um objeto&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Definimos um objeto como uma entidade no ambiente &lt;code&gt;R&lt;/code&gt; com características internas contendo informações necessárias para interpretar sua estrutura e conteúdo
&lt;ul&gt;
&lt;li&gt;Atributos&lt;/li&gt;
&lt;li&gt;Atributos intrínsecos: &lt;strong&gt;modo&lt;/strong&gt; e &lt;strong&gt;comprimento&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;h2 id=&#34;associando-o-nome-a-um-objeto&#34;&gt;Associando o nome a um objeto&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;&amp;gt; x &amp;lt;- 10
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Comandos de atribuição&lt;/li&gt;
&lt;li&gt;Use: &lt;code&gt;&amp;lt;-&lt;/code&gt;, isto é, &lt;code&gt;&amp;lt;&lt;/code&gt; + &lt;code&gt;-&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Evite: &lt;code&gt;=&lt;/code&gt;, use apenas para definir argumentos em uma função&lt;/li&gt;
&lt;li&gt;Nomes sintáticos e nomes não sintáticos;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;section&gt;
&lt;h2&gt;Nomes sintáticos e não sintáticos&lt;/h2&gt;
&lt;ul&gt;
&lt;li class=&#34;fragment&#34; data-fragment-index=&#34;3&#34;&gt;
&lt;p&gt;Deve consistir em letras, dígitos, &lt;code&gt;.&lt;/code&gt; e &lt;code&gt;_&lt;/code&gt; ;&lt;/p&gt;
&lt;/li&gt;
&lt;li class=&#34;fragment&#34; data-fragment-index=&#34;1&#34;&gt;
&lt;p&gt;Os nomes devem ser iniciado por uma letra ou um ponto não seguido de um número, Ex.: &lt;code&gt;.123&lt;/code&gt;;&lt;/p&gt;
&lt;/li&gt;
&lt;li class=&#34;fragment&#34; data-fragment-index=&#34;2&#34;&gt;
&lt;p&gt;Letras maiúsculas e minúsculas são diferentes;&lt;/p&gt;
&lt;/li&gt;
&lt;li class=&#34;fragment&#34; data-fragment-index=&#34;5&#34;&gt;
&lt;p&gt;Não pode inicia por &lt;code&gt;_&lt;/code&gt; ou dígito;&lt;/p&gt;
&lt;/li&gt;
&lt;li class=&#34;fragment&#34; data-fragment-index=&#34;4&#34;&gt;
&lt;p&gt;Não pode usar palavras reservadas: &lt;code&gt;?Reserved()&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Nomes sintáticos e não sintáticos&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;# Nome nao sintatico
.123 &amp;lt;- 50
## Error in 0.123 &amp;lt;- 50 : lado esquerdo da atribuicao inválida (do_set)

# Qual a sugestao de nome sintatico para &#39;.123&#39;?
make.names(.123)
[1] &amp;quot;X0.123&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;section&gt;
&lt;h2&gt;Associando um nome ao objeto&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;&amp;gt; x &amp;lt;- 10 # Ou 10 -&amp;gt; x
&lt;/code&gt;&lt;/pre&gt;
&lt;img src=&#34;x=10.png&#34; width=&#34;60%&#34; style=&#34;display: block; margin: auto;&#34; /&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;&amp;gt; lobstr::obj_addr(x)
&amp;gt; # [1] &amp;quot;0xf8a104fc20&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Associando um nome ao objeto&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;&amp;gt; y &amp;lt;- x
&amp;gt; lobstr::obj_addr(y)
&amp;gt; # [1] &amp;quot;0xf8a104fc20&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;img src=&#34;y=x=10.png&#34; width=&#34;60%&#34; style=&#34;display: block; margin: auto;&#34; /&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Associando um nome ao objeto e ambiente global&lt;/h2&gt;
&lt;img src=&#34;objamb.png&#34; width=&#34;60%&#34; style=&#34;display: block; margin: auto;&#34; /&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Associando um nome ao objeto&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;&amp;gt; lobstr::obj_addr(x)
&amp;gt; # [1] &amp;quot;0xf8a104fc20&amp;quot;
&amp;gt; x &amp;lt;- 30
&amp;gt; lobstr::obj_addr(x)
&amp;gt; # [1] &amp;quot;0x42db6dbb50&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;h2 id=&#34;atributos-e-classes&#34;&gt;Atributos e Classes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;atributos intrínsecos:
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;modo&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;mode()&lt;/code&gt; baseado na linguagem &lt;code&gt;S&lt;/code&gt; e&lt;/li&gt;
&lt;li&gt;&lt;code&gt;typeof()&lt;/code&gt; baseado na linguagem &lt;code&gt;C&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;comprimento&lt;/strong&gt;: &lt;code&gt;length()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Demais atributos: &lt;code&gt;attributes()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Classe: &lt;code&gt;class()&lt;/code&gt; e &lt;code&gt;sloop::s3_class()&lt;/code&gt; e atributo classe por &lt;code&gt;attributes()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;section&gt;
&lt;h2&gt;Atributo intrínseco de modo (Vetores)&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;&amp;gt; # Objeto modo caractere
&amp;gt; x &amp;lt;- &amp;quot;Ben&amp;quot;; mode(x)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;character&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;&amp;gt; # Objeto modo logico
&amp;gt; z &amp;lt;- TRUE; mode(z)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;logical&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;&amp;gt; # Objeto modo complexo
&amp;gt; w &amp;lt;- 1i; mode(w)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;complex&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Atributo intrínseco de modo (Vetores)&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;&amp;gt; # Objeto modo numerico
&amp;gt; y &amp;lt;- 10L; mode(y); y2 &amp;lt;- 10; mode(y2)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;numeric&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;numeric&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;&amp;gt; # y eh igual a y2? # y eh identico y2?
&amp;gt; y == y2; identical(y, y2)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] TRUE
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] FALSE
&lt;/code&gt;&lt;/pre&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Atributo intrínseco de modo (Vetores)&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;&amp;gt; # Objeto modo caractere
&amp;gt; x &amp;lt;- &amp;quot;Ben&amp;quot;; typeof(x)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;character&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;&amp;gt; # Objeto modo logico
&amp;gt; z &amp;lt;- TRUE; typeof(z)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;logical&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;&amp;gt; # Objeto modo complexo
&amp;gt; w &amp;lt;- 1i; typeof(w)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;complex&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Atributo intrínseco de modo (Vetores)&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;&amp;gt; # Objeto modo numerico
&amp;gt; y &amp;lt;- 10L; typeof(y); y2 &amp;lt;- 10; typeof(y2)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;integer&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;double&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;&amp;gt; # y eh igual a y2? # y eh identico y2?
&amp;gt; y == y2; identical(y, y2)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] TRUE
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] FALSE
&lt;/code&gt;&lt;/pre&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;h2 id=&#34;resumo-do-modo-em-vetores-atômicos&#34;&gt;Resumo do modo em vetores atômicos&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:center&#34;&gt;&lt;code&gt;typeof&lt;/code&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;&lt;code&gt;mode&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;logical&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;logical&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;integer&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;numeric&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;double&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;numeric&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;complex&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;complex&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;character&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;character&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;raw&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;raw&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;section&gt;
&lt;h2&gt;Comprimento&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;&amp;gt; # Vetor de comprimento 5
&amp;gt; v1 &amp;lt;- 1:5
&amp;gt; # Vetor de comprimento 3
&amp;gt; v2 &amp;lt;- c(&amp;quot;Ben&amp;quot;, &amp;quot;Maria&amp;quot;, &amp;quot;Lana&amp;quot;)
&amp;gt; # Vetor de comprimento quatro
&amp;gt; v3 &amp;lt;- c(TRUE, FALSE, TRUE, TRUE)
&amp;gt; # Vejamos o comprimento dos vetores
&amp;gt; length(v1); length(v2); length(v3)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 5
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 3
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] 4
&lt;/code&gt;&lt;/pre&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Comprimento&lt;/h2&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/estcomp/s03/v1v2v3_huccf721c4a70307ba5fe5e442b4161bdc_260782_0ab2220e12cdb6726c1f0d0db5b82299.webp 400w,
               /slides/estcomp/s03/v1v2v3_huccf721c4a70307ba5fe5e442b4161bdc_260782_e5f12f3f374b191ede089d0d26dbc394.webp 760w,
               /slides/estcomp/s03/v1v2v3_huccf721c4a70307ba5fe5e442b4161bdc_260782_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/estcomp/s03/v1v2v3_huccf721c4a70307ba5fe5e442b4161bdc_260782_0ab2220e12cdb6726c1f0d0db5b82299.webp&#34;
               width=&#34;760&#34;
               height=&#34;265&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;h2 id=&#34;resumo&#34;&gt;Resumo&lt;/h2&gt;
&lt;p&gt;Um resumo as funções mensionadas podem ser refletidas com as seguintes indagações:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;base::class()&lt;/code&gt; e &lt;code&gt;loop::c3_class()&lt;/code&gt;:  Qual o tipo de objeto?&lt;/li&gt;
&lt;li&gt;&lt;code&gt;base::mode()&lt;/code&gt;: Qual o tipo de dados baseados na linguagem &lt;code&gt;S&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;&lt;code&gt;base::typeof()&lt;/code&gt;: Qual o tipo de dados baseados na linguagem &lt;code&gt;C&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;&lt;code&gt;base::attributes()&lt;/code&gt;: O objeto tem atributos?&lt;/li&gt;
&lt;li&gt;&lt;code&gt;base::length()&lt;/code&gt;: Qual o comprimento do objeto?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Sintaxe: &lt;code&gt;pacote::nome_função()&lt;/code&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;h2 id=&#34;classes&#34;&gt;Classes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Objetos que armazenam &amp;ldquo;dados&amp;rdquo;, pensando em análises:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;numeric&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;logical&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;character&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;list&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;matrix&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;array&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;factor&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;data.frame&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;section&gt;
&lt;h2&gt;Coersão do R&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;&amp;gt; # Criando um objeto x e imprimindo o seu resultado
&amp;gt; x &amp;lt;- c(&amp;quot;Nome&amp;quot;, 3, 4, 5);x
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;Nome&amp;quot; &amp;quot;3&amp;quot;    &amp;quot;4&amp;quot;    &amp;quot;5&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;img src=&#34;coersao.png&#34; width=&#34;30%&#34; style=&#34;display: block; margin: auto;&#34; /&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Coersão imposta pelo usuário&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;&amp;gt; # Objeto de modo numerico
&amp;gt; minha_idade &amp;lt;- 35; mode(minha_idade)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;numeric&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;&amp;gt; # Coersão do objeto para modo caractere (`string`)
&amp;gt; minha_idade &amp;lt;- as.character(minha_idade) 
&amp;gt; mode(minha_idade)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;character&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;&amp;gt; # Verificando se o objeto tem modo &#39;character&#39;
&amp;gt; is.character(minha_idade)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] TRUE
&lt;/code&gt;&lt;/pre&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;section&gt;
&lt;h2&gt;Tipo de objetos&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Vetores atômicos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Lógicos, Numéricos e Caracteres;&lt;/li&gt;
&lt;li&gt;Matrizes unidimensionais (&lt;em&gt;Matrix&lt;/em&gt;) e multidimensionais (&lt;em&gt;Arrays&lt;/em&gt;);&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Vetores em listas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Listas (&lt;em&gt;Lists&lt;/em&gt;);&lt;/li&gt;
&lt;li&gt;Quadro de dados (&lt;em&gt;Data frames&lt;/em&gt;);&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Existem outros, mas para esse módulo, exploraremos estes nas seções seguintes&lt;/p&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;h1 id=&#34;questões&#34;&gt;Questões?&lt;/h1&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Dúvidas e Sugestões&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/#contact&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Contato&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Estatística Computacional</title>
      <link>http://bendeivide.github.io/slides/estcomp/s06/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estcomp/s06/</guid>
      <description>
&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo03.jpg&#34;
  &gt;

&lt;h1 id=&#34;estatística-computacional&#34;&gt;Estatística Computacional&lt;/h1&gt;
&lt;p&gt;Aula 06 - Introdução ao Markdown no R
&lt;/br&gt;&lt;/p&gt;
&lt;p&gt;
  &lt;i class=&#34;fas fa-user-tie  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;https://bendeivide.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Ben Dêivide&lt;/a&gt; | 
  &lt;i class=&#34;fas fa-school  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;https://www.ufsj.edu.br/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;UFSJ&lt;/a&gt;
&lt;/br&gt;

  &lt;i class=&#34;fas fa-book  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;http://bendeivide.github.io/courses/estcomp/&#34;&gt;Estatística Computacional&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;h2 id=&#34;selo-dc&#34;&gt;Selo DC&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/dc/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/estcomp/s06/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_57f4d021c573f1cdb22f5303fccfacd9.webp 400w,
               /slides/estcomp/s06/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_e3124639f3c96b16d12396d9954194c3.webp 760w,
               /slides/estcomp/s06/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/estcomp/s06/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_57f4d021c573f1cdb22f5303fccfacd9.webp&#34;
               width=&#34;385&#34;
               height=&#34;406&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;h2 id=&#34;acesso-a-todo-material&#34;&gt;Acesso a todo material&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;http://bendeivide.github.io/courses/estcomp/&#34;&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/estcomp/s06/folder_hu84ae0d30d5154d1e73aaf9945c348d03_20466_620e1c48e451842e2f4135b7117821ad.webp 400w,
               /slides/estcomp/s06/folder_hu84ae0d30d5154d1e73aaf9945c348d03_20466_81e4eb609876936d8a5e708f395fd9b9.webp 760w,
               /slides/estcomp/s06/folder_hu84ae0d30d5154d1e73aaf9945c348d03_20466_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/estcomp/s06/folder_hu84ae0d30d5154d1e73aaf9945c348d03_20466_620e1c48e451842e2f4135b7117821ad.webp&#34;
               width=&#34;607&#34;
               height=&#34;471&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;h2 id=&#34;visão-geral-sobre-o-markdown-e-rmarkdown&#34;&gt;Visão geral sobre o Markdown e RMarkdown&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Markdown: Linguagem de marcação
&lt;ul&gt;
&lt;li&gt;Exemplos de linguagem de marcação: $ \LaTeX $, HTML, XML, etc.&lt;/li&gt;
&lt;li&gt;Objetivo principal: &amp;hellip;&lt;/li&gt;
&lt;li&gt;Criador: John Gruber&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h2 id=&#34;rmarkdown-pacote-r&#34;&gt;RMarkdown: Pacote R&lt;/h2&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;h2 id=&#34;introdução-ao-markdown&#34;&gt;Introdução ao Markdown&lt;/h2&gt;
&lt;h2 id=&#34;criando-seções&#34;&gt;Criando Seções&lt;/h2&gt;
&lt;!-- https://stackoverflow.com/questions/30861845/how-to-use-two-column-layout-with-reveal-js --&gt;
&lt;!-- &lt;style&gt; --&gt;
&lt;!-- .container{ --&gt;
&lt;!--   display: flex; --&gt;
&lt;!-- } --&gt;
&lt;!-- .col { --&gt;
&lt;!--   flex: 1; --&gt;
&lt;!-- } --&gt;
&lt;!-- &lt;/style&gt; --&gt;
&lt;style&gt;
.container{
  display: grid;
  grid-auto-flow: column;
}
&lt;/style&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;pre&gt;&lt;code&gt;# Título 1
## Título 2
### Título 3
#### Título 4
##### Título 5
###### Título 6
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;h1 id=&#34;título-1&#34;&gt;Título 1&lt;/h1&gt;
&lt;h2 id=&#34;título-2&#34;&gt;Título 2&lt;/h2&gt;
&lt;h3 id=&#34;título-3&#34;&gt;Título 3&lt;/h3&gt;
&lt;h4 id=&#34;título-4&#34;&gt;Título 4&lt;/h4&gt;
&lt;h5 id=&#34;título-5&#34;&gt;Título 5&lt;/h5&gt;
&lt;h6 id=&#34;título-6&#34;&gt;Título 6&lt;/h6&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;h2 id=&#34;introdução-ao-rmarkdown&#34;&gt;Introdução ao RMarkdown&lt;/h2&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;h1 id=&#34;questões&#34;&gt;Questões?&lt;/h1&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Dúvidas e Sugestões&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/#contact&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Contato&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Estatística Computacional</title>
      <link>http://bendeivide.github.io/slides/estcomp/s07/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/estcomp/s07/</guid>
      <description>
&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo03.jpg&#34;
  &gt;

&lt;h1 id=&#34;estatística-computacional&#34;&gt;Estatística Computacional&lt;/h1&gt;
&lt;p&gt;Aula 07 - Introdução ao Markdown no R
&lt;/br&gt;&lt;/p&gt;
&lt;p&gt;
  &lt;i class=&#34;fas fa-user-tie  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;https://bendeivide.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Ben Dêivide&lt;/a&gt; | 
  &lt;i class=&#34;fas fa-school  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;https://www.ufsj.edu.br/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;UFSJ&lt;/a&gt;
&lt;/br&gt;

  &lt;i class=&#34;fas fa-book  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;http://bendeivide.github.io/courses/estcomp/&#34;&gt;Estatística Computacional&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;h2 id=&#34;selo-dc&#34;&gt;Selo DC&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/dc/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/estcomp/s07/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_57f4d021c573f1cdb22f5303fccfacd9.webp 400w,
               /slides/estcomp/s07/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_e3124639f3c96b16d12396d9954194c3.webp 760w,
               /slides/estcomp/s07/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/estcomp/s07/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_57f4d021c573f1cdb22f5303fccfacd9.webp&#34;
               width=&#34;385&#34;
               height=&#34;406&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;h2 id=&#34;acesso-a-todo-material&#34;&gt;Acesso a todo material&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;http://bendeivide.github.io/courses/estcomp/&#34;&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/estcomp/s07/folder_hu84ae0d30d5154d1e73aaf9945c348d03_20466_620e1c48e451842e2f4135b7117821ad.webp 400w,
               /slides/estcomp/s07/folder_hu84ae0d30d5154d1e73aaf9945c348d03_20466_81e4eb609876936d8a5e708f395fd9b9.webp 760w,
               /slides/estcomp/s07/folder_hu84ae0d30d5154d1e73aaf9945c348d03_20466_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/estcomp/s07/folder_hu84ae0d30d5154d1e73aaf9945c348d03_20466_620e1c48e451842e2f4135b7117821ad.webp&#34;
               width=&#34;607&#34;
               height=&#34;471&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;section&gt;
&lt;h2&gt; Introdução ao Markdown &lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Markdown é uma ferramenta de conversão de texto para HTML para escritores da web (&lt;a href=&#34;https://daringfireball.net/projects/markdown/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;John Gruber&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Objetivo: &lt;code&gt;Markdown =&amp;gt; HTML&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Criador: &lt;a href=&#34;https://daringfireball.net/projects/markdown/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;John Gruber&lt;/a&gt;, em 2004&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt; Introdução ao Markdown &lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;A ideia do Markdown:
&lt;ul&gt;
&lt;li&gt;Texto de escrita simples&lt;/li&gt;
&lt;li&gt;Ferramenta escrita na linguagem &lt;code&gt;Perl&lt;/code&gt;, que converte o código para &lt;code&gt;HTML&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;extensão do arquivo: &lt;code&gt;.md&lt;/code&gt; ou &lt;code&gt;.markdown&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt; Introdução ao Markdown &lt;/h2&gt;
&lt;p&gt;A ideia da linguagem de marcação é:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Escrito em &lt;code&gt;HTML&lt;/code&gt;:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;p&amp;gt;Este é um parágrafo com uma palavra em &amp;lt;b&amp;gt;negrito&amp;lt;/b&amp;gt; e outra em &amp;lt;i&amp;gt;itálico&amp;lt;/i&amp;gt;.&amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Escrito em &lt;code&gt;Markdown&lt;/code&gt;:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&#34;language-markdown&#34;&gt;Este é um parágrafo com uma palavra em **negrito** e outra em *itálico*.
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Renderização:&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Este é um parágrafo com uma palavra em &lt;strong&gt;negrito&lt;/strong&gt; e outra em &lt;em&gt;itálico&lt;/em&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;style&gt;
.container{
  display: grid;
  text-align: left;
  grid-auto-flow: column;
}
&lt;/style&gt;
&lt;section&gt;
&lt;h1&gt; Sintaxe &lt;/h1&gt;
&lt;hr&gt;
&lt;h2&gt; Criando Seções &lt;/h2&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-markdown&#34;&gt;# Seção 1
## Subseção 1
### Subsubseção 1
#### Subsubsubseção 2
##### ...
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;h1 id=&#34;seção-1&#34;&gt;Seção 1&lt;/h1&gt;
&lt;h2 id=&#34;subseção-1&#34;&gt;Subseção 1&lt;/h2&gt;
&lt;h3 id=&#34;subsubseção-1&#34;&gt;Subsubseção 1&lt;/h3&gt;
&lt;h4 id=&#34;subsubsubseção-2&#34;&gt;Subsubsubseção 2&lt;/h4&gt;
&lt;h5 id=&#34;heading&#34;&gt;&amp;hellip;&lt;/h5&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h2&gt; Outra forma &lt;/h2&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-markdown&#34;&gt;Seção 1
========

Subseção 1
----------
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;h1 id=&#34;título-1&#34;&gt;Título 1&lt;/h1&gt;
&lt;h2 id=&#34;título-2&#34;&gt;Título 2&lt;/h2&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h2&gt; Texto &lt;/h2&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-markdown&#34;&gt;Texto em **negrito**!\
Texto em __negrito__!\
Texto em *itálico*\
Texto em _itálico_ \
Texto ~~taxado~~
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;p&gt;Texto em &lt;strong&gt;negrito&lt;/strong&gt;!&lt;br&gt;
Texto em &lt;strong&gt;negrito&lt;/strong&gt;!&lt;br&gt;
Texto em &lt;em&gt;itálico&lt;/em&gt;!&lt;br&gt;
Texto em &lt;em&gt;itálico&lt;/em&gt; &lt;br&gt;
Texto &lt;del&gt;taxado&lt;/del&gt; \&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h2&gt; Parágrafos &lt;/h2&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-markdown&#34;&gt;Texto do primeiro parágrafo. \
Texto do segundo parágrafo.

Ou ainda o parágrafo pode 
ser separado acrescentando 
dois espaços na última linha

&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;p&gt;Texto do primeiro parágrafo. &lt;br&gt;
Texto do segundo parágrafo.&lt;/p&gt;
&lt;p&gt;Ou ainda o parágrafo pode
ser separado acrescentando
dois espaços na última linha&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h2&gt; Listas não ordenadas &lt;/h2&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-markdown&#34;&gt;- Primeiro item da lista 1
- Segundo item da lista 1

+ Primeiro item da lista 2
+ Segundo item da lista 2

* Primeiro item da lista 3
* Segundo item da lista 3
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;ul&gt;
&lt;li&gt;Primeiro item da lista 1&lt;/li&gt;
&lt;li&gt;Segundo item da lista 1&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Primeiro item da lista 2&lt;/li&gt;
&lt;li&gt;Segundo item da lista 2&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Primeiro item da lista 3&lt;/li&gt;
&lt;li&gt;Segundo item da lista 3&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h2&gt; Listas com checagem &lt;/h2&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-markdown&#34;&gt;- [X] Primeiro OK!
- [ ] Segundo pendente
- [ ] Segundo também


&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input checked=&#34;&#34; disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Primeiro OK!&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Segundo pendente&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Segundo também&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h2&gt; Listas e sublistas não ordenadas &lt;/h2&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-markdown&#34;&gt;- Lista 1
  - Sublista 1.1
  - Sublista 1.2
    - Subsublista 1.2.1
- Lista 2
  - Sublista 2.1
  - Sublista 2.2
    - Subsublista 2.2.1
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;ul&gt;
&lt;li&gt;Lista 1
&lt;ul&gt;
&lt;li&gt;Sublista 1.1&lt;/li&gt;
&lt;li&gt;Sublista 1.2
&lt;ul&gt;
&lt;li&gt;Subsublista 1.2.1&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Lista 2
&lt;ul&gt;
&lt;li&gt;Sublista 2.1&lt;/li&gt;
&lt;li&gt;Sublista 2.2
&lt;ul&gt;
&lt;li&gt;Subsublista 2.2.1&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h2&gt; Listas ordenadas &lt;/h2&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-markdown&#34;&gt;1. Primeiro 
2. Segundo 
3. Terceiro
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;ol&gt;
&lt;li&gt;Primeiro&lt;/li&gt;
&lt;li&gt;Segundo&lt;/li&gt;
&lt;li&gt;Terceiro&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h2&gt; Citações &lt;/h2&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-markdown&#34;&gt;&amp;gt; Citação em nível 1
&amp;gt;&amp;gt; Citação em nível 2
&amp;gt;&amp;gt;&amp;gt; Citação em nível 3
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;blockquote&gt;
&lt;p&gt;Citação em nível 1&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Citação em nível 2&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Citação em nível 3&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h2&gt;Linhas horizontais&lt;/h2&gt;
&lt;p&gt;Três ou quatro traços (ou asteriscos), formam uma linha:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-markdown&#34;&gt;Primeira linha:

----

Segunda Linha:

****
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt; Links &lt;/h2&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-markdown&#34;&gt;- [Ben Dêivide](https://bendeivide.github.io/)
- Outra forma: [Ben Dêivide][link01]

   [link01]: https://bendeivide.github.io/
   
- Outra forma: [Ben Dêivide]

   [Ben Dêivide]: https://bendeivide.github.io/
   
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Ben Dêivide&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Outra forma: &lt;a href=&#34;https://bendeivide.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Ben Dêivide&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Outra forma: &lt;a href=&#34;https://bendeivide.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Ben Dêivide&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h2&gt; Imagem sem Nome &lt;/h2&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-markdown&#34;&gt;
![](./imagens/rstudio.png)
   
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/estcomp/s07/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_0cd5d2661e8fc6dbb49dd886a81160b2.webp 400w,
               /slides/estcomp/s07/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_5bd7ddd151c2f4da3fa79a2fa5972624.webp 760w,
               /slides/estcomp/s07/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/estcomp/s07/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_0cd5d2661e8fc6dbb49dd886a81160b2.webp&#34;
               width=&#34;170&#34;
               height=&#34;170&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h2&gt; Imagem com Nome &lt;/h2&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-markdown&#34;&gt;
![](./imagens/rstudio.png &amp;quot;IDE RStudio&amp;quot;)
   
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;p&gt;















&lt;figure  id=&#34;figure-ide-rstudio&#34;&gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;IDE RStudio&#34; srcset=&#34;
               /slides/estcomp/s07/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_0cd5d2661e8fc6dbb49dd886a81160b2.webp 400w,
               /slides/estcomp/s07/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_5bd7ddd151c2f4da3fa79a2fa5972624.webp 760w,
               /slides/estcomp/s07/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/estcomp/s07/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_0cd5d2661e8fc6dbb49dd886a81160b2.webp&#34;
               width=&#34;170&#34;
               height=&#34;170&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      IDE RStudio
    &lt;/figcaption&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h2&gt; Imagem estilo de referênica &lt;/h2&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-markdown&#34;&gt;
![][rstudio]

  [rstudio]: ./imagens/rstudio.png &amp;quot;IDE RStudio&amp;quot;
   
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;p&gt;















&lt;figure  id=&#34;figure-ide-rstudio&#34;&gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;IDE RStudio&#34; srcset=&#34;
               /slides/estcomp/s07/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_0cd5d2661e8fc6dbb49dd886a81160b2.webp 400w,
               /slides/estcomp/s07/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_5bd7ddd151c2f4da3fa79a2fa5972624.webp 760w,
               /slides/estcomp/s07/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/estcomp/s07/rstudio_hucbfa44c25ae8fec7feb2f58ef04a2141_39544_0cd5d2661e8fc6dbb49dd886a81160b2.webp&#34;
               width=&#34;170&#34;
               height=&#34;170&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      IDE RStudio
    &lt;/figcaption&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h2&gt; Códigos &lt;/h2&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-markdown&#34;&gt;
```python
print(&#39;Ola, Mundo!&#39;)
```

```r
print(&#39;Ola, Mundo!&#39;)
```

```html
&amp;lt;p&amp;gt; Isso está em &amp;lt;i&amp;gt;negrito&amp;lt;/i&amp;gt; ! &amp;lt;/p&amp;gt;
```

&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;ul&gt;
&lt;li&gt;Código &lt;code&gt;python&lt;/code&gt;:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;print(&#39;Ola, Mundo!&#39;)
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Código &lt;code&gt;R&lt;/code&gt;:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;print(&#39;Ola, Mundo!&#39;)
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Código &lt;code&gt;html&lt;/code&gt;:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&#34;language-html&#34;&gt;&amp;lt;p&amp;gt; Isso está em &amp;lt;i&amp;gt;negrito&amp;lt;/i&amp;gt; ! &amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h2&gt; Tabelas &lt;/h2&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-markdown&#34;&gt;
| Col1     | Col2     |   Col3   |
|:---------|:--------:|---------:|
| Direita  | centro   | esquerda |
| B        |     D    |        F |

   
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;style type=&#34;text/css&#34;&gt;
.tg  {border-collapse:collapse;border-color:#93a1a1;border-spacing:0;}
.tg td{background-color:#fdf6e3;border-bottom-width:1px;border-color:#93a1a1;border-style:solid;border-top-width:1px;
  border-width:0px;color:#002b36;font-family:Arial, sans-serif;font-size:14px;overflow:hidden;padding:13px 13px;
  word-break:normal;}
.tg th{background-color:#657b83;border-bottom-width:1px;border-color:#93a1a1;border-style:solid;border-top-width:1px;
  border-width:0px;color:#fdf6e3;font-family:Arial, sans-serif;font-size:14px;font-weight:normal;overflow:hidden;
  padding:13px 13px;word-break:normal;}
.tg .tg-z4i2{border-color:#ffffff;text-align:left;vertical-align:middle}
.tg .tg-wl5s{background-color:#eee8d5;border-color:#ffffff;text-align:left;vertical-align:middle}
.tg .tg-i2ob{background-color:#eee8d5;border-color:#ffffff;text-align:right;vertical-align:middle}
.tg .tg-44qx{border-color:#ffffff;font-weight:bold;text-align:center;vertical-align:middle}
.tg .tg-0w69{border-color:#ffffff;text-align:right;vertical-align:middle}
.tg .tg-2eyt{border-color:#ffffff;font-weight:bold;text-align:left;vertical-align:middle}
.tg .tg-ung0{border-color:#ffffff;font-weight:bold;text-align:right;vertical-align:middle}
.tg .tg-ttci{background-color:#eee8d5;border-color:#ffffff;text-align:center;vertical-align:middle}
.tg .tg-v0mg{border-color:#ffffff;text-align:center;vertical-align:middle}
&lt;/style&gt;
&lt;table class=&#34;tg&#34;&gt;
&lt;thead&gt;
  &lt;tr&gt;
    &lt;th class=&#34;tg-2eyt&#34;&gt;Col1&lt;/th&gt;
    &lt;th class=&#34;tg-44qx&#34;&gt;Col2&lt;/th&gt;
    &lt;th class=&#34;tg-ung0&#34;&gt;Col3&lt;/th&gt;
  &lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
  &lt;tr&gt;
    &lt;td class=&#34;tg-wl5s&#34;&gt;Direita&lt;/td&gt;
    &lt;td class=&#34;tg-ttci&#34;&gt;centro&lt;/td&gt;
    &lt;td class=&#34;tg-i2ob&#34;&gt;esquerda&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td class=&#34;tg-z4i2&#34;&gt;B&lt;/td&gt;
    &lt;td class=&#34;tg-v0mg&#34;&gt;D&lt;/td&gt;
    &lt;td class=&#34;tg-0w69&#34;&gt;F&lt;/td&gt;
  &lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;h1 id=&#34;questões&#34;&gt;Questões?&lt;/h1&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Dúvidas e Sugestões&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/#contact&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Contato&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Estatística e Probabilidade</title>
      <link>http://bendeivide.github.io/slides/profmat-est/s02/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/profmat-est/s02/</guid>
      <description>
&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap.png&#34;
  &gt;

&lt;h1 id=&#34;estatística-e-probabilidade&#34;&gt;Estatística e Probabilidade&lt;/h1&gt;
&lt;p&gt;Aula 02 - Definições gerais e técnicas de somatório
&lt;/br&gt;&lt;/p&gt;
&lt;p&gt;
  &lt;i class=&#34;fas fa-user-tie  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;https://bendeivide.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Ben Dêivide&lt;/a&gt; | 
  &lt;i class=&#34;fas fa-school  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;https://www.ufsj.edu.br/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;UFSJ&lt;/a&gt;
&lt;/br&gt;

  &lt;i class=&#34;fas fa-book  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;http://bendeivide.github.io/courses/epaec/&#34;&gt;Estatística e Probabilidade&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;selo-dc&#34;&gt;Selo DC&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/dc/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/profmat-est/s02/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_57f4d021c573f1cdb22f5303fccfacd9.webp 400w,
               /slides/profmat-est/s02/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_e3124639f3c96b16d12396d9954194c3.webp 760w,
               /slides/profmat-est/s02/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/profmat-est/s02/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_57f4d021c573f1cdb22f5303fccfacd9.webp&#34;
               width=&#34;385&#34;
               height=&#34;406&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;!-- https://revealjs.com/transitions/ --&gt;
&lt;section data-transition=&#34;zoom&#34;&gt;
  &lt;h2&gt;Introdução&lt;/h2&gt;
  &lt;p&gt; Nossa vida atual é assim hoje ... &lt;/p&gt;
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  &lt;figure  id=&#34;figure-imagens-gratispngcom&#34;&gt;
    &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
      &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;Imagens: gratispng.com&#34; srcset=&#34;
                 /slides/profmat-est/s02/programador_hu85c5d9c20779881f2ae8deae4e3d792a_590442_0769bc3bdb3596bca3f6a01e3f6b0394.webp 400w,
                 /slides/profmat-est/s02/programador_hu85c5d9c20779881f2ae8deae4e3d792a_590442_198182e3dda60929a57504574af4d842.webp 760w,
                 /slides/profmat-est/s02/programador_hu85c5d9c20779881f2ae8deae4e3d792a_590442_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
                 src=&#34;http://bendeivide.github.io/slides/profmat-est/s02/programador_hu85c5d9c20779881f2ae8deae4e3d792a_590442_0769bc3bdb3596bca3f6a01e3f6b0394.webp&#34;
                 width=&#34;530&#34;
                 height=&#34;380&#34;
                 loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
    &lt;/div&gt;&lt;figcaption&gt;
        Imagens: gratispng.com
      &lt;/figcaption&gt;&lt;/figure&gt;
&lt;/section&gt;
&lt;section data-transition-speed=&#34;fast&#34;&gt;
&lt;h2&gt;Introdução&lt;/h2&gt;
&lt;p&gt; Nossa vida atual é assim hoje ... &lt;/p&gt;














&lt;figure  id=&#34;figure-imagens-gratispngcom&#34;&gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;Imagens: gratispng.com&#34; srcset=&#34;
               /slides/profmat-est/s02/dados_hu887ba6b7f9c0e641f75b5f82feacab54_163105_453a07f9082a2771b97ce6d020dc4ec8.webp 400w,
               /slides/profmat-est/s02/dados_hu887ba6b7f9c0e641f75b5f82feacab54_163105_1d078c7aaef4a058d23d40388727b8be.webp 760w,
               /slides/profmat-est/s02/dados_hu887ba6b7f9c0e641f75b5f82feacab54_163105_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/profmat-est/s02/dados_hu887ba6b7f9c0e641f75b5f82feacab54_163105_453a07f9082a2771b97ce6d020dc4ec8.webp&#34;
               width=&#34;530&#34;
               height=&#34;380&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      Imagens: gratispng.com
    &lt;/figcaption&gt;&lt;/figure&gt;
&lt;/section&gt;
&lt;section data-transition-speed=&#34;fast&#34;&gt;
&lt;h2&gt;Introdução&lt;/h2&gt;
&lt;p&gt; Usamos para tudo ... &lt;/p&gt;














&lt;figure  id=&#34;figure-imagens-gratispngcom&#34;&gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;Imagens: gratispng.com&#34; srcset=&#34;
               /slides/profmat-est/s02/emojis_huf8050f69e6ce2d326df2bbe686aea7ea_72356_5f58a4399a031452fdf2f7b4567ce22a.webp 400w,
               /slides/profmat-est/s02/emojis_huf8050f69e6ce2d326df2bbe686aea7ea_72356_ea8f7f14ad53afdff9b10b7854945999.webp 760w,
               /slides/profmat-est/s02/emojis_huf8050f69e6ce2d326df2bbe686aea7ea_72356_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/profmat-est/s02/emojis_huf8050f69e6ce2d326df2bbe686aea7ea_72356_5f58a4399a031452fdf2f7b4567ce22a.webp&#34;
               width=&#34;530&#34;
               height=&#34;380&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      Imagens: gratispng.com
    &lt;/figcaption&gt;&lt;/figure&gt;
&lt;/section&gt;
&lt;section data-transition-speed=&#34;fast&#34;&gt;
&lt;h2&gt;Introdução&lt;/h2&gt;
&lt;p&gt; Pesquisar ... &lt;/p&gt;














&lt;figure  id=&#34;figure-imagens-gratispngcom&#34;&gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;Imagens: gratispng.com&#34; srcset=&#34;
               /slides/profmat-est/s02/searching_hu749c487df7c6eff3fe551052b606a39d_94218_979a7958ebfc5597f19575ecd9f05006.webp 400w,
               /slides/profmat-est/s02/searching_hu749c487df7c6eff3fe551052b606a39d_94218_4f5e7490b68d33a29e8fb42d353e8930.webp 760w,
               /slides/profmat-est/s02/searching_hu749c487df7c6eff3fe551052b606a39d_94218_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/profmat-est/s02/searching_hu749c487df7c6eff3fe551052b606a39d_94218_979a7958ebfc5597f19575ecd9f05006.webp&#34;
               width=&#34;530&#34;
               height=&#34;380&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      Imagens: gratispng.com
    &lt;/figcaption&gt;&lt;/figure&gt;
&lt;/section&gt;
&lt;section data-transition-speed=&#34;fast&#34;&gt;
&lt;h2&gt;Introdução&lt;/h2&gt;
&lt;p&gt; Contratempos ... &lt;/p&gt;














&lt;figure  id=&#34;figure-imagens-gratispngcom&#34;&gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;Imagens: gratispng.com&#34; srcset=&#34;
               /slides/profmat-est/s02/quebrando_pc_hub4a3ac35862bea0b486522facdebe990_189986_dd3a418c0515058ffb1d8bd7f924ff87.webp 400w,
               /slides/profmat-est/s02/quebrando_pc_hub4a3ac35862bea0b486522facdebe990_189986_d8e1aa3e09274d0d674507d64e36b02f.webp 760w,
               /slides/profmat-est/s02/quebrando_pc_hub4a3ac35862bea0b486522facdebe990_189986_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/profmat-est/s02/quebrando_pc_hub4a3ac35862bea0b486522facdebe990_189986_dd3a418c0515058ffb1d8bd7f924ff87.webp&#34;
               width=&#34;530&#34;
               height=&#34;380&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      Imagens: gratispng.com
    &lt;/figcaption&gt;&lt;/figure&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;!-- https://revealjs.com/transitions/ --&gt;
&lt;section data-transition=&#34;zoom&#34;&gt;
  &lt;h2&gt;Dados&lt;/h2&gt;
  &lt;p&gt; Em meio a tudo isso, uma coisa acontece ... &lt;/p&gt;
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  &lt;figure  id=&#34;figure-imagens-gratispngcom&#34;&gt;
    &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
      &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;Imagens: gratispng.com&#34; srcset=&#34;
                 /slides/profmat-est/s02/dados02_huaa69fdfff67864a40a8e5e6a627be466_18369921_7684bd630a966bea4c66d8f3e27710af.webp 400w,
                 /slides/profmat-est/s02/dados02_huaa69fdfff67864a40a8e5e6a627be466_18369921_88e47f38d0b957e637a120fc53fed28d.webp 760w,
                 /slides/profmat-est/s02/dados02_huaa69fdfff67864a40a8e5e6a627be466_18369921_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
                 src=&#34;http://bendeivide.github.io/slides/profmat-est/s02/dados02_huaa69fdfff67864a40a8e5e6a627be466_18369921_7684bd630a966bea4c66d8f3e27710af.webp&#34;
                 width=&#34;530&#34;
                 height=&#34;380&#34;
                 loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
    &lt;/div&gt;&lt;figcaption&gt;
        Imagens: gratispng.com
      &lt;/figcaption&gt;&lt;/figure&gt;
&lt;/section&gt;
&lt;section data-transition-speed=&#34;fast&#34;&gt;
&lt;h2&gt;Dados&lt;/h2&gt;
&lt;p&gt; Essas informações são processadas ... &lt;/p&gt;














&lt;figure  id=&#34;figure-imagens-gratispngcom&#34;&gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;Imagens: gratispng.com&#34; srcset=&#34;
               /slides/profmat-est/s02/infra_comp_hub6808cefc104d832c78f51c1fe99f225_205407_d992efe6d9441dba596dd57504563239.webp 400w,
               /slides/profmat-est/s02/infra_comp_hub6808cefc104d832c78f51c1fe99f225_205407_cc5813b7ab49e6ce51f87ec864d8bd40.webp 760w,
               /slides/profmat-est/s02/infra_comp_hub6808cefc104d832c78f51c1fe99f225_205407_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/profmat-est/s02/infra_comp_hub6808cefc104d832c78f51c1fe99f225_205407_d992efe6d9441dba596dd57504563239.webp&#34;
               width=&#34;530&#34;
               height=&#34;380&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      Imagens: gratispng.com
    &lt;/figcaption&gt;&lt;/figure&gt;
&lt;/section&gt;
&lt;section data-transition-speed=&#34;fast&#34;&gt;
&lt;h2&gt;Dados&lt;/h2&gt;
&lt;p&gt; Analisadas ... &lt;/p&gt;














&lt;figure  id=&#34;figure-imagens-gratispngcom&#34;&gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;Imagens: gratispng.com&#34; srcset=&#34;
               /slides/profmat-est/s02/exp_user_hu8f5c0e0d7f084260f0d10501891b1393_29133_6ef8d184a5fe1679c0d6b7abc1011d81.webp 400w,
               /slides/profmat-est/s02/exp_user_hu8f5c0e0d7f084260f0d10501891b1393_29133_87aaaa3da49d73051be18accb8582e5a.webp 760w,
               /slides/profmat-est/s02/exp_user_hu8f5c0e0d7f084260f0d10501891b1393_29133_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/profmat-est/s02/exp_user_hu8f5c0e0d7f084260f0d10501891b1393_29133_6ef8d184a5fe1679c0d6b7abc1011d81.webp&#34;
               width=&#34;530&#34;
               height=&#34;380&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      Imagens: gratispng.com
    &lt;/figcaption&gt;&lt;/figure&gt;
&lt;/section&gt;
&lt;section data-transition-speed=&#34;fast&#34;&gt;
&lt;h2&gt;Dados&lt;/h2&gt;
&lt;p&gt; E assim, todos esses dados ... &lt;/p&gt;














&lt;figure  id=&#34;figure-imagens-gratispngcom&#34;&gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;Imagens: gratispng.com&#34; srcset=&#34;
               /slides/profmat-est/s02/analise02_hu9ea620b0e1d37040944340d01dd78f2b_515291_8778f4bc4322cd248911f541b900c98e.webp 400w,
               /slides/profmat-est/s02/analise02_hu9ea620b0e1d37040944340d01dd78f2b_515291_7a54132dfe8825d6cab37da7f5bfd4ed.webp 760w,
               /slides/profmat-est/s02/analise02_hu9ea620b0e1d37040944340d01dd78f2b_515291_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/profmat-est/s02/analise02_hu9ea620b0e1d37040944340d01dd78f2b_515291_8778f4bc4322cd248911f541b900c98e.webp&#34;
               width=&#34;530&#34;
               height=&#34;380&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      Imagens: gratispng.com
    &lt;/figcaption&gt;&lt;/figure&gt;
&lt;/section&gt;
&lt;section data-transition-speed=&#34;fast&#34;&gt;
&lt;h2&gt;Dados&lt;/h2&gt;
&lt;p&gt; ... que os usuários repassam ... &lt;/p&gt;














&lt;figure  id=&#34;figure-imagens-gratispngcom&#34;&gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;Imagens: gratispng.com&#34; srcset=&#34;
               /slides/profmat-est/s02/analise03_hub2e1dffd2cc65cb9ada91baab78eae39_412393_ecbf33cd9eab19e34cbc14286fd53e75.webp 400w,
               /slides/profmat-est/s02/analise03_hub2e1dffd2cc65cb9ada91baab78eae39_412393_6104309efe8272d3b6d06f70cad0b52b.webp 760w,
               /slides/profmat-est/s02/analise03_hub2e1dffd2cc65cb9ada91baab78eae39_412393_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/profmat-est/s02/analise03_hub2e1dffd2cc65cb9ada91baab78eae39_412393_ecbf33cd9eab19e34cbc14286fd53e75.webp&#34;
               width=&#34;530&#34;
               height=&#34;380&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      Imagens: gratispng.com
    &lt;/figcaption&gt;&lt;/figure&gt;
&lt;/section&gt;
&lt;section data-transition-speed=&#34;fast&#34;&gt;
&lt;h1&gt;Dados &gt; \$&lt;/h1&gt;
&lt;/section&gt;
&lt;section data-transition-speed=&#34;fast&#34;&gt;
&lt;h2&gt;Dados&lt;/h2&gt;
&lt;p&gt; E aí, o Vale do silício é o que tem que ser! &lt;/p&gt;














&lt;figure  id=&#34;figure-imagens-oficinadanetcombr&#34;&gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;Imagens: oficinadanet.com.br&#34; srcset=&#34;
               /slides/profmat-est/s02/vale_silicio_hu2e878ae56d4a55650a6917f7b07e2ae0_84455_e4d52bf7f5244f20b8c1cbb9bbc42621.webp 400w,
               /slides/profmat-est/s02/vale_silicio_hu2e878ae56d4a55650a6917f7b07e2ae0_84455_927ece7d5689dccd421079d10c92cf95.webp 760w,
               /slides/profmat-est/s02/vale_silicio_hu2e878ae56d4a55650a6917f7b07e2ae0_84455_1200x1200_fit_q75_h2_lanczos.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/profmat-est/s02/vale_silicio_hu2e878ae56d4a55650a6917f7b07e2ae0_84455_e4d52bf7f5244f20b8c1cbb9bbc42621.webp&#34;
               width=&#34;530&#34;
               height=&#34;380&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      Imagens: oficinadanet.com.br
    &lt;/figcaption&gt;&lt;/figure&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;!-- https://revealjs.com/transitions/ --&gt;
&lt;section data-transition=&#34;zoom&#34;&gt;
  &lt;h2&gt;Motivação inicial &lt;/h2&gt;
  &lt;p&gt; Definições gerais da estatística (Exemplo do livro EPAEC) &lt;/p&gt;
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  &lt;figure  &gt;
    &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
      &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
                 /slides/profmat-est/s02/epaec_exerc5.19_huf42f90654072e146aede07d81ef72130_118873_d2eb6c328bbca59128eb008a44841e3c.webp 400w,
                 /slides/profmat-est/s02/epaec_exerc5.19_huf42f90654072e146aede07d81ef72130_118873_2422affad744e4d2bee6a7971f41e9ec.webp 760w,
                 /slides/profmat-est/s02/epaec_exerc5.19_huf42f90654072e146aede07d81ef72130_118873_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
                 src=&#34;http://bendeivide.github.io/slides/profmat-est/s02/epaec_exerc5.19_huf42f90654072e146aede07d81ef72130_118873_d2eb6c328bbca59128eb008a44841e3c.webp&#34;
                 width=&#34;830&#34;
                 height=&#34;420&#34;
                 loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
    &lt;/div&gt;&lt;/figure&gt;
&lt;/section&gt;
&lt;section data-transition-speed=&#34;fast&#34;&gt;
&lt;h2&gt;Motivação inicial&lt;/h2&gt;
&lt;p&gt; Definições gerais da estatística... &lt;/p&gt;














&lt;figure  id=&#34;figure-imagem-livro-epaec&#34;&gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;Imagem: Livro EPAEC&#34; srcset=&#34;
               /slides/profmat-est/s02/prodcons_hu5910991e216a6cca12abe1fdcd74a6f7_5529_41d76642fcdda6f48ac510a3ac9a6405.webp 400w,
               /slides/profmat-est/s02/prodcons_hu5910991e216a6cca12abe1fdcd74a6f7_5529_18a6dc64c476a8c99164f36faf38e895.webp 760w,
               /slides/profmat-est/s02/prodcons_hu5910991e216a6cca12abe1fdcd74a6f7_5529_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/profmat-est/s02/prodcons_hu5910991e216a6cca12abe1fdcd74a6f7_5529_41d76642fcdda6f48ac510a3ac9a6405.webp&#34;
               width=&#34;530&#34;
               height=&#34;380&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      Imagem: Livro EPAEC
    &lt;/figcaption&gt;&lt;/figure&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;método-científico&#34;&gt;Método Científico&lt;/h2&gt;
&lt;iframe width=&#34;760&#34; height=&#34;515&#34; src=&#34;https://www.youtube.com/embed/QPeS1v7l6yk&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;!-- https://revealjs.com/transitions/ --&gt;
&lt;section data-transition=&#34;zoom&#34;&gt;
  &lt;h2&gt;Definições Gerais da Estatística&lt;/h2&gt;
  &lt;aside class=&#34;notes&#34;&gt;
    📝 Mostrar a relação do Método científico com as Definições gerais da estatística (Smoothdraw)
  &lt;/aside&gt;
  &lt;iframe width=&#34;760&#34; height=&#34;515&#34; src=&#34;https://www.youtube.com/embed/mASLUwyaC5Q&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;/section&gt;
&lt;section data-transition-speed=&#34;fast&#34;&gt;
&lt;h2&gt;Definições Gerais da Estatística&lt;/h2&gt;
&lt;aside class=&#34;notes&#34;&gt;
    📝 Mostrar a relação do Método científico com as Definições gerais da estatística (Smoothdraw)
  &lt;/aside&gt;
&lt;iframe width=&#34;760&#34; height=&#34;515&#34; src=&#34;https://www.youtube.com/embed/xvORKHMVUr8&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;/section&gt;
&lt;hr&gt;
&lt;h2 id=&#34;natureza-das-variáveis&#34;&gt;Natureza das variáveis&lt;/h2&gt;
&lt;iframe width=&#34;760&#34; height=&#34;515&#34; src=&#34;https://www.youtube.com/embed/LIg6uLzCRmU&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;técnicas-de-somatório&#34;&gt;Técnicas de Somatório&lt;/h2&gt;
  &lt;aside class=&#34;notes&#34;&gt;
    📝 Fazer alguns exemplos na sala digital (Smoothdraw)
  &lt;/aside&gt;
&lt;iframe width=&#34;760&#34; height=&#34;515&#34; src=&#34;https://www.youtube.com/embed/tWCxCyZZHes&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h1 id=&#34;questões&#34;&gt;Questões?&lt;/h1&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Dúvidas e Sugestões&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/#contact&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Contato&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;!-- https://revealjs.com/transitions/ --&gt;
&lt;section data-transition=&#34;zoom&#34;&gt;
  &lt;h1&gt;Próximas aulas...&lt;/h1&gt;
&lt;/section&gt;
&lt;section data-transition-speed=&#34;fast&#34;&gt;
&lt;a href=&#34;http://bendeivide.github.io/courses/epaec&#34; target=&#34;_blank&#34;&gt;














&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/profmat-est/s02/ben_hu087225affb9399e037f09661c4d0adbd_219224_5c10d459c8ddc0416f506a4ad838a085.webp 400w,
               /slides/profmat-est/s02/ben_hu087225affb9399e037f09661c4d0adbd_219224_29ebba9a3e515b23ea411bffea18d2f1.webp 760w,
               /slides/profmat-est/s02/ben_hu087225affb9399e037f09661c4d0adbd_219224_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/profmat-est/s02/ben_hu087225affb9399e037f09661c4d0adbd_219224_5c10d459c8ddc0416f506a4ad838a085.webp&#34;
               width=&#34;630&#34;
               height=&#34;480&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;
&lt;p&gt;&lt;a href=&#34;http://bendeivide.github.io/courses/epaec&#34; target=&#34;_blank&#34;&gt;bendeivide.github.io/courses/epaec&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;!-- &lt;section&gt; --&gt;
&lt;!--   &lt;h2&gt;Some Slide&lt;/h2&gt; --&gt;
&lt;!--   &lt;aside class=&#34;notes&#34;&gt; --&gt;
&lt;!--     Anotações no Visualizador (Clique em S) 📝 --&gt;
&lt;!--   &lt;/aside&gt; --&gt;
&lt;!-- &lt;/section&gt; --&gt;
&lt;!-- ## Animação --&gt;
&lt;!-- &lt;section data-auto-animate&gt; --&gt;
&lt;!--   &lt;h1&gt;Auto-Animate&lt;/h1&gt; --&gt;
&lt;!-- &lt;/section&gt; --&gt;
&lt;!-- &lt;section data-auto-animate&gt; --&gt;
&lt;!--   &lt;h1 style=&#34;margin-top: 100px; color: red;&#34;&gt;Auto-Animate&lt;/h1&gt; --&gt;
&lt;!-- &lt;/section&gt; --&gt;
</description>
    </item>
    
    <item>
      <title>Estatística e Probabilidade</title>
      <link>http://bendeivide.github.io/slides/profmat-est/s03/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/profmat-est/s03/</guid>
      <description>
&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap.png&#34;
  &gt;

&lt;h1 id=&#34;estatística-e-probabilidade&#34;&gt;Estatística e Probabilidade&lt;/h1&gt;
&lt;p&gt;Aula 03 - Coleta, organização e apresentação de dados
&lt;/br&gt;&lt;/p&gt;
&lt;p&gt;
  &lt;i class=&#34;fas fa-user-tie  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;https://bendeivide.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Ben Dêivide&lt;/a&gt; | 
  &lt;i class=&#34;fas fa-school  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;https://www.ufsj.edu.br/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;UFSJ&lt;/a&gt;
&lt;/br&gt;

  &lt;i class=&#34;fas fa-book  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;http://bendeivide.github.io/courses/epaec/&#34;&gt;Estatística e Probabilidade&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;selo-dc&#34;&gt;Selo DC&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/dc/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/profmat-est/s03/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_57f4d021c573f1cdb22f5303fccfacd9.webp 400w,
               /slides/profmat-est/s03/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_e3124639f3c96b16d12396d9954194c3.webp 760w,
               /slides/profmat-est/s03/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/profmat-est/s03/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_57f4d021c573f1cdb22f5303fccfacd9.webp&#34;
               width=&#34;385&#34;
               height=&#34;406&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;section&gt;
  &lt;h2&gt;Motivação inicial&lt;/h2&gt;
  &lt;h3&gt; Dados (Primeiro tipo) &lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;##    [1] 100.93730855  90.78737290  31.43347250  70.04161421 114.72725633
##    [6] 119.48971504  39.59619123  81.81619913  18.66636591  87.17608029
##   [11] 155.08897515 137.78907540  88.08832220 149.37223517 137.06950642
##   [16] 104.46736332  52.25280719  90.24248077 146.27606310 124.14892624
##   [21]  70.18446816  -9.26434191  66.25670311  -5.95305960  36.74009892
##   [26]  81.31692224  65.62222848  56.39205866  94.91194969  87.31097349
##   [31]   7.31297728  96.10269670 148.42831703 109.24629800  31.00282108
##   [36]  28.22428188 118.10436143  12.04566231  83.77279952  67.42185057
##   [41] 154.32756997  61.87275600  58.56687325 141.72369515  51.61740066
##   [46]  98.55923323 111.62625763  84.93956592  66.11927084 132.76138181
##   [51]  79.96812265  83.27217175 168.39769766 206.88835518 125.29096323
##   [56] 139.31711921  54.88940279 126.64484962  67.70528732 114.54937442
##   [61]  38.12027656  77.19118624  58.48386726 117.00578218 153.31881978
##   [66] 160.80629190 136.78453288  75.93956913 128.13723814  37.68401441
##   [71] 119.04611063  28.47863736  47.57772476  89.07482247  25.50318816
##   [76] 158.63531406  26.00864892  78.48060920  47.41806790 176.12931720
##   [81] 129.64140273  88.86692455 135.64471381 135.83004169 122.01209322
##   [86] 107.94153107 132.98820692 211.02598315  40.80274630  96.30220828
##   [91]  79.18226626  90.42588281 103.47723907 157.76741590 129.74786735
##   [96]  29.01774458  19.66613773 144.64629498 107.40839776 161.35141951
##  [101]  61.90978304 120.96877029  48.00283177 135.57869830  68.33934925
##  [106] 128.15873322 133.04933429  17.09745713 151.40839885 156.39768070
##  [111]  35.99226983 156.44341137  76.79327364  84.21198952 146.21465734
##  [116] 103.85723620 151.99618026 137.09431034 162.77724291 147.54594832
##  [121]  75.93171964 110.14408890  98.41301281  40.22098498 131.18406184
##  [126]  54.25977582 112.43790039  46.86886034  81.80088764  39.65025733
##  [131] 171.46063907 131.67179455   0.15921912  65.90839135  76.99722603
##  [136]  50.84654029 124.76658564 136.29087501 133.36493659 147.73932182
##  [141]  16.23339104  39.74073038   1.83737554 173.53761549 118.62361693
##  [146] 153.29396670 126.53249342 105.09917229 166.88912329 104.36173842
##  [151]  80.44478963  87.50662577 157.75523729  56.76363801  56.66608288
##  [156] -16.05085152 130.44150845 157.50030241  40.02011641  20.99996227
##  [161] 132.65830968  72.52957574 126.05272627  65.02984668  78.05453426
##  [166]  66.13403519 147.95705974  26.59133353 109.18819463  28.24264087
##  [171]  43.13000509  79.26773366 107.19671441 153.10121653  71.46030486
##  [176] 163.85906882 111.41446603  84.55934677 147.99145653 127.44111874
##  [181] 121.27565469 132.17500176  31.98469282  90.07469468 130.96513384
##  [186] 203.41048025  84.73576229 114.06228061 134.56586684 102.31807191
##  [191] 105.65146808 149.76659371  65.94243193  36.14713767  26.56511251
##  [196]  84.32629667  14.81702537  32.47426719  44.89531614  45.02284927
##  [201] 160.77568881 116.54382426 169.51375596 143.60234925  45.95914887
##  [206] 124.79107957 152.63137781  36.26750249  90.31666358  35.24581787
##  [211] 107.09401423 163.08575260  78.42498360   8.86437052 117.62719794
##  [216]  32.57742793 135.38441590  79.45545316  77.69774100  47.94218492
##  [221]  83.53876419  85.85891879 121.62145627  84.61964525  97.16818461
##  [226] 136.67577101 104.86558098 181.54458683 128.03053495 166.47823822
##  [231]  86.05882522  36.66342279  87.54258030 100.89942073 118.85363636
##  [236] 139.80042788  57.96612915 -10.27358754  43.59720045  32.93450206
##  [241] 180.25570214 137.22118642 143.10411030 119.75779077 125.45593482
##  [246]  93.87249371 104.62923236  82.10600428  82.01723878 151.42853604
##  [251] 153.89462962 146.58906076  26.96030665  54.69622119  65.98260843
##  [256] 153.15830184  65.37934239  43.31858674  45.26922831  49.35481906
##  [261] 120.51386629 123.88702210 -16.49397725 100.81277326 149.01767616
##  [266] 140.31741324 105.98004444 -21.83078022 101.55112381  83.21266510
##  [271]  86.81119190  82.20737696  75.94226009 111.13677339 221.49551593
##  [276] 174.81490594  64.13958986  76.64730499 133.14617264 215.00884455
##  [281] 116.37550706 103.19317408  43.02195300 159.02051018 102.06942385
##  [286]  39.32032183 103.65978883  87.13377028 113.34032055 169.38621629
##  [291] 109.65398175 129.61583113  58.50127365 119.62866408 119.24338053
##  [296] 152.55223329 157.78987423  48.27810205  87.27659671 163.68421330
##  [301] 175.12723195 129.52047336  68.46572743 139.61747686 106.26922851
##  [306] 116.13774856  77.72083953 138.34219672  29.82484891  41.19766102
##  [311] 125.57982346 165.83826319 219.64564735  96.61152958  89.81074668
##  [316] 199.82172261 177.16088972  38.58311869 232.22439961 137.85068541
##  [321] 152.76725961 147.89724477 141.69395288  91.53622150  79.77831785
##  [326] 114.78007869  88.40627464  77.59608842 101.11553983 102.22336486
##  [331] 124.03605826 131.78099276  -0.03711965  65.46722481  93.46774053
##  [336]  82.78741085  97.37935880 104.80619603 113.32035266 127.73967376
##  [341] 161.77229393 114.25666907  77.06035361 131.17390109  63.80024542
##  [346] 180.97093517  69.16632949 119.22705287 205.72606564  48.57163169
##  [351]  55.66060172 163.55730007  19.74572794 156.11366915 207.92193209
##  [356] 121.41233065 160.05893452 151.58450581 132.69371264 200.60408866
##  [361] 154.73149209 136.32046770  30.01714317  35.61024184  51.57922612
##  [366]  13.16571211 141.58486790  62.05234457 207.75385005  78.83705599
##  [371]  99.71750317 120.01808643  81.71610990  78.54280824 112.23485634
##  [376] 210.98881244 115.71349040  71.81074627  25.71519208 120.76492965
##  [381]  73.59681587  82.47646913 136.53109686  72.16879175  27.51197319
##  [386]  47.40017859  65.85806906  69.35294107 194.53900175  92.72947332
##  [391]  68.02881397  79.44119774 117.13959392  43.33766227 103.30351513
##  [396] 101.89998830 146.05323738 206.74828192  70.00865342 162.22232293
##  [401]  96.02714914 159.08757749 209.30720313 120.30874654  63.08204477
##  [406]   2.17566485   2.49771492  52.95010922 159.88933843  68.78803048
##  [411]  93.35651724  99.13895389  77.01853589 173.64683953 208.46598063
##  [416] -50.07156532  11.40072085  81.75803886 118.72668903  38.29610367
##  [421] 123.74467110 161.65287285  70.34356716 137.61312197 130.60227534
##  [426]  88.56713174  64.75803251 161.47580236 175.92575649 167.25470902
##  [431]  93.81542355 146.69512268 100.97484228 141.54260549  84.77526660
##  [436]  97.03593614 150.36983487  31.11024570  49.78986365  98.83598475
##  [441] 177.33736369  62.03183745 150.33963287 113.71074582  95.98088177
##  [446]  54.82237523 123.65725515 169.42444890 101.73730469  35.37074860
##  [451] 158.19837525  23.83077015 -25.91675268  64.62353847  85.62835586
##  [456]  78.23458443  82.84606146  98.03445580 144.34829939  82.00257996
##  [461]  63.55228647 187.58728096  95.69807049 155.31815079  99.04110814
##  [466]  25.32699108 235.03183115  62.81527889 153.25974905  98.39591342
##  [471]  73.00201553   3.71782162 150.39156881  86.03826016  37.52170724
##  [476] 162.42455639  90.38933117 145.59881155  -7.91348400 164.48052662
##  [481]  78.59450172  87.24985535 166.35791194 141.93450603  26.74996614
##  [486]  69.18736511 105.30529197   7.79916211  19.17885731 111.38383521
##  [491] 146.06083510  83.43982803 164.36170155 102.86304012 -10.19665626
##  [496]  73.85448259 154.03926551  87.84293312  54.52767189  56.58502463
##  [501] 143.47375225  65.99952011 108.66072694  92.02809805 139.67497163
##  [506] 184.71752457 161.99843432 101.47183716 182.86072495 156.56115701
##  [511]  29.87946839 107.83852306 143.37542982  98.33824214 147.70322782
##  [516] 156.50483626 119.68486560 118.84041640  87.41285465 125.20474454
##  [521]  33.50982643  94.08502737  68.33757667 133.88456724  85.10591176
##  [526] 131.39611236 183.92153640 -20.00012703  32.50785575 160.10039479
##  [531] 164.69213597  97.02028269  65.74688274  27.32803478 164.70632806
##  [536] 158.80845447 143.20225391 -14.83662617  30.40949940  30.70616275
##  [541]  46.34765780  52.92872484  70.67828451 151.73606100 122.94811033
##  [546]  40.32774640 139.59446358  11.38475446  70.61387890  35.88148437
##  [551]  84.39326695  65.06123497 -32.19248839 141.25111884 115.34631566
##  [556]  97.09802709 146.32847054  89.06540697 149.65667487   3.83328288
##  [561]  47.36424078 144.51988810 277.05701388 137.07553713  89.62643730
##  [566] 108.99692271 171.31824247  77.84166053 118.35949933 134.79108481
##  [571] 146.67223643 174.59445413 157.97614951 111.33979785  35.22674076
##  [576]  96.86106542 149.66414684  49.70345300  62.45075262 187.20081912
##  [581]  40.61999543  79.15147911  21.50899203  85.97629824  70.73365181
##  [586] 133.01595988  68.12437255  73.04891834 147.57601168  94.72100771
##  [591]  81.29653636  91.18837096 113.82416540 111.81662963 203.08370797
##  [596]  35.49700071 128.55947237 189.26951134 110.64701215 144.23460730
##  [601]  54.90148678  97.26250210  32.16226445 115.86152886 169.78595597
##  [606]  39.43880916  89.79291696  22.37743370 125.90248343  79.05798484
##  [611]  14.52733922 224.15813357 124.90168675  66.30658974  55.65093022
##  [616]  13.43113246 130.22745607  56.43624609 136.26708232  98.46340099
##  [621]  94.13888128 104.91114693  66.15713891  97.53768225  71.96401200
##  [626] 219.95774326  95.50639492  58.91757911  85.65191192 106.56394370
##  [631]  46.89580248 136.67905179 116.13460992  82.55101143 164.17628321
##  [636]  49.27559756  74.49678629  91.64151269  84.86661072 201.32352362
##  [641] 145.04528192 106.77145202  89.93555229  59.65816295 132.20620619
##  [646]  83.16704397  13.41482444 113.09603313  54.16512009  71.57177624
##  [651]  56.70897791 141.27469559  59.99338579 148.79150434 235.00377654
##  [656]  93.23052016  94.69844180  32.79680974 122.15609143 148.05588708
##  [661]  87.92820917 104.14774456  81.91376211 116.69300999 113.28047105
##  [666] 250.64528733  82.76349312 153.12787266  63.51574630 102.82738605
##  [671] 123.39148560  81.36773747 110.50808438 164.48041528  18.65802251
##  [676]  60.82317452 125.54565517 160.88130280 115.25546238 110.51468167
##  [681] 123.44329828   4.78287139 161.92011423 119.54994457  98.44005416
##  [686]  19.05997391 122.56331391  65.45783182 170.27228110  14.93286561
##  [691] 109.61227986  64.85216193  59.57220683  68.09006292 186.86727140
##  [696] -13.02391316  19.37639531 132.68700994 145.14403643 137.73042439
##  [701]  88.65946156  65.20156862 125.33236787 130.81171468  16.65603627
##  [706]  83.18728871 125.35899284  15.13046492  89.65363880  80.07014859
##  [711]  40.56900863 122.62827021 110.37948520  39.49388119 138.37075271
##  [716]  70.04861544  21.95136136  50.21679785 154.66255042 145.85714430
##  [721]  61.34753224  76.20820912  43.46484080  78.55822842  58.02081751
##  [726]  69.95066635  61.30546109  55.37538244  98.21340765  84.79109488
##  [731] -50.60818918  -0.42615289  97.68142953  82.02314677  90.24891691
##  [736]  24.27649323  55.39834764  56.86467543 127.59770740  90.58830433
##  [741]  83.74266282  73.15307754  81.42612936 136.14035118 160.28459417
##  [746] 159.20765628 133.55952177 158.77510367 109.42632364 124.95317984
##  [751]   2.61908443 121.03686231 158.67381249  27.68842215  81.66243970
##  [756]  69.61018826 115.99356887 154.99238361  79.69816862 220.53732134
##  [761] 157.94499424 116.91947958 122.80886720  84.29776668 170.21720101
##  [766]  79.48650255  95.59487419 116.24377974 159.25499001  87.22457133
##  [771] 144.22239604  75.57194652  63.63119134  40.58723635  73.10287920
##  [776] 105.96756087 165.90890477 172.15402788 112.45131058 140.78511634
##  [781]  63.26960968 112.90766390  57.35696156 110.78243793  64.53948940
##  [786] 135.54327616  77.63140706  83.08508479 125.86167111 104.93517972
##  [791] 137.18428079  86.07249293 126.95358403  95.58302652  62.71212459
##  [796]  21.99607744 154.14782627 -17.05280013 110.31526330 138.23712856
##  [801]  -6.25342905 126.05893332  97.67885500  42.52641395 131.46691539
##  [806]  63.67642620  80.67913388  66.41428051 145.01930952 144.34208453
##  [811] 119.51390559  53.62442549 137.29196144 124.74120783  98.90342691
##  [816] 129.40111631 137.82455370  75.29868637  63.33421857  99.94898030
##  [821] 140.29128484 155.46546909  84.51602589  54.57108759 113.15130638
##  [826]  98.95410962  89.38287462  48.44480401 106.97553698 108.31089923
##  [831]  50.76701755 101.13170354 139.26650163  41.04052379 195.53953888
##  [836]  73.09992525 144.21382145 107.36548184  49.57863186 141.90944961
##  [841]  41.58804313 122.71590665 110.62864338  72.34568263 101.17150126
##  [846] 132.40894452  12.86026324 129.75813305  56.07354935 132.22187856
##  [851]  68.54507487  95.08999052 134.21088496  30.76569845 177.74727930
##  [856]  59.28293291  57.81844571 151.24637129 105.78516882 112.07470199
##  [861]  30.45919292 176.30304223 102.32581184 161.99911798 115.42863177
##  [866] 139.28138023 155.87393524  99.75088638  91.07908949 134.81145345
##  [871] 126.08986042  77.60867049 120.27003020  63.15177877 112.78740072
##  [876]  85.75332475  98.44393375  75.70705565  93.24559579  25.96406386
##  [881] 162.81845628 110.45208250 115.65783948 153.75741193  85.66874127
##  [886]  98.40112863  62.86333017 204.26100961 142.74452052 150.02229981
##  [891]  40.79410450  22.94487224  89.41334996 108.51762850  65.46113128
##  [896] 184.88603695  96.36550187  64.11955719  79.17427808 209.67933805
##  [901] 127.11739129 151.18338045 140.64130544 165.05135387 128.39782055
##  [906]  93.99642789  75.39986469 110.03859877 108.23996494 134.68288481
##  [911] 106.66621267  63.02684207  80.12405924 112.85793197  85.99130404
##  [916] 150.39837961 157.76098120  89.86025254  83.92952265  18.94730415
##  [921] 128.40526295 133.56401236 173.01297609  18.11403129 164.92505411
##  [926]  92.31500856 178.95744228 202.76175928 164.22433254 120.87016586
##  [931] 157.99268036 124.57951279 155.10043589 128.42852151  81.80414574
##  [936] 106.84781854 136.21377136 176.99908030 149.34961674  52.69890010
##  [941]  69.36596579 164.34432952  72.16749200  98.85111389 166.23705613
##  [946] 113.19488345 142.06695095  86.79312555 144.33846460 111.27428778
##  [951] 127.24163623 158.81253634  84.32123791 125.26883443 176.98506493
##  [956] 174.55013553 112.18447423  79.23428368  -1.75863811  67.83210511
##  [961] 102.69107405  80.52190580 193.89127767  27.11966366 136.19276892
##  [966]  39.09618692  84.71205651 101.21988583 117.61330506 141.18948778
##  [971] 129.88932805 164.78187322  71.09669104 108.64874902  70.94018770
##  [976]  60.87047018  16.65853979  64.32633758  74.66620861  65.24080279
##  [981] 127.08039056  70.94613518 121.54160255 133.58505948  78.32463472
##  [986]  60.95082856 120.81490912  58.91897002 110.55379452 137.74115849
##  [991] 189.00548763 133.29738410  99.46330902  39.94726968  67.83011078
##  [996] 139.86461552 126.41241372 114.18348694  99.39303476  90.40431113
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3&gt; Dados (Segundo tipo) &lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;##    [1] -50.60818918 -50.07156532 -32.19248839 -25.91675268 -21.83078022
##    [6] -20.00012703 -17.05280013 -16.49397725 -16.05085152 -14.83662617
##   [11] -13.02391316 -10.27358754 -10.19665626  -9.26434191  -7.91348400
##   [16]  -6.25342905  -5.95305960  -1.75863811  -0.42615289  -0.03711965
##   [21]   0.15921912   1.83737554   2.17566485   2.49771492   2.61908443
##   [26]   3.71782162   3.83328288   4.78287139   7.31297728   7.79916211
##   [31]   8.86437052  11.38475446  11.40072085  12.04566231  12.86026324
##   [36]  13.16571211  13.41482444  13.43113246  14.52733922  14.81702537
##   [41]  14.93286561  15.13046492  16.23339104  16.65603627  16.65853979
##   [46]  17.09745713  18.11403129  18.65802251  18.66636591  18.94730415
##   [51]  19.05997391  19.17885731  19.37639531  19.66613773  19.74572794
##   [56]  20.99996227  21.50899203  21.95136136  21.99607744  22.37743370
##   [61]  22.94487224  23.83077015  24.27649323  25.32699108  25.50318816
##   [66]  25.71519208  25.96406386  26.00864892  26.56511251  26.59133353
##   [71]  26.74996614  26.96030665  27.11966366  27.32803478  27.51197319
##   [76]  27.68842215  28.22428188  28.24264087  28.47863736  29.01774458
##   [81]  29.82484891  29.87946839  30.01714317  30.40949940  30.45919292
##   [86]  30.70616275  30.76569845  31.00282108  31.11024570  31.43347250
##   [91]  31.98469282  32.16226445  32.47426719  32.50785575  32.57742793
##   [96]  32.79680974  32.93450206  33.50982643  35.22674076  35.24581787
##  [101]  35.37074860  35.49700071  35.61024184  35.88148437  35.99226983
##  [106]  36.14713767  36.26750249  36.66342279  36.74009892  37.52170724
##  [111]  37.68401441  38.12027656  38.29610367  38.58311869  39.09618692
##  [116]  39.32032183  39.43880916  39.49388119  39.59619123  39.65025733
##  [121]  39.74073038  39.94726968  40.02011641  40.22098498  40.32774640
##  [126]  40.56900863  40.58723635  40.61999543  40.79410450  40.80274630
##  [131]  41.04052379  41.19766102  41.58804313  42.52641395  43.02195300
##  [136]  43.13000509  43.31858674  43.33766227  43.46484080  43.59720045
##  [141]  44.89531614  45.02284927  45.26922831  45.95914887  46.34765780
##  [146]  46.86886034  46.89580248  47.36424078  47.40017859  47.41806790
##  [151]  47.57772476  47.94218492  48.00283177  48.27810205  48.44480401
##  [156]  48.57163169  49.27559756  49.35481906  49.57863186  49.70345300
##  [161]  49.78986365  50.21679785  50.76701755  50.84654029  51.57922612
##  [166]  51.61740066  52.25280719  52.69890010  52.92872484  52.95010922
##  [171]  53.62442549  54.16512009  54.25977582  54.52767189  54.57108759
##  [176]  54.69622119  54.82237523  54.88940279  54.90148678  55.37538244
##  [181]  55.39834764  55.65093022  55.66060172  56.07354935  56.39205866
##  [186]  56.43624609  56.58502463  56.66608288  56.70897791  56.76363801
##  [191]  56.86467543  57.35696156  57.81844571  57.96612915  58.02081751
##  [196]  58.48386726  58.50127365  58.56687325  58.91757911  58.91897002
##  [201]  59.28293291  59.57220683  59.65816295  59.99338579  60.82317452
##  [206]  60.87047018  60.95082856  61.30546109  61.34753224  61.87275600
##  [211]  61.90978304  62.03183745  62.05234457  62.45075262  62.71212459
##  [216]  62.81527889  62.86333017  63.02684207  63.08204477  63.15177877
##  [221]  63.26960968  63.33421857  63.51574630  63.55228647  63.63119134
##  [226]  63.67642620  63.80024542  64.11955719  64.13958986  64.32633758
##  [231]  64.53948940  64.62353847  64.75803251  64.85216193  65.02984668
##  [236]  65.06123497  65.20156862  65.24080279  65.37934239  65.45783182
##  [241]  65.46113128  65.46722481  65.62222848  65.74688274  65.85806906
##  [246]  65.90839135  65.94243193  65.98260843  65.99952011  66.11927084
##  [251]  66.13403519  66.15713891  66.25670311  66.30658974  66.41428051
##  [256]  67.42185057  67.70528732  67.83011078  67.83210511  68.02881397
##  [261]  68.09006292  68.12437255  68.33757667  68.33934925  68.46572743
##  [266]  68.54507487  68.78803048  69.16632949  69.18736511  69.35294107
##  [271]  69.36596579  69.61018826  69.95066635  70.00865342  70.04161421
##  [276]  70.04861544  70.18446816  70.34356716  70.61387890  70.67828451
##  [281]  70.73365181  70.94018770  70.94613518  71.09669104  71.46030486
##  [286]  71.57177624  71.81074627  71.96401200  72.16749200  72.16879175
##  [291]  72.34568263  72.52957574  73.00201553  73.04891834  73.09992525
##  [296]  73.10287920  73.15307754  73.59681587  73.85448259  74.49678629
##  [301]  74.66620861  75.29868637  75.39986469  75.57194652  75.70705565
##  [306]  75.93171964  75.93956913  75.94226009  76.20820912  76.64730499
##  [311]  76.79327364  76.99722603  77.01853589  77.06035361  77.19118624
##  [316]  77.59608842  77.60867049  77.63140706  77.69774100  77.72083953
##  [321]  77.84166053  78.05453426  78.23458443  78.32463472  78.42498360
##  [326]  78.48060920  78.54280824  78.55822842  78.59450172  78.83705599
##  [331]  79.05798484  79.15147911  79.17427808  79.18226626  79.23428368
##  [336]  79.26773366  79.44119774  79.45545316  79.48650255  79.69816862
##  [341]  79.77831785  79.96812265  80.07014859  80.12405924  80.44478963
##  [346]  80.52190580  80.67913388  81.29653636  81.31692224  81.36773747
##  [351]  81.42612936  81.66243970  81.71610990  81.75803886  81.80088764
##  [356]  81.80414574  81.81619913  81.91376211  82.00257996  82.01723878
##  [361]  82.02314677  82.10600428  82.20737696  82.47646913  82.55101143
##  [366]  82.76349312  82.78741085  82.84606146  83.08508479  83.16704397
##  [371]  83.18728871  83.21266510  83.27217175  83.43982803  83.53876419
##  [376]  83.74266282  83.77279952  83.92952265  84.21198952  84.29776668
##  [381]  84.32123791  84.32629667  84.39326695  84.51602589  84.55934677
##  [386]  84.61964525  84.71205651  84.73576229  84.77526660  84.79109488
##  [391]  84.86661072  84.93956592  85.10591176  85.62835586  85.65191192
##  [396]  85.66874127  85.75332475  85.85891879  85.97629824  85.99130404
##  [401]  86.03826016  86.05882522  86.07249293  86.79312555  86.81119190
##  [406]  87.13377028  87.17608029  87.22457133  87.24985535  87.27659671
##  [411]  87.31097349  87.41285465  87.50662577  87.54258030  87.84293312
##  [416]  87.92820917  88.08832220  88.40627464  88.56713174  88.65946156
##  [421]  88.86692455  89.06540697  89.07482247  89.38287462  89.41334996
##  [426]  89.62643730  89.65363880  89.79291696  89.81074668  89.86025254
##  [431]  89.93555229  90.07469468  90.24248077  90.24891691  90.31666358
##  [436]  90.38933117  90.40431113  90.42588281  90.58830433  90.78737290
##  [441]  91.07908949  91.18837096  91.53622150  91.64151269  92.02809805
##  [446]  92.31500856  92.72947332  93.23052016  93.24559579  93.35651724
##  [451]  93.46774053  93.81542355  93.87249371  93.99642789  94.08502737
##  [456]  94.13888128  94.69844180  94.72100771  94.91194969  95.08999052
##  [461]  95.50639492  95.58302652  95.59487419  95.69807049  95.98088177
##  [466]  96.02714914  96.10269670  96.30220828  96.36550187  96.61152958
##  [471]  96.86106542  97.02028269  97.03593614  97.09802709  97.16818461
##  [476]  97.26250210  97.37935880  97.53768225  97.67885500  97.68142953
##  [481]  98.03445580  98.21340765  98.33824214  98.39591342  98.40112863
##  [486]  98.41301281  98.44005416  98.44393375  98.46340099  98.55923323
##  [491]  98.83598475  98.85111389  98.90342691  98.95410962  99.04110814
##  [496]  99.13895389  99.39303476  99.46330902  99.71750317  99.75088638
##  [501]  99.94898030 100.81277326 100.89942073 100.93730855 100.97484228
##  [506] 101.11553983 101.13170354 101.17150126 101.21988583 101.47183716
##  [511] 101.55112381 101.73730469 101.89998830 102.06942385 102.22336486
##  [516] 102.31807191 102.32581184 102.69107405 102.82738605 102.86304012
##  [521] 103.19317408 103.30351513 103.47723907 103.65978883 103.85723620
##  [526] 104.14774456 104.36173842 104.46736332 104.62923236 104.80619603
##  [531] 104.86558098 104.91114693 104.93517972 105.09917229 105.30529197
##  [536] 105.65146808 105.78516882 105.96756087 105.98004444 106.26922851
##  [541] 106.56394370 106.66621267 106.77145202 106.84781854 106.97553698
##  [546] 107.09401423 107.19671441 107.36548184 107.40839776 107.83852306
##  [551] 107.94153107 108.23996494 108.31089923 108.51762850 108.64874902
##  [556] 108.66072694 108.99692271 109.18819463 109.24629800 109.42632364
##  [561] 109.61227986 109.65398175 110.03859877 110.14408890 110.31526330
##  [566] 110.37948520 110.45208250 110.50808438 110.51468167 110.55379452
##  [571] 110.62864338 110.64701215 110.78243793 111.13677339 111.27428778
##  [576] 111.33979785 111.38383521 111.41446603 111.62625763 111.81662963
##  [581] 112.07470199 112.18447423 112.23485634 112.43790039 112.45131058
##  [586] 112.78740072 112.85793197 112.90766390 113.09603313 113.15130638
##  [591] 113.19488345 113.28047105 113.32035266 113.34032055 113.71074582
##  [596] 113.82416540 114.06228061 114.18348694 114.25666907 114.54937442
##  [601] 114.72725633 114.78007869 115.25546238 115.34631566 115.42863177
##  [606] 115.65783948 115.71349040 115.86152886 115.99356887 116.13460992
##  [611] 116.13774856 116.24377974 116.37550706 116.54382426 116.69300999
##  [616] 116.91947958 117.00578218 117.13959392 117.61330506 117.62719794
##  [621] 118.10436143 118.35949933 118.62361693 118.72668903 118.84041640
##  [626] 118.85363636 119.04611063 119.22705287 119.24338053 119.48971504
##  [631] 119.51390559 119.54994457 119.62866408 119.68486560 119.75779077
##  [636] 120.01808643 120.27003020 120.30874654 120.51386629 120.76492965
##  [641] 120.81490912 120.87016586 120.96877029 121.03686231 121.27565469
##  [646] 121.41233065 121.54160255 121.62145627 122.01209322 122.15609143
##  [651] 122.56331391 122.62827021 122.71590665 122.80886720 122.94811033
##  [656] 123.39148560 123.44329828 123.65725515 123.74467110 123.88702210
##  [661] 124.03605826 124.14892624 124.57951279 124.74120783 124.76658564
##  [666] 124.79107957 124.90168675 124.95317984 125.20474454 125.26883443
##  [671] 125.29096323 125.33236787 125.35899284 125.45593482 125.54565517
##  [676] 125.57982346 125.86167111 125.90248343 126.05272627 126.05893332
##  [681] 126.08986042 126.41241372 126.53249342 126.64484962 126.95358403
##  [686] 127.08039056 127.11739129 127.24163623 127.44111874 127.59770740
##  [691] 127.73967376 128.03053495 128.13723814 128.15873322 128.39782055
##  [696] 128.40526295 128.42852151 128.55947237 129.40111631 129.52047336
##  [701] 129.61583113 129.64140273 129.74786735 129.75813305 129.88932805
##  [706] 130.22745607 130.44150845 130.60227534 130.81171468 130.96513384
##  [711] 131.17390109 131.18406184 131.39611236 131.46691539 131.67179455
##  [716] 131.78099276 132.17500176 132.20620619 132.22187856 132.40894452
##  [721] 132.65830968 132.68700994 132.69371264 132.76138181 132.98820692
##  [726] 133.01595988 133.04933429 133.14617264 133.29738410 133.36493659
##  [731] 133.55952177 133.56401236 133.58505948 133.88456724 134.21088496
##  [736] 134.56586684 134.68288481 134.79108481 134.81145345 135.38441590
##  [741] 135.54327616 135.57869830 135.64471381 135.83004169 136.14035118
##  [746] 136.19276892 136.21377136 136.26708232 136.29087501 136.32046770
##  [751] 136.53109686 136.67577101 136.67905179 136.78453288 137.06950642
##  [756] 137.07553713 137.09431034 137.18428079 137.22118642 137.29196144
##  [761] 137.61312197 137.73042439 137.74115849 137.78907540 137.82455370
##  [766] 137.85068541 138.23712856 138.34219672 138.37075271 139.26650163
##  [771] 139.28138023 139.31711921 139.59446358 139.61747686 139.67497163
##  [776] 139.80042788 139.86461552 140.29128484 140.31741324 140.64130544
##  [781] 140.78511634 141.18948778 141.25111884 141.27469559 141.54260549
##  [786] 141.58486790 141.69395288 141.72369515 141.90944961 141.93450603
##  [791] 142.06695095 142.74452052 143.10411030 143.20225391 143.37542982
##  [796] 143.47375225 143.60234925 144.21382145 144.22239604 144.23460730
##  [801] 144.33846460 144.34208453 144.34829939 144.51988810 144.64629498
##  [806] 145.01930952 145.04528192 145.14403643 145.59881155 145.85714430
##  [811] 146.05323738 146.06083510 146.21465734 146.27606310 146.32847054
##  [816] 146.58906076 146.67223643 146.69512268 147.54594832 147.57601168
##  [821] 147.70322782 147.73932182 147.89724477 147.95705974 147.99145653
##  [826] 148.05588708 148.42831703 148.79150434 149.01767616 149.34961674
##  [831] 149.37223517 149.65667487 149.66414684 149.76659371 150.02229981
##  [836] 150.33963287 150.36983487 150.39156881 150.39837961 151.18338045
##  [841] 151.24637129 151.40839885 151.42853604 151.58450581 151.73606100
##  [846] 151.99618026 152.55223329 152.63137781 152.76725961 153.10121653
##  [851] 153.12787266 153.15830184 153.25974905 153.29396670 153.31881978
##  [856] 153.75741193 153.89462962 154.03926551 154.14782627 154.32756997
##  [861] 154.66255042 154.73149209 154.99238361 155.08897515 155.10043589
##  [866] 155.31815079 155.46546909 155.87393524 156.11366915 156.39768070
##  [871] 156.44341137 156.50483626 156.56115701 157.50030241 157.75523729
##  [876] 157.76098120 157.76741590 157.78987423 157.94499424 157.97614951
##  [881] 157.99268036 158.19837525 158.63531406 158.67381249 158.77510367
##  [886] 158.80845447 158.81253634 159.02051018 159.08757749 159.20765628
##  [891] 159.25499001 159.88933843 160.05893452 160.10039479 160.28459417
##  [896] 160.77568881 160.80629190 160.88130280 161.35141951 161.47580236
##  [901] 161.65287285 161.77229393 161.92011423 161.99843432 161.99911798
##  [906] 162.22232293 162.42455639 162.77724291 162.81845628 163.08575260
##  [911] 163.55730007 163.68421330 163.85906882 164.17628321 164.22433254
##  [916] 164.34432952 164.36170155 164.48041528 164.48052662 164.69213597
##  [921] 164.70632806 164.78187322 164.92505411 165.05135387 165.83826319
##  [926] 165.90890477 166.23705613 166.35791194 166.47823822 166.88912329
##  [931] 167.25470902 168.39769766 169.38621629 169.42444890 169.51375596
##  [936] 169.78595597 170.21720101 170.27228110 171.31824247 171.46063907
##  [941] 172.15402788 173.01297609 173.53761549 173.64683953 174.55013553
##  [946] 174.59445413 174.81490594 175.12723195 175.92575649 176.12931720
##  [951] 176.30304223 176.98506493 176.99908030 177.16088972 177.33736369
##  [956] 177.74727930 178.95744228 180.25570214 180.97093517 181.54458683
##  [961] 182.86072495 183.92153640 184.71752457 184.88603695 186.86727140
##  [966] 187.20081912 187.58728096 189.00548763 189.26951134 193.89127767
##  [971] 194.53900175 195.53953888 199.82172261 200.60408866 201.32352362
##  [976] 202.76175928 203.08370797 203.41048025 204.26100961 205.72606564
##  [981] 206.74828192 206.88835518 207.75385005 207.92193209 208.46598063
##  [986] 209.30720313 209.67933805 210.98881244 211.02598315 215.00884455
##  [991] 219.64564735 219.95774326 220.53732134 221.49551593 224.15813357
##  [996] 232.22439961 235.00377654 235.03183115 250.64528733 277.05701388
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3&gt; Dados (Terceiro tipo) &lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;## 
## Tabela de frequência 
## Tipo de variável: continuous
## 
##                Classes  Fi     PM   Fr Fac1 Fac2 Fp Fac1p Fac2p
## 1  -62.31 |---  -38.91   2 -50.61 0.00    2 1000  0   0.2 100.0
## 2  -38.91 |---  -15.51   7 -27.21 0.01    9  998  1   0.9  99.8
## 3    -15.51 |---  7.89  21  -3.81 0.02   30  991  2   3.0  99.1
## 4     7.89 |---  31.29  59  19.59 0.06   89  970  6   8.9  97.0
## 5    31.29 |---  54.69  86  42.99 0.09  175  911  9  17.5  91.1
## 6    54.69 |---  78.09 147  66.39 0.15  322  825 15  32.2  82.5
## 7   78.09 |---  101.49 188  89.79 0.19  510  678 19  51.0  67.8
## 8  101.49 |---  124.89 156 113.19 0.16  666  490 16  66.6  49.0
## 9  124.89 |---  148.29 160 136.59 0.16  826  334 16  82.6  33.4
## 10 148.29 |---  171.69 114 159.99 0.11  940  174 11  94.0  17.4
## 11 171.69 |---  195.09  31 183.39 0.03  971   60  3  97.1   6.0
## 12 195.09 |---  218.49  19 206.79 0.02  990   29  2  99.0   2.9
## 13 218.49 |---  241.89   8 230.19 0.01  998   10  1  99.8   1.0
## 14 241.89 |---  265.29   1 253.59 0.00  999    2  0  99.9   0.2
## 15 265.29 |---  288.69   1 276.99 0.00 1000    1  0 100.0   0.1
## 
##  ============================================== 
## Classes: Agrupamento de classes 
## Fi: Frequência absoluta 
## PM: Ponto médio 
## Fr: Frequência relativa 
## Fac1: Frequência acumulada (abaixo de) 
## Fac2: Frequência acumulada (acima de) 
## Fp: Frequência percentual 
## Fac1p: Frequência acumulada percentual (abaixo de) 
## Fac2p: Frequência acumulada percentual (acima de)
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3&gt; Dados (Quarto tipo) &lt;/h3&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s03/index_files/figure-html/unnamed-chunk-4-1.png&#34; width=&#34;672&#34; /&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;coleta-dados-brutos&#34;&gt;Coleta (Dados brutos)&lt;/h2&gt;
&lt;p&gt;Dados elaborados sobre o número de erros encontrados em 20 conjunto de caracteres monitorado em um canal de comunicação&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:right&#34;&gt;3&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;0&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;3&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;4&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;3&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;2&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;3&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;0&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;2&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;3&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;2&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;2&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;dados-em-rol-ou-elaborados&#34;&gt;Dados em rol ou elaborados&lt;/h2&gt;
&lt;p&gt;Dados elaborados sobre o número de erros encontrados em 20 conjunto de caracteres monitorado em um canal de comunicação&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:right&#34;&gt;0&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;0&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;0&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:right&#34;&gt;2&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;2&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;2&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;2&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;3&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;3&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;3&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;3&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;3&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;section&gt;
&lt;h2&gt; Distribuição de frequência &lt;/h2&gt;
&lt;h3&gt;Frequência absoluta&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:center&#34;&gt;Número de erros &lt;code&gt;\((x_i)\)&lt;/code&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;Frequência simples ($f_i$)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;1&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;2&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;3&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;4&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;Total&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;20&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h3&gt;Frequência relativa&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:center&#34;&gt;Número de erros &lt;code&gt;\((x_i)\)&lt;/code&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(f_i\)&lt;/code&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(f_{r_i}\)&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(3\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(3 / 20 = 0,15\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(1\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(7\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(7 / 20 = 0,35\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(2\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(4\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(4 / 20 = 0,20\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(3\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(5\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(5 / 20 = 0,25\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(4\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(1\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(1 / 20 = 0,05\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h3&gt;Frequência percentual&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:center&#34;&gt;Número de erros &lt;code&gt;\((x_i)\)&lt;/code&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(f_i\)&lt;/code&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(f_{r_i}\)&lt;/code&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(f_{\%_i}\)&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(3\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,15\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,15 \times 100 = 15\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(1\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(7\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,35\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,35 \times 100 = 35\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(2\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(4\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,20\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,20 \times 100 = 20\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(3\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(5\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,25\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,25 \times 100 = 25\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(4\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(1\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,05\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,05 \times 100 = 5\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;Total&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(20\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(1\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(100\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h3&gt;Tabela completa&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:center&#34;&gt;Número de erros &lt;code&gt;\((x_i)\)&lt;/code&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(f_i\)&lt;/code&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(f_{r_i}\)&lt;/code&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(f_{\%_i}\)&lt;/code&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(f_{ac\downarrow_i}\)&lt;/code&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(f_{ac\uparrow_i}\)&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(3\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,15\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(15\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(3\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(20\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(1\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(7\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,35\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(35\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(10\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(17\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(2\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(4\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,20\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(35\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(14\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(10\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(3\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(5\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,25\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(25\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(19\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(6\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(4\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(1\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,05\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(5\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(20\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(1\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;Total&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(20\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(1\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(100\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;section&gt;
&lt;h2&gt;Tabela para V. contínua (Algoritmo) &lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:center&#34;&gt;Classe&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;$ F_i $&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;$ Li_{1a} \vdash  Ls_{1a} $&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;$ f_1 $&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;$ Li_{2a} \vdash  Ls_{2a} $&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;$ f_2 $&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;$ \vdots $&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;$ \vdots $&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;$ Li_{ka}  \vdash Ls_{ka} $&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;$ f_k $&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;pre&gt; 1º Passo - Número de classes &lt;/pre&gt;
&lt;p&gt;&lt;code&gt;\begin{align} k &amp;amp; \approx \left\{\begin{array}{ll} \sqrt{\textrm{número de elementos}}, &amp;amp; n \leq 100 \\ 5log_{10}(\textrm{número de elementos}), &amp;amp; n &amp;gt; 100 \end{array}\right. \end{align}&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt; 2º Passo - Amplitude total &lt;/pre&gt;
&lt;p&gt;&lt;code&gt;\begin{align} A_t &amp;amp; = \max_i(X_i) - \min_i(X_i), \end{align}&lt;/code&gt;
para &lt;code&gt;\(i \in \mathbb{N}^{+}\)&lt;/code&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;pre&gt; 3º Passo - Amplitude de classe &lt;/pre&gt;
&lt;p&gt;&lt;code&gt;\begin{align} c &amp;amp; = \left\{\begin{array}{ll} \frac{A_t}{k - 1}, &amp;amp; \textrm{Amostra} \\ \frac{A_t}{k}, &amp;amp; \textrm{População}. \end{array}\right. \end{align}&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt; 4º Passo - LI da primeira classe &lt;/pre&gt;
&lt;p&gt;&lt;code&gt;\begin{align} Li_{1a} &amp;amp; = \left\{\begin{array}{ll} X_{(1)} - c / 2, &amp;amp; \textrm{Amostra} \\ X_{(1)}, &amp;amp; \textrm{População}. \end{array}\right. \end{align}&lt;/code&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt; Em resumo... &lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Calcular &lt;code&gt;\(k\)&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;Calcular &lt;code&gt;\(A_t\)&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;Calcular &lt;code&gt;\(c\)&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;Calcular &lt;code&gt;\(Li_{1a}\)&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;Determinar as classes,&lt;/li&gt;
&lt;li&gt;Calcular o ponto médio, e&lt;/li&gt;
&lt;li&gt;Calcular as frequências como apresentadas no início dessa seção.&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;gráficos&#34;&gt;Gráficos&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Gráfico de Haste ou bastão&lt;/li&gt;
&lt;li&gt;Gráfico de barras&lt;/li&gt;
&lt;li&gt;Gráfico de Pizza&lt;/li&gt;
&lt;li&gt;Histograma de frequências&lt;/li&gt;
&lt;li&gt;Ogivas&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;section&gt;
&lt;h2&gt; Uso do pacote &lt;code&gt;leem&lt;/code&gt; &lt;/h2&gt;














&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/profmat-est/s03/leem_hu7b1031bcd7f556bee541df85c0c5375e_34750_3761f4b815fffe33ceb7dbc21c169f83.webp 400w,
               /slides/profmat-est/s03/leem_hu7b1031bcd7f556bee541df85c0c5375e_34750_3705f9ee693abc73a6049df605c75df5.webp 760w,
               /slides/profmat-est/s03/leem_hu7b1031bcd7f556bee541df85c0c5375e_34750_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/profmat-est/s03/leem_hu7b1031bcd7f556bee541df85c0c5375e_34750_3761f4b815fffe33ceb7dbc21c169f83.webp&#34;
               width=&#34;150&#34;
               height=&#34;150&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;p&gt;Instalação&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;install.packages(&amp;quot;devtools&amp;quot;)
devtools::install_github(&amp;quot;bendeivide/leem&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Anexando e carregando&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;library(leem)
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt; Funções &lt;/h2&gt;
&lt;!-- | Função     | Finalidade                  | --&gt;
&lt;!-- |:-----------|:----------------------------| --&gt;
&lt;!-- | new_leem() | Construtor da classe *leem* | --&gt;
&lt;!-- | tabfreq()  | Disatribuição de frequência | --&gt;
&lt;!-- | hist()     | Hitograma de frequência     | --&gt;
&lt;!-- | ogive()    | Ogivas                      | --&gt;
&lt;!-- | polyfreq() | Polígono de frequências     | --&gt;
&lt;style type=&#34;text/css&#34;&gt;
.tg  {border-collapse:collapse;border-color:#93a1a1;border-spacing:0;}
.tg td{background-color:#fdf6e3;border-bottom-width:1px;border-color:#93a1a1;border-style:solid;border-top-width:1px;
  border-width:0px;color:#002b36;font-family:Arial, sans-serif;font-size:14px;overflow:hidden;padding:10px 5px;
  word-break:normal;}
.tg th{background-color:#657b83;border-bottom-width:1px;border-color:#93a1a1;border-style:solid;border-top-width:1px;
  border-width:0px;color:#fdf6e3;font-family:Arial, sans-serif;font-size:14px;font-weight:normal;overflow:hidden;
  padding:10px 5px;word-break:normal;}
.tg .tg-5lw0{background-color:#eee8d5;border-color:#ffffff;
  font-family:&#34;Lucida Sans Unicode&#34;, &#34;Lucida Grande&#34;, sans-serif !important;font-size:28px;text-align:left;
  vertical-align:middle}
.tg .tg-xzvq{border-color:#ffffff;font-family:&#34;Lucida Sans Unicode&#34;, &#34;Lucida Grande&#34;, sans-serif !important;font-size:28px;
  text-align:left;vertical-align:middle}
.tg .tg-vqs5{border-color:#ffffff;font-family:&#34;Lucida Sans Unicode&#34;, &#34;Lucida Grande&#34;, sans-serif !important;font-size:28px;
  font-weight:bold;text-align:left;vertical-align:middle}
&lt;/style&gt;
&lt;table class=&#34;tg&#34;&gt;
&lt;thead&gt;
  &lt;tr&gt;
    &lt;th class=&#34;tg-vqs5&#34;&gt;Função&lt;/th&gt;
    &lt;th class=&#34;tg-vqs5&#34;&gt;Finalidade&lt;/th&gt;
  &lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
  &lt;tr&gt;
    &lt;td class=&#34;tg-5lw0&#34;&gt; &lt;code&gt;base::sort()&lt;/code&gt;  &lt;/td&gt;
    &lt;td class=&#34;tg-5lw0&#34;&gt;Dados em rol &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td class=&#34;tg-5lw0&#34;&gt; &lt;code&gt;new_leem()&lt;/code&gt;  &lt;/td&gt;
    &lt;td class=&#34;tg-5lw0&#34;&gt;Construtor da classe &lt;i&gt;leem&lt;/i&gt; &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td class=&#34;tg-xzvq&#34;&gt; &lt;code&gt;tabfreq()&lt;/code&gt;  &lt;/td&gt;
    &lt;td class=&#34;tg-xzvq&#34;&gt;Distribuição de frequência&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td class=&#34;tg-5lw0&#34;&gt; &lt;code&gt;hist()&lt;/code&gt; &lt;/td&gt;
    &lt;td class=&#34;tg-5lw0&#34;&gt;Hitograma de frequência&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td class=&#34;tg-xzvq&#34;&gt; &lt;code&gt;ogive()&lt;/code&gt; &lt;/td&gt;
    &lt;td class=&#34;tg-xzvq&#34;&gt;Ogivas&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td class=&#34;tg-5lw0&#34;&gt; &lt;code&gt;polyfreq()&lt;/code&gt; &lt;/td&gt;
    &lt;td class=&#34;tg-5lw0&#34;&gt;Polígono de frequências&lt;/td&gt;
  &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td class=&#34;tg-5lw0&#34;&gt; &lt;code&gt;stickchart()&lt;/code&gt; &lt;/td&gt;
    &lt;td class=&#34;tg-5lw0&#34;&gt;Gráfico de hastes ou bastão&lt;/td&gt;
  &lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt; Exemplo &lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Considere a distribuição de frequência do número de erros encontrados em 20 conjunto de carac-  teres monitorado em um canal de comunicação&lt;/li&gt;
&lt;/ol&gt;
&lt;style type=&#34;text/css&#34;&gt;
.tg  {border-collapse:collapse;border-color:#93a1a1;border-spacing:0;}
.tg td{background-color:#fdf6e3;border-bottom-width:1px;border-color:#93a1a1;border-style:solid;border-top-width:1px;
  border-width:0px;color:#002b36;font-family:Arial, sans-serif;font-size:14px;overflow:hidden;padding:10px 5px;
  word-break:normal;}
.tg th{background-color:#657b83;border-bottom-width:1px;border-color:#93a1a1;border-style:solid;border-top-width:1px;
  border-width:0px;color:#fdf6e3;font-family:Arial, sans-serif;font-size:14px;font-weight:normal;overflow:hidden;
  padding:10px 5px;word-break:normal;}
.tg .tg-j4p1{background-color:#eee8d5;color:#191919;font-family:&#34;Lucida Sans Unicode&#34;, &#34;Lucida Grande&#34;, sans-serif !important;
  font-size:28px;font-style:italic;font-weight:bold;text-align:right;vertical-align:middle}
.tg .tg-1bo1{background-color:#ffffff;border-color:#fdf6e3;
  font-family:&#34;Lucida Sans Unicode&#34;, &#34;Lucida Grande&#34;, sans-serif !important;font-size:28px;font-style:italic;
  font-weight:bold;text-align:right;vertical-align:middle}
&lt;/style&gt;
&lt;table class=&#34;tg&#34;&gt;
&lt;thead&gt;
  &lt;tr&gt;
    &lt;th class=&#34;tg-j4p1&#34;&gt;&lt;span style=&#34;font-weight:700&#34;&gt;3&lt;/span&gt;&lt;/th&gt;
    &lt;th class=&#34;tg-j4p1&#34;&gt;&lt;span style=&#34;font-weight:700&#34;&gt;0&lt;/span&gt;&lt;/th&gt;
    &lt;th class=&#34;tg-j4p1&#34;&gt;&lt;span style=&#34;font-weight:700&#34;&gt;3&lt;/span&gt;&lt;/th&gt;
    &lt;th class=&#34;tg-j4p1&#34;&gt;&lt;span style=&#34;font-weight:700&#34;&gt;4&lt;/span&gt;&lt;/th&gt;
    &lt;th class=&#34;tg-j4p1&#34;&gt;&lt;span style=&#34;font-weight:700&#34;&gt;3&lt;/span&gt;&lt;/th&gt;
    &lt;th class=&#34;tg-j4p1&#34;&gt;&lt;span style=&#34;font-weight:700&#34;&gt;1&lt;/span&gt;&lt;/th&gt;
    &lt;th class=&#34;tg-j4p1&#34;&gt;&lt;span style=&#34;font-weight:700&#34;&gt;2&lt;/span&gt;&lt;/th&gt;
    &lt;th class=&#34;tg-j4p1&#34;&gt;&lt;span style=&#34;font-weight:700&#34;&gt;3&lt;/span&gt;&lt;/th&gt;
    &lt;th class=&#34;tg-j4p1&#34;&gt;&lt;span style=&#34;font-weight:700&#34;&gt;0&lt;/span&gt;&lt;/th&gt;
    &lt;th class=&#34;tg-j4p1&#34;&gt;&lt;span style=&#34;font-weight:700&#34;&gt;0&lt;/span&gt;&lt;/th&gt;
  &lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
  &lt;tr&gt;
    &lt;td class=&#34;tg-1bo1&#34;&gt;1&lt;/td&gt;
    &lt;td class=&#34;tg-1bo1&#34;&gt;1&lt;/td&gt;
    &lt;td class=&#34;tg-1bo1&#34;&gt;2&lt;/td&gt;
    &lt;td class=&#34;tg-1bo1&#34;&gt;1&lt;/td&gt;
    &lt;td class=&#34;tg-1bo1&#34;&gt;1&lt;/td&gt;
    &lt;td class=&#34;tg-1bo1&#34;&gt;1&lt;/td&gt;
    &lt;td class=&#34;tg-1bo1&#34;&gt;3&lt;/td&gt;
    &lt;td class=&#34;tg-1bo1&#34;&gt;2&lt;/td&gt;
    &lt;td class=&#34;tg-1bo1&#34;&gt;2&lt;/td&gt;
    &lt;td class=&#34;tg-1bo1&#34;&gt;1&lt;/td&gt;
  &lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Exemplo&lt;/h2&gt;
&lt;ol start=&#34;2&#34;&gt;
&lt;li&gt;Os dados representam a temperatura (°F) do anel de vedação de cada teste de acionamento ou lançamento real do motor do foguete Challenger.&lt;/li&gt;
&lt;/ol&gt;
&lt;style type=&#34;text/css&#34;&gt;
.tg  {border-collapse:collapse;border-color:#93a1a1;border-spacing:0;}
.tg td{background-color:#fdf6e3;border-bottom-width:1px;border-color:#93a1a1;border-style:solid;border-top-width:1px;
  border-width:0px;color:#002b36;font-family:Arial, sans-serif;font-size:14px;overflow:hidden;padding:10px 5px;
  word-break:normal;}
.tg th{background-color:#657b83;border-bottom-width:1px;border-color:#93a1a1;border-style:solid;border-top-width:1px;
  border-width:0px;color:#fdf6e3;font-family:Arial, sans-serif;font-size:14px;font-weight:normal;overflow:hidden;
  padding:10px 5px;word-break:normal;}
.tg .tg-61io{background-color:#eee8d5;color:#191919;font-size:28px;font-style:italic;font-weight:bold;text-align:left;
  vertical-align:middle}
.tg .tg-8svn{background-color:#fdf6e3;color:#191919;font-size:28px;font-style:italic;font-weight:bold;text-align:left;
  vertical-align:middle}
.tg .tg-aete{background-color:#fdf6e3;color:#191919;font-family:&#34;Lucida Sans Unicode&#34;, &#34;Lucida Grande&#34;, sans-serif !important;
  font-size:28px;font-style:italic;font-weight:bold;text-align:left;vertical-align:middle}
.tg .tg-4ynv{background-color:#eee8d5;color:#191919;font-family:&#34;Lucida Sans Unicode&#34;, &#34;Lucida Grande&#34;, sans-serif !important;
  font-size:28px;font-style:italic;font-weight:bold;text-align:left;vertical-align:middle}
.tg .tg-uika{color:#191919;font-size:28px;font-style:italic;font-weight:bold;text-align:left;vertical-align:middle}
&lt;/style&gt;
&lt;table class=&#34;tg&#34;&gt;
&lt;thead&gt;
  &lt;tr&gt;
    &lt;th class=&#34;tg-aete&#34;&gt;84&lt;/th&gt;
    &lt;th class=&#34;tg-aete&#34;&gt;49&lt;/th&gt;
    &lt;th class=&#34;tg-aete&#34;&gt;61&lt;/th&gt;
    &lt;th class=&#34;tg-aete&#34;&gt;40&lt;/th&gt;
    &lt;th class=&#34;tg-aete&#34;&gt;83&lt;/th&gt;
    &lt;th class=&#34;tg-aete&#34;&gt;67&lt;/th&gt;
    &lt;th class=&#34;tg-aete&#34;&gt;45&lt;/th&gt;
    &lt;th class=&#34;tg-aete&#34;&gt;66&lt;/th&gt;
    &lt;th class=&#34;tg-aete&#34;&gt;70&lt;/th&gt;
    &lt;th class=&#34;tg-aete&#34;&gt;69&lt;/th&gt;
    &lt;th class=&#34;tg-8svn&#34;&gt;80&lt;/th&gt;
    &lt;th class=&#34;tg-8svn&#34;&gt;58&lt;/th&gt;
  &lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
  &lt;tr&gt;
    &lt;td class=&#34;tg-4ynv&#34;&gt;68&lt;/td&gt;
    &lt;td class=&#34;tg-4ynv&#34;&gt;60&lt;/td&gt;
    &lt;td class=&#34;tg-4ynv&#34;&gt;67&lt;/td&gt;
    &lt;td class=&#34;tg-4ynv&#34;&gt;72&lt;/td&gt;
    &lt;td class=&#34;tg-4ynv&#34;&gt;73&lt;/td&gt;
    &lt;td class=&#34;tg-4ynv&#34;&gt;70&lt;/td&gt;
    &lt;td class=&#34;tg-4ynv&#34;&gt;57&lt;/td&gt;
    &lt;td class=&#34;tg-4ynv&#34;&gt;63&lt;/td&gt;
    &lt;td class=&#34;tg-4ynv&#34;&gt;70&lt;/td&gt;
    &lt;td class=&#34;tg-4ynv&#34;&gt;78&lt;/td&gt;
    &lt;td class=&#34;tg-61io&#34;&gt;52&lt;/td&gt;
    &lt;td class=&#34;tg-61io&#34;&gt;67&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td class=&#34;tg-uika&#34;&gt;53&lt;/td&gt;
    &lt;td class=&#34;tg-uika&#34;&gt;67&lt;/td&gt;
    &lt;td class=&#34;tg-uika&#34;&gt;75&lt;/td&gt;
    &lt;td class=&#34;tg-uika&#34;&gt;61&lt;/td&gt;
    &lt;td class=&#34;tg-uika&#34;&gt;70&lt;/td&gt;
    &lt;td class=&#34;tg-uika&#34;&gt;81&lt;/td&gt;
    &lt;td class=&#34;tg-uika&#34;&gt;76&lt;/td&gt;
    &lt;td class=&#34;tg-uika&#34;&gt;79&lt;/td&gt;
    &lt;td class=&#34;tg-uika&#34;&gt;75&lt;/td&gt;
    &lt;td class=&#34;tg-uika&#34;&gt;76&lt;/td&gt;
    &lt;td class=&#34;tg-uika&#34;&gt;58&lt;/td&gt;
    &lt;td class=&#34;tg-uika&#34;&gt;31&lt;/td&gt;
  &lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;style&gt;
.container{
  display: grid;
  text-align: center;
  grid-auto-flow: column;
}
.col {
  width: 500px;
  height: 400px;
  border: 3px solid #0094ff;
}
.col2 {
  width: 500px;
  height: 500px;
  border: 3px solid #0094ff;
}
.col3 {
  width: 500px;
  height: 450px;
  border: 3px solid #0094ff;
}

&lt;/style&gt;
&lt;section&gt;
&lt;h1&gt; &lt;code&gt;leem&lt;/code&gt; em ação &lt;/h1&gt;
&lt;hr&gt;
&lt;h2&gt; Importando os dados &lt;/h2&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;# Numero de erros
d1 &amp;lt;- read.table(&amp;quot;https://raw.githubusercontent.com/bendeivide/book-epaec/master/dados/cap02/nerros.txt&amp;quot;, h = TRUE)
(d1 &amp;lt;- d1$erros)

# Temperatura do foguete Challenger
d2 &amp;lt;- read.table(&amp;quot;https://raw.githubusercontent.com/bendeivide/book-epaec/master/dados/cap02/challenger.txt&amp;quot;, h = TRUE)
(d2 &amp;lt;- d2$chal)

&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;pre&gt;&lt;code&gt;##  [1] 3 1 0 1 3 2 4 1 3 1 1 1 2 3 3 2 0 2 0 1
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;##  [1] 84 49 61 40 83 67 45 66 70 69 80 58 68 60 67 72 73 70 57 63 70 78 52 67 53
## [26] 67 75 61 70 81 76 79 75 76 58 31
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h2&gt; Dados em rol &lt;/h2&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;sort(d1)
sort(d2)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;pre&gt;&lt;code&gt;##  [1] 0 0 0 1 1 1 1 1 1 1 2 2 2 2 3 3 3 3 3 4
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;##  [1] 31 40 45 49 52 53 57 58 58 60 61 61 63 66 67 67 67 67 68 69 70 70 70 70 72
## [26] 73 75 75 76 76 78 79 80 81 83 84
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h2&gt; Distribuição de frequências &lt;/h2&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col2&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;## Forma convencional:
aux &amp;lt;- new_leem(d1, 1)
tabd1 &amp;lt;- tabfreq(aux); tabd1
#-----
aux &amp;lt;- new_leem(d2, 2)
tabd2 &amp;lt;- tabfreq(aux); tabd2
## Usando o operador &#39;pipe&#39; nativo
d1 |&amp;gt; new_leem(variable = 1) |&amp;gt; tabfreq()
d2 |&amp;gt; new_leem(variable = 2) |&amp;gt; tabfreq()
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col2&#34;&gt;
&lt;pre&gt;&lt;code&gt;## 
## Tabela de frequência 
## Tipo de variável: discrete
## 
##   Groups Fi   Fr Fac1 Fac2 Fp Fac1p Fac2p
## 1      0  3 0.15    3   20 15    15   100
## 2      1  7 0.35   10   17 35    50    85
## 3      2  4 0.20   14   10 20    70    50
## 4      3  5 0.25   19    6 25    95    30
## 5      4  1 0.05   20    1  5   100     5
## ============================================== 
## Groups: Agrupamento discretizado 
## Fi: Frequência absoluta 
## Fr: Frequência relativa 
## Fac1: Frequência acumulada (abaixo de) 
## Fac2: Frequência acumulada (acima de) 
## Fp: Frequência percentual 
## Fac1p: Frequência acumulada percentual (abaixo de) 
## Fac2p: Frequência acumulada percentual (acima de)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## 
## Tabela de frequência 
## Tipo de variável: continuous
## 
##           Classes Fi   PM   Fr Fac1 Fac2 Fp  Fac1p  Fac2p
## 1 25.7 |---  36.3  1 31.0 0.03    1   36  3   2.78 100.00
## 2 36.3 |---  46.9  2 41.6 0.06    3   35  6   8.33  97.22
## 3 46.9 |---  57.5  4 52.2 0.11    7   33 11  19.44  91.67
## 4 57.5 |---  68.1 12 62.8 0.33   19   29 33  52.78  80.56
## 5 68.1 |---  78.7 12 73.4 0.33   31   17 33  86.11  47.22
## 6 78.7 |---  89.3  5 84.0 0.14   36    5 14 100.00  13.89
## 
##  ============================================== 
## Classes: Agrupamento de classes 
## Fi: Frequência absoluta 
## PM: Ponto médio 
## Fr: Frequência relativa 
## Fac1: Frequência acumulada (abaixo de) 
## Fac2: Frequência acumulada (acima de) 
## Fp: Frequência percentual 
## Fac1p: Frequência acumulada percentual (abaixo de) 
## Fac2p: Frequência acumulada percentual (acima de)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h2&gt; Apresentação gráfica &lt;/h2&gt;
&lt;h3&gt;Gráfico de hastes ou bastão&lt;/h3&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;# Forma convencional:
aux1 &amp;lt;- new_leem(d1, variable = &amp;quot;discrete&amp;quot;)
aux2 &amp;lt;- tabfreq(aux1)
stickchart(aux2,
          lwd=3, # largura da linha
          pcol = &amp;quot;red&amp;quot;, # cor da linha
          bgcol = &amp;quot;lightgray&amp;quot;, # cor do fundo
          panel.first = grid(col = &amp;quot;white&amp;quot;) # inserindo grid e sua cor
         )
# Usando o pipe
d1 |&amp;gt;
  new_leem(variable = &amp;quot;discrete&amp;quot;) |&amp;gt;
  tabfreq() |&amp;gt;
  stickchart(lwd=3, # largura da linha
            pcol = &amp;quot;red&amp;quot;, # cor da linha
            bgcol = &amp;quot;lightgray&amp;quot;, # cor do fundo
            panel.first = grid(col = &amp;quot;white&amp;quot;) # inserindo grid e sua cor
            )
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s03/index_files/figure-html/unnamed-chunk-11-1.png&#34; width=&#34;672&#34; /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h3&gt;Gráfico de barras&lt;/h3&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;# Forma convencional:
aux1 &amp;lt;- new_leem(d1, variable = 1)
aux2 &amp;lt;- tabfreq(aux1)
barplot(aux2, barcol = heat.colors(5))
# Usando o pipe
d1 |&amp;gt;
  new_leem(variable = 1) |&amp;gt;
    tabfreq() |&amp;gt;
      barplot(barcol = heat.colors(5))
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s03/index_files/figure-html/unnamed-chunk-12-1.png&#34; width=&#34;672&#34; /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h3&gt;Histograma de frequências&lt;/h3&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;# Usando o pipe:
d2 |&amp;gt;
  new_leem(variable = 2) |&amp;gt;
    tabfreq() |&amp;gt;
      hist(barcol = heat.colors(6))
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s03/index_files/figure-html/unnamed-chunk-13-1.png&#34; width=&#34;672&#34; /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h3&gt;Polígono&lt;/h3&gt;
&lt;h4&gt;Dados discretos&lt;/h4&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;# Usando o pipe:
d1 |&amp;gt;
  new_leem(variable = 1) |&amp;gt;
    tabfreq() |&amp;gt;
      polyfreq(barcol = heat.colors(5),
           main = &amp;quot;Polígono de frequências e
Histograma de frequências&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s03/index_files/figure-html/unnamed-chunk-14-1.png&#34; width=&#34;672&#34; /&gt;
&lt;pre&gt;&lt;code&gt;## 
##  Note: The polygon graph has interpretation problems for the discrete quantitative variable
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h3&gt;Polígono&lt;/h3&gt;
&lt;h4&gt;Dados contínuos&lt;/h4&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;# Usando o pipe:
d2 |&amp;gt;
  new_leem(variable = 2) |&amp;gt;
    tabfreq() |&amp;gt;
      polyfreq(barcol = heat.colors(5),
           main = &amp;quot;Polígono de frequências e
Histograma de frequências&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s03/index_files/figure-html/unnamed-chunk-15-1.png&#34; width=&#34;672&#34; /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h3&gt;Polígono&lt;/h3&gt;
&lt;h4&gt;Sem as barras&lt;/h4&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;# Usando o pipe:
d2 |&amp;gt;
  new_leem(variable = 2) |&amp;gt;
    tabfreq() |&amp;gt;
      polyfreq(bars = FALSE)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s03/index_files/figure-html/unnamed-chunk-16-1.png&#34; width=&#34;672&#34; /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h3&gt;Ogivas&lt;/h3&gt;
&lt;h4&gt;Dados discretos (Crescente)&lt;/h4&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;# Usando o pipe:
d1 |&amp;gt;
  new_leem(variable = 1) |&amp;gt;
    tabfreq() |&amp;gt;
      ogive(bars = TRUE, barcol = &amp;quot;red&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s03/index_files/figure-html/unnamed-chunk-17-1.png&#34; width=&#34;672&#34; /&gt;
&lt;pre&gt;&lt;code&gt;## 
##  Note: The ogive graph has interpretation problems for the discrete quantitative variable
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h3&gt;Ogivas&lt;/h3&gt;
&lt;h4&gt;Dados discretos (Decrescente)&lt;/h4&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;d1 |&amp;gt;
  new_leem(variable = 1) |&amp;gt;
   tabfreq() |&amp;gt;
    ogive(decreasing = TRUE,
        bars = TRUE, barcol = &amp;quot;yellow&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s03/index_files/figure-html/unnamed-chunk-18-1.png&#34; width=&#34;672&#34; /&gt;
&lt;pre&gt;&lt;code&gt;## 
##  Note: The ogive graph has interpretation problems for the discrete quantitative variable
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h3&gt;Ogivas&lt;/h3&gt;
&lt;h4&gt;Dados discretos (Ambos)&lt;/h4&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;d1 |&amp;gt;
  new_leem(variable = 1) |&amp;gt;
  tabfreq() |&amp;gt;
  ogive(both = TRUE, # ambas ogivas
        bars = TRUE, # barras
        barcol = c(&amp;quot;red&amp;quot;, &amp;quot;yellow&amp;quot;))
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s03/index_files/figure-html/unnamed-chunk-19-1.png&#34; width=&#34;672&#34; /&gt;
&lt;pre&gt;&lt;code&gt;## 
##  Note: The ogive graph has interpretation problems for the discrete quantitative variable
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h3&gt;Ogivas&lt;/h3&gt;
&lt;h4&gt;Dados contínuos (Crescente)&lt;/h4&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;d2 |&amp;gt;
  new_leem(variable = 2) |&amp;gt;
  tabfreq() |&amp;gt;
  ogive(bars = TRUE, barcol = &amp;quot;red&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s03/index_files/figure-html/unnamed-chunk-20-1.png&#34; width=&#34;672&#34; /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h3&gt;Ogivas&lt;/h3&gt;
&lt;h4&gt;Dados contínuos (Decrescente)&lt;/h4&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;d2 |&amp;gt;
  new_leem(variable = 2) |&amp;gt;
  tabfreq() |&amp;gt;
  ogive(decreasing = TRUE,
        bars = TRUE, barcol = &amp;quot;yellow&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s03/index_files/figure-html/unnamed-chunk-21-1.png&#34; width=&#34;672&#34; /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h3&gt;Ogivas&lt;/h3&gt;
&lt;h4&gt;Dados contínuos (Ambos)&lt;/h4&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;d2 |&amp;gt;
  new_leem(variable = 2) |&amp;gt;
  tabfreq() |&amp;gt;
  ogive(both = TRUE, # ambas ogivas
        bars = TRUE, # barras
        barcol = c(&amp;quot;red&amp;quot;, &amp;quot;yellow&amp;quot;))
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s03/index_files/figure-html/unnamed-chunk-22-1.png&#34; width=&#34;672&#34; /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h3&gt;Ogivas&lt;/h3&gt;
&lt;h4&gt;Dados contínuos (Ambos + Histograma)&lt;/h4&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;d2 |&amp;gt;
  new_leem(variable = 2) |&amp;gt;
  tabfreq() |&amp;gt;
  ogive(both = TRUE, # ambas ogivas
        bars = TRUE, # barras
        barcol = c(&amp;quot;red&amp;quot;, &amp;quot;yellow&amp;quot;), # cor da barra das duas ogivas
        histogram = TRUE, # incluindo o histograma
        histcol = gray.colors(6), # cor do histograma
        bgcol = &amp;quot;purple&amp;quot;) # cor do fundo
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s03/index_files/figure-html/unnamed-chunk-23-1.png&#34; width=&#34;672&#34; /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h1 id=&#34;questões&#34;&gt;Questões?&lt;/h1&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Dúvidas e Sugestões&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/#contact&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Contato&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;!-- https://revealjs.com/transitions/ --&gt;
&lt;section data-transition=&#34;zoom&#34;&gt;
  &lt;h1&gt;Próximas aulas...&lt;/h1&gt;
&lt;/section&gt;
&lt;section data-transition-speed=&#34;fast&#34;&gt;
&lt;a href=&#34;http://bendeivide.github.io/courses/epaec&#34; target=&#34;_blank&#34;&gt;














&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/profmat-est/s03/ben_hu087225affb9399e037f09661c4d0adbd_219224_5c10d459c8ddc0416f506a4ad838a085.webp 400w,
               /slides/profmat-est/s03/ben_hu087225affb9399e037f09661c4d0adbd_219224_29ebba9a3e515b23ea411bffea18d2f1.webp 760w,
               /slides/profmat-est/s03/ben_hu087225affb9399e037f09661c4d0adbd_219224_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/profmat-est/s03/ben_hu087225affb9399e037f09661c4d0adbd_219224_5c10d459c8ddc0416f506a4ad838a085.webp&#34;
               width=&#34;630&#34;
               height=&#34;480&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;
&lt;p&gt;&lt;a href=&#34;http://bendeivide.github.io/courses/epaec&#34; target=&#34;_blank&#34;&gt;bendeivide.github.io/courses/epaec&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;!-- &lt;section&gt; --&gt;
&lt;!--   &lt;h2&gt;Some Slide&lt;/h2&gt; --&gt;
&lt;!--   &lt;aside class=&#34;notes&#34;&gt; --&gt;
&lt;!--     Anotações no Visualizador (Clique em S) 📝 --&gt;
&lt;!--   &lt;/aside&gt; --&gt;
&lt;!-- &lt;/section&gt; --&gt;
&lt;!-- ## Animação --&gt;
&lt;!-- &lt;section data-auto-animate&gt; --&gt;
&lt;!--   &lt;h1&gt;Auto-Animate&lt;/h1&gt; --&gt;
&lt;!-- &lt;/section&gt; --&gt;
&lt;!-- &lt;section data-auto-animate&gt; --&gt;
&lt;!--   &lt;h1 style=&#34;margin-top: 100px; color: red;&#34;&gt;Auto-Animate&lt;/h1&gt; --&gt;
&lt;!-- &lt;/section&gt; --&gt;
</description>
    </item>
    
    <item>
      <title>Estatística e Probabilidade</title>
      <link>http://bendeivide.github.io/slides/profmat-est/s04/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/profmat-est/s04/</guid>
      <description>
&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap.png&#34;
  &gt;

&lt;h1 id=&#34;estatística-e-probabilidade&#34;&gt;Estatística e Probabilidade&lt;/h1&gt;
&lt;p&gt;Aula 04 - Coleta, organização e apresentação de dados
&lt;/br&gt;&lt;/p&gt;
&lt;p&gt;
  &lt;i class=&#34;fas fa-user-tie  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;https://bendeivide.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Ben Dêivide&lt;/a&gt; | 
  &lt;i class=&#34;fas fa-school  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;https://www.ufsj.edu.br/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;UFSJ&lt;/a&gt;
&lt;/br&gt;

  &lt;i class=&#34;fas fa-book  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;http://bendeivide.github.io/courses/epaec/&#34;&gt;Estatística e Probabilidade&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;selo-dc&#34;&gt;Selo DC&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/dc/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/profmat-est/s04/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_57f4d021c573f1cdb22f5303fccfacd9.webp 400w,
               /slides/profmat-est/s04/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_e3124639f3c96b16d12396d9954194c3.webp 760w,
               /slides/profmat-est/s04/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/profmat-est/s04/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_57f4d021c573f1cdb22f5303fccfacd9.webp&#34;
               width=&#34;385&#34;
               height=&#34;406&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;section&gt;
  &lt;h2&gt;Motivação inicial&lt;/h2&gt;
  &lt;h3&gt; Dados (Primeiro tipo) &lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;##    [1] 100.93730855  90.78737290  31.43347250  70.04161421 114.72725633
##    [6] 119.48971504  39.59619123  81.81619913  18.66636591  87.17608029
##   [11] 155.08897515 137.78907540  88.08832220 149.37223517 137.06950642
##   [16] 104.46736332  52.25280719  90.24248077 146.27606310 124.14892624
##   [21]  70.18446816  -9.26434191  66.25670311  -5.95305960  36.74009892
##   [26]  81.31692224  65.62222848  56.39205866  94.91194969  87.31097349
##   [31]   7.31297728  96.10269670 148.42831703 109.24629800  31.00282108
##   [36]  28.22428188 118.10436143  12.04566231  83.77279952  67.42185057
##   [41] 154.32756997  61.87275600  58.56687325 141.72369515  51.61740066
##   [46]  98.55923323 111.62625763  84.93956592  66.11927084 132.76138181
##   [51]  79.96812265  83.27217175 168.39769766 206.88835518 125.29096323
##   [56] 139.31711921  54.88940279 126.64484962  67.70528732 114.54937442
##   [61]  38.12027656  77.19118624  58.48386726 117.00578218 153.31881978
##   [66] 160.80629190 136.78453288  75.93956913 128.13723814  37.68401441
##   [71] 119.04611063  28.47863736  47.57772476  89.07482247  25.50318816
##   [76] 158.63531406  26.00864892  78.48060920  47.41806790 176.12931720
##   [81] 129.64140273  88.86692455 135.64471381 135.83004169 122.01209322
##   [86] 107.94153107 132.98820692 211.02598315  40.80274630  96.30220828
##   [91]  79.18226626  90.42588281 103.47723907 157.76741590 129.74786735
##   [96]  29.01774458  19.66613773 144.64629498 107.40839776 161.35141951
##  [101]  61.90978304 120.96877029  48.00283177 135.57869830  68.33934925
##  [106] 128.15873322 133.04933429  17.09745713 151.40839885 156.39768070
##  [111]  35.99226983 156.44341137  76.79327364  84.21198952 146.21465734
##  [116] 103.85723620 151.99618026 137.09431034 162.77724291 147.54594832
##  [121]  75.93171964 110.14408890  98.41301281  40.22098498 131.18406184
##  [126]  54.25977582 112.43790039  46.86886034  81.80088764  39.65025733
##  [131] 171.46063907 131.67179455   0.15921912  65.90839135  76.99722603
##  [136]  50.84654029 124.76658564 136.29087501 133.36493659 147.73932182
##  [141]  16.23339104  39.74073038   1.83737554 173.53761549 118.62361693
##  [146] 153.29396670 126.53249342 105.09917229 166.88912329 104.36173842
##  [151]  80.44478963  87.50662577 157.75523729  56.76363801  56.66608288
##  [156] -16.05085152 130.44150845 157.50030241  40.02011641  20.99996227
##  [161] 132.65830968  72.52957574 126.05272627  65.02984668  78.05453426
##  [166]  66.13403519 147.95705974  26.59133353 109.18819463  28.24264087
##  [171]  43.13000509  79.26773366 107.19671441 153.10121653  71.46030486
##  [176] 163.85906882 111.41446603  84.55934677 147.99145653 127.44111874
##  [181] 121.27565469 132.17500176  31.98469282  90.07469468 130.96513384
##  [186] 203.41048025  84.73576229 114.06228061 134.56586684 102.31807191
##  [191] 105.65146808 149.76659371  65.94243193  36.14713767  26.56511251
##  [196]  84.32629667  14.81702537  32.47426719  44.89531614  45.02284927
##  [201] 160.77568881 116.54382426 169.51375596 143.60234925  45.95914887
##  [206] 124.79107957 152.63137781  36.26750249  90.31666358  35.24581787
##  [211] 107.09401423 163.08575260  78.42498360   8.86437052 117.62719794
##  [216]  32.57742793 135.38441590  79.45545316  77.69774100  47.94218492
##  [221]  83.53876419  85.85891879 121.62145627  84.61964525  97.16818461
##  [226] 136.67577101 104.86558098 181.54458683 128.03053495 166.47823822
##  [231]  86.05882522  36.66342279  87.54258030 100.89942073 118.85363636
##  [236] 139.80042788  57.96612915 -10.27358754  43.59720045  32.93450206
##  [241] 180.25570214 137.22118642 143.10411030 119.75779077 125.45593482
##  [246]  93.87249371 104.62923236  82.10600428  82.01723878 151.42853604
##  [251] 153.89462962 146.58906076  26.96030665  54.69622119  65.98260843
##  [256] 153.15830184  65.37934239  43.31858674  45.26922831  49.35481906
##  [261] 120.51386629 123.88702210 -16.49397725 100.81277326 149.01767616
##  [266] 140.31741324 105.98004444 -21.83078022 101.55112381  83.21266510
##  [271]  86.81119190  82.20737696  75.94226009 111.13677339 221.49551593
##  [276] 174.81490594  64.13958986  76.64730499 133.14617264 215.00884455
##  [281] 116.37550706 103.19317408  43.02195300 159.02051018 102.06942385
##  [286]  39.32032183 103.65978883  87.13377028 113.34032055 169.38621629
##  [291] 109.65398175 129.61583113  58.50127365 119.62866408 119.24338053
##  [296] 152.55223329 157.78987423  48.27810205  87.27659671 163.68421330
##  [301] 175.12723195 129.52047336  68.46572743 139.61747686 106.26922851
##  [306] 116.13774856  77.72083953 138.34219672  29.82484891  41.19766102
##  [311] 125.57982346 165.83826319 219.64564735  96.61152958  89.81074668
##  [316] 199.82172261 177.16088972  38.58311869 232.22439961 137.85068541
##  [321] 152.76725961 147.89724477 141.69395288  91.53622150  79.77831785
##  [326] 114.78007869  88.40627464  77.59608842 101.11553983 102.22336486
##  [331] 124.03605826 131.78099276  -0.03711965  65.46722481  93.46774053
##  [336]  82.78741085  97.37935880 104.80619603 113.32035266 127.73967376
##  [341] 161.77229393 114.25666907  77.06035361 131.17390109  63.80024542
##  [346] 180.97093517  69.16632949 119.22705287 205.72606564  48.57163169
##  [351]  55.66060172 163.55730007  19.74572794 156.11366915 207.92193209
##  [356] 121.41233065 160.05893452 151.58450581 132.69371264 200.60408866
##  [361] 154.73149209 136.32046770  30.01714317  35.61024184  51.57922612
##  [366]  13.16571211 141.58486790  62.05234457 207.75385005  78.83705599
##  [371]  99.71750317 120.01808643  81.71610990  78.54280824 112.23485634
##  [376] 210.98881244 115.71349040  71.81074627  25.71519208 120.76492965
##  [381]  73.59681587  82.47646913 136.53109686  72.16879175  27.51197319
##  [386]  47.40017859  65.85806906  69.35294107 194.53900175  92.72947332
##  [391]  68.02881397  79.44119774 117.13959392  43.33766227 103.30351513
##  [396] 101.89998830 146.05323738 206.74828192  70.00865342 162.22232293
##  [401]  96.02714914 159.08757749 209.30720313 120.30874654  63.08204477
##  [406]   2.17566485   2.49771492  52.95010922 159.88933843  68.78803048
##  [411]  93.35651724  99.13895389  77.01853589 173.64683953 208.46598063
##  [416] -50.07156532  11.40072085  81.75803886 118.72668903  38.29610367
##  [421] 123.74467110 161.65287285  70.34356716 137.61312197 130.60227534
##  [426]  88.56713174  64.75803251 161.47580236 175.92575649 167.25470902
##  [431]  93.81542355 146.69512268 100.97484228 141.54260549  84.77526660
##  [436]  97.03593614 150.36983487  31.11024570  49.78986365  98.83598475
##  [441] 177.33736369  62.03183745 150.33963287 113.71074582  95.98088177
##  [446]  54.82237523 123.65725515 169.42444890 101.73730469  35.37074860
##  [451] 158.19837525  23.83077015 -25.91675268  64.62353847  85.62835586
##  [456]  78.23458443  82.84606146  98.03445580 144.34829939  82.00257996
##  [461]  63.55228647 187.58728096  95.69807049 155.31815079  99.04110814
##  [466]  25.32699108 235.03183115  62.81527889 153.25974905  98.39591342
##  [471]  73.00201553   3.71782162 150.39156881  86.03826016  37.52170724
##  [476] 162.42455639  90.38933117 145.59881155  -7.91348400 164.48052662
##  [481]  78.59450172  87.24985535 166.35791194 141.93450603  26.74996614
##  [486]  69.18736511 105.30529197   7.79916211  19.17885731 111.38383521
##  [491] 146.06083510  83.43982803 164.36170155 102.86304012 -10.19665626
##  [496]  73.85448259 154.03926551  87.84293312  54.52767189  56.58502463
##  [501] 143.47375225  65.99952011 108.66072694  92.02809805 139.67497163
##  [506] 184.71752457 161.99843432 101.47183716 182.86072495 156.56115701
##  [511]  29.87946839 107.83852306 143.37542982  98.33824214 147.70322782
##  [516] 156.50483626 119.68486560 118.84041640  87.41285465 125.20474454
##  [521]  33.50982643  94.08502737  68.33757667 133.88456724  85.10591176
##  [526] 131.39611236 183.92153640 -20.00012703  32.50785575 160.10039479
##  [531] 164.69213597  97.02028269  65.74688274  27.32803478 164.70632806
##  [536] 158.80845447 143.20225391 -14.83662617  30.40949940  30.70616275
##  [541]  46.34765780  52.92872484  70.67828451 151.73606100 122.94811033
##  [546]  40.32774640 139.59446358  11.38475446  70.61387890  35.88148437
##  [551]  84.39326695  65.06123497 -32.19248839 141.25111884 115.34631566
##  [556]  97.09802709 146.32847054  89.06540697 149.65667487   3.83328288
##  [561]  47.36424078 144.51988810 277.05701388 137.07553713  89.62643730
##  [566] 108.99692271 171.31824247  77.84166053 118.35949933 134.79108481
##  [571] 146.67223643 174.59445413 157.97614951 111.33979785  35.22674076
##  [576]  96.86106542 149.66414684  49.70345300  62.45075262 187.20081912
##  [581]  40.61999543  79.15147911  21.50899203  85.97629824  70.73365181
##  [586] 133.01595988  68.12437255  73.04891834 147.57601168  94.72100771
##  [591]  81.29653636  91.18837096 113.82416540 111.81662963 203.08370797
##  [596]  35.49700071 128.55947237 189.26951134 110.64701215 144.23460730
##  [601]  54.90148678  97.26250210  32.16226445 115.86152886 169.78595597
##  [606]  39.43880916  89.79291696  22.37743370 125.90248343  79.05798484
##  [611]  14.52733922 224.15813357 124.90168675  66.30658974  55.65093022
##  [616]  13.43113246 130.22745607  56.43624609 136.26708232  98.46340099
##  [621]  94.13888128 104.91114693  66.15713891  97.53768225  71.96401200
##  [626] 219.95774326  95.50639492  58.91757911  85.65191192 106.56394370
##  [631]  46.89580248 136.67905179 116.13460992  82.55101143 164.17628321
##  [636]  49.27559756  74.49678629  91.64151269  84.86661072 201.32352362
##  [641] 145.04528192 106.77145202  89.93555229  59.65816295 132.20620619
##  [646]  83.16704397  13.41482444 113.09603313  54.16512009  71.57177624
##  [651]  56.70897791 141.27469559  59.99338579 148.79150434 235.00377654
##  [656]  93.23052016  94.69844180  32.79680974 122.15609143 148.05588708
##  [661]  87.92820917 104.14774456  81.91376211 116.69300999 113.28047105
##  [666] 250.64528733  82.76349312 153.12787266  63.51574630 102.82738605
##  [671] 123.39148560  81.36773747 110.50808438 164.48041528  18.65802251
##  [676]  60.82317452 125.54565517 160.88130280 115.25546238 110.51468167
##  [681] 123.44329828   4.78287139 161.92011423 119.54994457  98.44005416
##  [686]  19.05997391 122.56331391  65.45783182 170.27228110  14.93286561
##  [691] 109.61227986  64.85216193  59.57220683  68.09006292 186.86727140
##  [696] -13.02391316  19.37639531 132.68700994 145.14403643 137.73042439
##  [701]  88.65946156  65.20156862 125.33236787 130.81171468  16.65603627
##  [706]  83.18728871 125.35899284  15.13046492  89.65363880  80.07014859
##  [711]  40.56900863 122.62827021 110.37948520  39.49388119 138.37075271
##  [716]  70.04861544  21.95136136  50.21679785 154.66255042 145.85714430
##  [721]  61.34753224  76.20820912  43.46484080  78.55822842  58.02081751
##  [726]  69.95066635  61.30546109  55.37538244  98.21340765  84.79109488
##  [731] -50.60818918  -0.42615289  97.68142953  82.02314677  90.24891691
##  [736]  24.27649323  55.39834764  56.86467543 127.59770740  90.58830433
##  [741]  83.74266282  73.15307754  81.42612936 136.14035118 160.28459417
##  [746] 159.20765628 133.55952177 158.77510367 109.42632364 124.95317984
##  [751]   2.61908443 121.03686231 158.67381249  27.68842215  81.66243970
##  [756]  69.61018826 115.99356887 154.99238361  79.69816862 220.53732134
##  [761] 157.94499424 116.91947958 122.80886720  84.29776668 170.21720101
##  [766]  79.48650255  95.59487419 116.24377974 159.25499001  87.22457133
##  [771] 144.22239604  75.57194652  63.63119134  40.58723635  73.10287920
##  [776] 105.96756087 165.90890477 172.15402788 112.45131058 140.78511634
##  [781]  63.26960968 112.90766390  57.35696156 110.78243793  64.53948940
##  [786] 135.54327616  77.63140706  83.08508479 125.86167111 104.93517972
##  [791] 137.18428079  86.07249293 126.95358403  95.58302652  62.71212459
##  [796]  21.99607744 154.14782627 -17.05280013 110.31526330 138.23712856
##  [801]  -6.25342905 126.05893332  97.67885500  42.52641395 131.46691539
##  [806]  63.67642620  80.67913388  66.41428051 145.01930952 144.34208453
##  [811] 119.51390559  53.62442549 137.29196144 124.74120783  98.90342691
##  [816] 129.40111631 137.82455370  75.29868637  63.33421857  99.94898030
##  [821] 140.29128484 155.46546909  84.51602589  54.57108759 113.15130638
##  [826]  98.95410962  89.38287462  48.44480401 106.97553698 108.31089923
##  [831]  50.76701755 101.13170354 139.26650163  41.04052379 195.53953888
##  [836]  73.09992525 144.21382145 107.36548184  49.57863186 141.90944961
##  [841]  41.58804313 122.71590665 110.62864338  72.34568263 101.17150126
##  [846] 132.40894452  12.86026324 129.75813305  56.07354935 132.22187856
##  [851]  68.54507487  95.08999052 134.21088496  30.76569845 177.74727930
##  [856]  59.28293291  57.81844571 151.24637129 105.78516882 112.07470199
##  [861]  30.45919292 176.30304223 102.32581184 161.99911798 115.42863177
##  [866] 139.28138023 155.87393524  99.75088638  91.07908949 134.81145345
##  [871] 126.08986042  77.60867049 120.27003020  63.15177877 112.78740072
##  [876]  85.75332475  98.44393375  75.70705565  93.24559579  25.96406386
##  [881] 162.81845628 110.45208250 115.65783948 153.75741193  85.66874127
##  [886]  98.40112863  62.86333017 204.26100961 142.74452052 150.02229981
##  [891]  40.79410450  22.94487224  89.41334996 108.51762850  65.46113128
##  [896] 184.88603695  96.36550187  64.11955719  79.17427808 209.67933805
##  [901] 127.11739129 151.18338045 140.64130544 165.05135387 128.39782055
##  [906]  93.99642789  75.39986469 110.03859877 108.23996494 134.68288481
##  [911] 106.66621267  63.02684207  80.12405924 112.85793197  85.99130404
##  [916] 150.39837961 157.76098120  89.86025254  83.92952265  18.94730415
##  [921] 128.40526295 133.56401236 173.01297609  18.11403129 164.92505411
##  [926]  92.31500856 178.95744228 202.76175928 164.22433254 120.87016586
##  [931] 157.99268036 124.57951279 155.10043589 128.42852151  81.80414574
##  [936] 106.84781854 136.21377136 176.99908030 149.34961674  52.69890010
##  [941]  69.36596579 164.34432952  72.16749200  98.85111389 166.23705613
##  [946] 113.19488345 142.06695095  86.79312555 144.33846460 111.27428778
##  [951] 127.24163623 158.81253634  84.32123791 125.26883443 176.98506493
##  [956] 174.55013553 112.18447423  79.23428368  -1.75863811  67.83210511
##  [961] 102.69107405  80.52190580 193.89127767  27.11966366 136.19276892
##  [966]  39.09618692  84.71205651 101.21988583 117.61330506 141.18948778
##  [971] 129.88932805 164.78187322  71.09669104 108.64874902  70.94018770
##  [976]  60.87047018  16.65853979  64.32633758  74.66620861  65.24080279
##  [981] 127.08039056  70.94613518 121.54160255 133.58505948  78.32463472
##  [986]  60.95082856 120.81490912  58.91897002 110.55379452 137.74115849
##  [991] 189.00548763 133.29738410  99.46330902  39.94726968  67.83011078
##  [996] 139.86461552 126.41241372 114.18348694  99.39303476  90.40431113
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3&gt; Dados (Segundo tipo) &lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;##    [1] -50.60818918 -50.07156532 -32.19248839 -25.91675268 -21.83078022
##    [6] -20.00012703 -17.05280013 -16.49397725 -16.05085152 -14.83662617
##   [11] -13.02391316 -10.27358754 -10.19665626  -9.26434191  -7.91348400
##   [16]  -6.25342905  -5.95305960  -1.75863811  -0.42615289  -0.03711965
##   [21]   0.15921912   1.83737554   2.17566485   2.49771492   2.61908443
##   [26]   3.71782162   3.83328288   4.78287139   7.31297728   7.79916211
##   [31]   8.86437052  11.38475446  11.40072085  12.04566231  12.86026324
##   [36]  13.16571211  13.41482444  13.43113246  14.52733922  14.81702537
##   [41]  14.93286561  15.13046492  16.23339104  16.65603627  16.65853979
##   [46]  17.09745713  18.11403129  18.65802251  18.66636591  18.94730415
##   [51]  19.05997391  19.17885731  19.37639531  19.66613773  19.74572794
##   [56]  20.99996227  21.50899203  21.95136136  21.99607744  22.37743370
##   [61]  22.94487224  23.83077015  24.27649323  25.32699108  25.50318816
##   [66]  25.71519208  25.96406386  26.00864892  26.56511251  26.59133353
##   [71]  26.74996614  26.96030665  27.11966366  27.32803478  27.51197319
##   [76]  27.68842215  28.22428188  28.24264087  28.47863736  29.01774458
##   [81]  29.82484891  29.87946839  30.01714317  30.40949940  30.45919292
##   [86]  30.70616275  30.76569845  31.00282108  31.11024570  31.43347250
##   [91]  31.98469282  32.16226445  32.47426719  32.50785575  32.57742793
##   [96]  32.79680974  32.93450206  33.50982643  35.22674076  35.24581787
##  [101]  35.37074860  35.49700071  35.61024184  35.88148437  35.99226983
##  [106]  36.14713767  36.26750249  36.66342279  36.74009892  37.52170724
##  [111]  37.68401441  38.12027656  38.29610367  38.58311869  39.09618692
##  [116]  39.32032183  39.43880916  39.49388119  39.59619123  39.65025733
##  [121]  39.74073038  39.94726968  40.02011641  40.22098498  40.32774640
##  [126]  40.56900863  40.58723635  40.61999543  40.79410450  40.80274630
##  [131]  41.04052379  41.19766102  41.58804313  42.52641395  43.02195300
##  [136]  43.13000509  43.31858674  43.33766227  43.46484080  43.59720045
##  [141]  44.89531614  45.02284927  45.26922831  45.95914887  46.34765780
##  [146]  46.86886034  46.89580248  47.36424078  47.40017859  47.41806790
##  [151]  47.57772476  47.94218492  48.00283177  48.27810205  48.44480401
##  [156]  48.57163169  49.27559756  49.35481906  49.57863186  49.70345300
##  [161]  49.78986365  50.21679785  50.76701755  50.84654029  51.57922612
##  [166]  51.61740066  52.25280719  52.69890010  52.92872484  52.95010922
##  [171]  53.62442549  54.16512009  54.25977582  54.52767189  54.57108759
##  [176]  54.69622119  54.82237523  54.88940279  54.90148678  55.37538244
##  [181]  55.39834764  55.65093022  55.66060172  56.07354935  56.39205866
##  [186]  56.43624609  56.58502463  56.66608288  56.70897791  56.76363801
##  [191]  56.86467543  57.35696156  57.81844571  57.96612915  58.02081751
##  [196]  58.48386726  58.50127365  58.56687325  58.91757911  58.91897002
##  [201]  59.28293291  59.57220683  59.65816295  59.99338579  60.82317452
##  [206]  60.87047018  60.95082856  61.30546109  61.34753224  61.87275600
##  [211]  61.90978304  62.03183745  62.05234457  62.45075262  62.71212459
##  [216]  62.81527889  62.86333017  63.02684207  63.08204477  63.15177877
##  [221]  63.26960968  63.33421857  63.51574630  63.55228647  63.63119134
##  [226]  63.67642620  63.80024542  64.11955719  64.13958986  64.32633758
##  [231]  64.53948940  64.62353847  64.75803251  64.85216193  65.02984668
##  [236]  65.06123497  65.20156862  65.24080279  65.37934239  65.45783182
##  [241]  65.46113128  65.46722481  65.62222848  65.74688274  65.85806906
##  [246]  65.90839135  65.94243193  65.98260843  65.99952011  66.11927084
##  [251]  66.13403519  66.15713891  66.25670311  66.30658974  66.41428051
##  [256]  67.42185057  67.70528732  67.83011078  67.83210511  68.02881397
##  [261]  68.09006292  68.12437255  68.33757667  68.33934925  68.46572743
##  [266]  68.54507487  68.78803048  69.16632949  69.18736511  69.35294107
##  [271]  69.36596579  69.61018826  69.95066635  70.00865342  70.04161421
##  [276]  70.04861544  70.18446816  70.34356716  70.61387890  70.67828451
##  [281]  70.73365181  70.94018770  70.94613518  71.09669104  71.46030486
##  [286]  71.57177624  71.81074627  71.96401200  72.16749200  72.16879175
##  [291]  72.34568263  72.52957574  73.00201553  73.04891834  73.09992525
##  [296]  73.10287920  73.15307754  73.59681587  73.85448259  74.49678629
##  [301]  74.66620861  75.29868637  75.39986469  75.57194652  75.70705565
##  [306]  75.93171964  75.93956913  75.94226009  76.20820912  76.64730499
##  [311]  76.79327364  76.99722603  77.01853589  77.06035361  77.19118624
##  [316]  77.59608842  77.60867049  77.63140706  77.69774100  77.72083953
##  [321]  77.84166053  78.05453426  78.23458443  78.32463472  78.42498360
##  [326]  78.48060920  78.54280824  78.55822842  78.59450172  78.83705599
##  [331]  79.05798484  79.15147911  79.17427808  79.18226626  79.23428368
##  [336]  79.26773366  79.44119774  79.45545316  79.48650255  79.69816862
##  [341]  79.77831785  79.96812265  80.07014859  80.12405924  80.44478963
##  [346]  80.52190580  80.67913388  81.29653636  81.31692224  81.36773747
##  [351]  81.42612936  81.66243970  81.71610990  81.75803886  81.80088764
##  [356]  81.80414574  81.81619913  81.91376211  82.00257996  82.01723878
##  [361]  82.02314677  82.10600428  82.20737696  82.47646913  82.55101143
##  [366]  82.76349312  82.78741085  82.84606146  83.08508479  83.16704397
##  [371]  83.18728871  83.21266510  83.27217175  83.43982803  83.53876419
##  [376]  83.74266282  83.77279952  83.92952265  84.21198952  84.29776668
##  [381]  84.32123791  84.32629667  84.39326695  84.51602589  84.55934677
##  [386]  84.61964525  84.71205651  84.73576229  84.77526660  84.79109488
##  [391]  84.86661072  84.93956592  85.10591176  85.62835586  85.65191192
##  [396]  85.66874127  85.75332475  85.85891879  85.97629824  85.99130404
##  [401]  86.03826016  86.05882522  86.07249293  86.79312555  86.81119190
##  [406]  87.13377028  87.17608029  87.22457133  87.24985535  87.27659671
##  [411]  87.31097349  87.41285465  87.50662577  87.54258030  87.84293312
##  [416]  87.92820917  88.08832220  88.40627464  88.56713174  88.65946156
##  [421]  88.86692455  89.06540697  89.07482247  89.38287462  89.41334996
##  [426]  89.62643730  89.65363880  89.79291696  89.81074668  89.86025254
##  [431]  89.93555229  90.07469468  90.24248077  90.24891691  90.31666358
##  [436]  90.38933117  90.40431113  90.42588281  90.58830433  90.78737290
##  [441]  91.07908949  91.18837096  91.53622150  91.64151269  92.02809805
##  [446]  92.31500856  92.72947332  93.23052016  93.24559579  93.35651724
##  [451]  93.46774053  93.81542355  93.87249371  93.99642789  94.08502737
##  [456]  94.13888128  94.69844180  94.72100771  94.91194969  95.08999052
##  [461]  95.50639492  95.58302652  95.59487419  95.69807049  95.98088177
##  [466]  96.02714914  96.10269670  96.30220828  96.36550187  96.61152958
##  [471]  96.86106542  97.02028269  97.03593614  97.09802709  97.16818461
##  [476]  97.26250210  97.37935880  97.53768225  97.67885500  97.68142953
##  [481]  98.03445580  98.21340765  98.33824214  98.39591342  98.40112863
##  [486]  98.41301281  98.44005416  98.44393375  98.46340099  98.55923323
##  [491]  98.83598475  98.85111389  98.90342691  98.95410962  99.04110814
##  [496]  99.13895389  99.39303476  99.46330902  99.71750317  99.75088638
##  [501]  99.94898030 100.81277326 100.89942073 100.93730855 100.97484228
##  [506] 101.11553983 101.13170354 101.17150126 101.21988583 101.47183716
##  [511] 101.55112381 101.73730469 101.89998830 102.06942385 102.22336486
##  [516] 102.31807191 102.32581184 102.69107405 102.82738605 102.86304012
##  [521] 103.19317408 103.30351513 103.47723907 103.65978883 103.85723620
##  [526] 104.14774456 104.36173842 104.46736332 104.62923236 104.80619603
##  [531] 104.86558098 104.91114693 104.93517972 105.09917229 105.30529197
##  [536] 105.65146808 105.78516882 105.96756087 105.98004444 106.26922851
##  [541] 106.56394370 106.66621267 106.77145202 106.84781854 106.97553698
##  [546] 107.09401423 107.19671441 107.36548184 107.40839776 107.83852306
##  [551] 107.94153107 108.23996494 108.31089923 108.51762850 108.64874902
##  [556] 108.66072694 108.99692271 109.18819463 109.24629800 109.42632364
##  [561] 109.61227986 109.65398175 110.03859877 110.14408890 110.31526330
##  [566] 110.37948520 110.45208250 110.50808438 110.51468167 110.55379452
##  [571] 110.62864338 110.64701215 110.78243793 111.13677339 111.27428778
##  [576] 111.33979785 111.38383521 111.41446603 111.62625763 111.81662963
##  [581] 112.07470199 112.18447423 112.23485634 112.43790039 112.45131058
##  [586] 112.78740072 112.85793197 112.90766390 113.09603313 113.15130638
##  [591] 113.19488345 113.28047105 113.32035266 113.34032055 113.71074582
##  [596] 113.82416540 114.06228061 114.18348694 114.25666907 114.54937442
##  [601] 114.72725633 114.78007869 115.25546238 115.34631566 115.42863177
##  [606] 115.65783948 115.71349040 115.86152886 115.99356887 116.13460992
##  [611] 116.13774856 116.24377974 116.37550706 116.54382426 116.69300999
##  [616] 116.91947958 117.00578218 117.13959392 117.61330506 117.62719794
##  [621] 118.10436143 118.35949933 118.62361693 118.72668903 118.84041640
##  [626] 118.85363636 119.04611063 119.22705287 119.24338053 119.48971504
##  [631] 119.51390559 119.54994457 119.62866408 119.68486560 119.75779077
##  [636] 120.01808643 120.27003020 120.30874654 120.51386629 120.76492965
##  [641] 120.81490912 120.87016586 120.96877029 121.03686231 121.27565469
##  [646] 121.41233065 121.54160255 121.62145627 122.01209322 122.15609143
##  [651] 122.56331391 122.62827021 122.71590665 122.80886720 122.94811033
##  [656] 123.39148560 123.44329828 123.65725515 123.74467110 123.88702210
##  [661] 124.03605826 124.14892624 124.57951279 124.74120783 124.76658564
##  [666] 124.79107957 124.90168675 124.95317984 125.20474454 125.26883443
##  [671] 125.29096323 125.33236787 125.35899284 125.45593482 125.54565517
##  [676] 125.57982346 125.86167111 125.90248343 126.05272627 126.05893332
##  [681] 126.08986042 126.41241372 126.53249342 126.64484962 126.95358403
##  [686] 127.08039056 127.11739129 127.24163623 127.44111874 127.59770740
##  [691] 127.73967376 128.03053495 128.13723814 128.15873322 128.39782055
##  [696] 128.40526295 128.42852151 128.55947237 129.40111631 129.52047336
##  [701] 129.61583113 129.64140273 129.74786735 129.75813305 129.88932805
##  [706] 130.22745607 130.44150845 130.60227534 130.81171468 130.96513384
##  [711] 131.17390109 131.18406184 131.39611236 131.46691539 131.67179455
##  [716] 131.78099276 132.17500176 132.20620619 132.22187856 132.40894452
##  [721] 132.65830968 132.68700994 132.69371264 132.76138181 132.98820692
##  [726] 133.01595988 133.04933429 133.14617264 133.29738410 133.36493659
##  [731] 133.55952177 133.56401236 133.58505948 133.88456724 134.21088496
##  [736] 134.56586684 134.68288481 134.79108481 134.81145345 135.38441590
##  [741] 135.54327616 135.57869830 135.64471381 135.83004169 136.14035118
##  [746] 136.19276892 136.21377136 136.26708232 136.29087501 136.32046770
##  [751] 136.53109686 136.67577101 136.67905179 136.78453288 137.06950642
##  [756] 137.07553713 137.09431034 137.18428079 137.22118642 137.29196144
##  [761] 137.61312197 137.73042439 137.74115849 137.78907540 137.82455370
##  [766] 137.85068541 138.23712856 138.34219672 138.37075271 139.26650163
##  [771] 139.28138023 139.31711921 139.59446358 139.61747686 139.67497163
##  [776] 139.80042788 139.86461552 140.29128484 140.31741324 140.64130544
##  [781] 140.78511634 141.18948778 141.25111884 141.27469559 141.54260549
##  [786] 141.58486790 141.69395288 141.72369515 141.90944961 141.93450603
##  [791] 142.06695095 142.74452052 143.10411030 143.20225391 143.37542982
##  [796] 143.47375225 143.60234925 144.21382145 144.22239604 144.23460730
##  [801] 144.33846460 144.34208453 144.34829939 144.51988810 144.64629498
##  [806] 145.01930952 145.04528192 145.14403643 145.59881155 145.85714430
##  [811] 146.05323738 146.06083510 146.21465734 146.27606310 146.32847054
##  [816] 146.58906076 146.67223643 146.69512268 147.54594832 147.57601168
##  [821] 147.70322782 147.73932182 147.89724477 147.95705974 147.99145653
##  [826] 148.05588708 148.42831703 148.79150434 149.01767616 149.34961674
##  [831] 149.37223517 149.65667487 149.66414684 149.76659371 150.02229981
##  [836] 150.33963287 150.36983487 150.39156881 150.39837961 151.18338045
##  [841] 151.24637129 151.40839885 151.42853604 151.58450581 151.73606100
##  [846] 151.99618026 152.55223329 152.63137781 152.76725961 153.10121653
##  [851] 153.12787266 153.15830184 153.25974905 153.29396670 153.31881978
##  [856] 153.75741193 153.89462962 154.03926551 154.14782627 154.32756997
##  [861] 154.66255042 154.73149209 154.99238361 155.08897515 155.10043589
##  [866] 155.31815079 155.46546909 155.87393524 156.11366915 156.39768070
##  [871] 156.44341137 156.50483626 156.56115701 157.50030241 157.75523729
##  [876] 157.76098120 157.76741590 157.78987423 157.94499424 157.97614951
##  [881] 157.99268036 158.19837525 158.63531406 158.67381249 158.77510367
##  [886] 158.80845447 158.81253634 159.02051018 159.08757749 159.20765628
##  [891] 159.25499001 159.88933843 160.05893452 160.10039479 160.28459417
##  [896] 160.77568881 160.80629190 160.88130280 161.35141951 161.47580236
##  [901] 161.65287285 161.77229393 161.92011423 161.99843432 161.99911798
##  [906] 162.22232293 162.42455639 162.77724291 162.81845628 163.08575260
##  [911] 163.55730007 163.68421330 163.85906882 164.17628321 164.22433254
##  [916] 164.34432952 164.36170155 164.48041528 164.48052662 164.69213597
##  [921] 164.70632806 164.78187322 164.92505411 165.05135387 165.83826319
##  [926] 165.90890477 166.23705613 166.35791194 166.47823822 166.88912329
##  [931] 167.25470902 168.39769766 169.38621629 169.42444890 169.51375596
##  [936] 169.78595597 170.21720101 170.27228110 171.31824247 171.46063907
##  [941] 172.15402788 173.01297609 173.53761549 173.64683953 174.55013553
##  [946] 174.59445413 174.81490594 175.12723195 175.92575649 176.12931720
##  [951] 176.30304223 176.98506493 176.99908030 177.16088972 177.33736369
##  [956] 177.74727930 178.95744228 180.25570214 180.97093517 181.54458683
##  [961] 182.86072495 183.92153640 184.71752457 184.88603695 186.86727140
##  [966] 187.20081912 187.58728096 189.00548763 189.26951134 193.89127767
##  [971] 194.53900175 195.53953888 199.82172261 200.60408866 201.32352362
##  [976] 202.76175928 203.08370797 203.41048025 204.26100961 205.72606564
##  [981] 206.74828192 206.88835518 207.75385005 207.92193209 208.46598063
##  [986] 209.30720313 209.67933805 210.98881244 211.02598315 215.00884455
##  [991] 219.64564735 219.95774326 220.53732134 221.49551593 224.15813357
##  [996] 232.22439961 235.00377654 235.03183115 250.64528733 277.05701388
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3&gt; Dados (Terceiro tipo) &lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;##                 Classe  Fi     PM   Fr Fac1 Fac2 Fp Fac1p Fac2p
## 1  -62.31 |---  -38.91   2 -50.61 0.00    2 1000  0   0.2 100.0
## 2  -38.91 |---  -15.51   7 -27.21 0.01    9  998  1   0.9  99.8
## 3    -15.51 |---  7.89  21  -3.81 0.02   30  991  2   3.0  99.1
## 4     7.89 |---  31.29  59  19.59 0.06   89  970  6   8.9  97.0
## 5    31.29 |---  54.69  86  42.99 0.09  175  911  9  17.5  91.1
## 6    54.69 |---  78.09 147  66.39 0.15  322  825 15  32.2  82.5
## 7   78.09 |---  101.49 188  89.79 0.19  510  678 19  51.0  67.8
## 8  101.49 |---  124.89 156 113.19 0.16  666  490 16  66.6  49.0
## 9  124.89 |---  148.29 160 136.59 0.16  826  334 16  82.6  33.4
## 10 148.29 |---  171.69 114 159.99 0.11  940  174 11  94.0  17.4
## 11 171.69 |---  195.09  31 183.39 0.03  971   60  3  97.1   6.0
## 12 195.09 |---  218.49  19 206.79 0.02  990   29  2  99.0   2.9
## 13 218.49 |---  241.89   8 230.19 0.01  998   10  1  99.8   1.0
## 14 241.89 |---  265.29   1 253.59 0.00  999    2  0  99.9   0.2
## 15 265.29 |---  288.69   1 276.99 0.00 1000    1  0 100.0   0.1
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3&gt; Dados (Quarto tipo) &lt;/h3&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s04/index_files/figure-html/unnamed-chunk-4-1.png&#34; width=&#34;672&#34; /&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;coleta-dados-brutos&#34;&gt;Coleta (Dados brutos)&lt;/h2&gt;
&lt;p&gt;Dados elaborados sobre o número de erros encontrados em 20 conjunto de caracteres monitorado em um canal de comunicação&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:right&#34;&gt;3&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;0&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;3&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;4&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;3&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;2&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;3&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;0&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;2&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;3&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;2&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;2&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;dados-em-rol-ou-elaborados&#34;&gt;Dados em rol ou elaborados&lt;/h2&gt;
&lt;p&gt;Dados elaborados sobre o número de erros encontrados em 20 conjunto de caracteres monitorado em um canal de comunicação&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:right&#34;&gt;0&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;0&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;0&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:right&#34;&gt;2&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;2&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;2&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;2&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;3&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;3&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;3&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;3&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;3&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;section&gt;
&lt;h2&gt; Distribuição de frequência &lt;/h2&gt;
&lt;h3&gt;Frequência absoluta&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:center&#34;&gt;Número de erros &lt;code&gt;\((x_i)\)&lt;/code&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;Frequência simples ($f_i$)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;1&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;2&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;3&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;4&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;Total&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;20&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h3&gt;Frequência relativa&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:center&#34;&gt;Número de erros &lt;code&gt;\((x_i)\)&lt;/code&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(f_i\)&lt;/code&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(f_{r_i}\)&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(3\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(3 / 20 = 0,15\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(1\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(7\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(7 / 20 = 0,35\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(2\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(4\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(4 / 20 = 0,20\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(3\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(5\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(5 / 20 = 0,25\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(4\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(1\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(1 / 20 = 0,05\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h3&gt;Frequência percentual&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:center&#34;&gt;Número de erros &lt;code&gt;\((x_i)\)&lt;/code&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(f_i\)&lt;/code&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(f_{r_i}\)&lt;/code&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(f_{\%_i}\)&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(3\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,15\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,15 \times 100 = 15\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(1\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(7\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,35\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,35 \times 100 = 35\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(2\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(4\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,20\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,20 \times 100 = 20\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(3\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(5\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,25\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,25 \times 100 = 25\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(4\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(1\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,05\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,05 \times 100 = 5\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;Total&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(20\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(1\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(100\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h3&gt;Tabela completa&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:center&#34;&gt;Número de erros &lt;code&gt;\((x_i)\)&lt;/code&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(f_i\)&lt;/code&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(f_{r_i}\)&lt;/code&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(f_{\%_i}\)&lt;/code&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(f_{ac\downarrow_i}\)&lt;/code&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(f_{ac\uparrow_i}\)&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(3\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,15\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(15\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(3\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(20\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(1\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(7\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,35\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(35\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(10\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(17\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(2\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(4\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,20\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(35\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(14\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(10\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(3\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(5\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,25\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(25\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(19\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(6\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(4\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(1\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,05\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(5\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(20\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(1\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;Total&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(20\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(1\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(100\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;section&gt;
&lt;h2&gt;Tabela para V. contínua (Algoritmo) &lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:center&#34;&gt;Classe&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;$ F_i $&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;$ Li_{1a} \vdash  Ls_{1a} $&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;$ f_1 $&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;$ Li_{2a} \vdash  Ls_{2a} $&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;$ f_2 $&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;$ \vdots $&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;$ \vdots $&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;$ Li_{ka}  \vdash Ls_{ka} $&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;$ f_k $&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;pre&gt; 1º Passo - Número de classes &lt;/pre&gt;
&lt;p&gt;&lt;code&gt;\begin{align} k &amp;amp; \approx \left\{\begin{array}{ll} \sqrt{\textrm{número de elementos}}, &amp;amp; n \leq 100 \\ 5log_{10}(\textrm{número de elementos}), &amp;amp; n &amp;gt; 100 \end{array}\right.  \end{align}&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt; 2º Passo - Amplitude total &lt;/pre&gt;
&lt;p&gt;&lt;code&gt;\begin{align} A_t &amp;amp; = \max_i(X_i) - \min_i(X_i),  \end{align}&lt;/code&gt;
para &lt;code&gt;\(i \in \mathbb{N}^{+}\)&lt;/code&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;pre&gt; 3º Passo - Amplitude de classe &lt;/pre&gt;
&lt;p&gt;&lt;code&gt;\begin{align} c &amp;amp; = \left\{\begin{array}{ll} \frac{A_t}{k - 1}, &amp;amp; \textrm{Amostra} \\ \frac{A_t}{k}, &amp;amp; \textrm{População}. \end{array}\right.  \end{align}&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt; 4º Passo - LI da primeira classe &lt;/pre&gt;
&lt;p&gt;&lt;code&gt;\begin{align} Li_{1a} &amp;amp; = \left\{\begin{array}{ll} X_{(1)} - c / 2, &amp;amp; \textrm{Amostra} \\ X_{(1)}, &amp;amp; \textrm{População}. \end{array}\right.  \end{align}&lt;/code&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt; Em resumo... &lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Calcular &lt;code&gt;\(k\)&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;Calcular &lt;code&gt;\(A_t\)&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;Calcular &lt;code&gt;\(c\)&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;Calcular &lt;code&gt;\(Li_{1a}\)&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;Determinar as classes,&lt;/li&gt;
&lt;li&gt;Calcular o ponto médio, e&lt;/li&gt;
&lt;li&gt;Calcular as frequências como apresentadas no início dessa seção.&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;gráficos&#34;&gt;Gráficos&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Gráfico de Haste ou bastão&lt;/li&gt;
&lt;li&gt;Gráfico de barras&lt;/li&gt;
&lt;li&gt;Gráfico de Pizza&lt;/li&gt;
&lt;li&gt;Histograma de frequências&lt;/li&gt;
&lt;li&gt;Ogivas&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;section&gt; 
&lt;h2&gt; Uso do pacote &lt;code&gt;leem&lt;/code&gt; &lt;/h2&gt;














&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/profmat-est/s04/leem_hu7b1031bcd7f556bee541df85c0c5375e_34750_3761f4b815fffe33ceb7dbc21c169f83.webp 400w,
               /slides/profmat-est/s04/leem_hu7b1031bcd7f556bee541df85c0c5375e_34750_3705f9ee693abc73a6049df605c75df5.webp 760w,
               /slides/profmat-est/s04/leem_hu7b1031bcd7f556bee541df85c0c5375e_34750_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/profmat-est/s04/leem_hu7b1031bcd7f556bee541df85c0c5375e_34750_3761f4b815fffe33ceb7dbc21c169f83.webp&#34;
               width=&#34;150&#34;
               height=&#34;150&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;p&gt;Instalação&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;install.packages(&amp;quot;devtools&amp;quot;)
devtools::install_github(&amp;quot;bendeivide/leem&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Anexando e carregando&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;library(leem)
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt; Funções &lt;/h2&gt;
&lt;!-- | Função     | Finalidade                  | --&gt;
&lt;!-- |:-----------|:----------------------------| --&gt;
&lt;!-- | new_leem() | Construtor da classe *leem* | --&gt;
&lt;!-- | tabfreq()  | Disatribuição de frequência | --&gt;
&lt;!-- | hist()     | Hitograma de frequência     | --&gt;
&lt;!-- | ogive()    | Ogivas                      | --&gt;
&lt;!-- | polyfreq() | Polígono de frequências     | --&gt;
&lt;style type=&#34;text/css&#34;&gt;
.tg  {border-collapse:collapse;border-color:#93a1a1;border-spacing:0;}
.tg td{background-color:#fdf6e3;border-bottom-width:1px;border-color:#93a1a1;border-style:solid;border-top-width:1px;
  border-width:0px;color:#002b36;font-family:Arial, sans-serif;font-size:14px;overflow:hidden;padding:10px 5px;
  word-break:normal;}
.tg th{background-color:#657b83;border-bottom-width:1px;border-color:#93a1a1;border-style:solid;border-top-width:1px;
  border-width:0px;color:#fdf6e3;font-family:Arial, sans-serif;font-size:14px;font-weight:normal;overflow:hidden;
  padding:10px 5px;word-break:normal;}
.tg .tg-5lw0{background-color:#eee8d5;border-color:#ffffff;
  font-family:&#34;Lucida Sans Unicode&#34;, &#34;Lucida Grande&#34;, sans-serif !important;font-size:28px;text-align:left;
  vertical-align:middle}
.tg .tg-xzvq{border-color:#ffffff;font-family:&#34;Lucida Sans Unicode&#34;, &#34;Lucida Grande&#34;, sans-serif !important;font-size:28px;
  text-align:left;vertical-align:middle}
.tg .tg-vqs5{border-color:#ffffff;font-family:&#34;Lucida Sans Unicode&#34;, &#34;Lucida Grande&#34;, sans-serif !important;font-size:28px;
  font-weight:bold;text-align:left;vertical-align:middle}
&lt;/style&gt;
&lt;table class=&#34;tg&#34;&gt;
&lt;thead&gt;
  &lt;tr&gt;
    &lt;th class=&#34;tg-vqs5&#34;&gt;Função&lt;/th&gt;
    &lt;th class=&#34;tg-vqs5&#34;&gt;Finalidade&lt;/th&gt;
  &lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
  &lt;tr&gt;
    &lt;td class=&#34;tg-5lw0&#34;&gt; &lt;code&gt;base::sort()&lt;/code&gt;  &lt;/td&gt;
    &lt;td class=&#34;tg-5lw0&#34;&gt;Dados em rol &lt;/td&gt;
  &lt;/tr&gt;                               
  &lt;tr&gt;
    &lt;td class=&#34;tg-5lw0&#34;&gt; &lt;code&gt;new_leem()&lt;/code&gt;  &lt;/td&gt;
    &lt;td class=&#34;tg-5lw0&#34;&gt;Construtor da classe &lt;i&gt;leem&lt;/i&gt; &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td class=&#34;tg-xzvq&#34;&gt; &lt;code&gt;tabfreq()&lt;/code&gt;  &lt;/td&gt;
    &lt;td class=&#34;tg-xzvq&#34;&gt;Distribuição de frequência&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td class=&#34;tg-5lw0&#34;&gt; &lt;code&gt;hist()&lt;/code&gt; &lt;/td&gt;
    &lt;td class=&#34;tg-5lw0&#34;&gt;Hitograma de frequência&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td class=&#34;tg-xzvq&#34;&gt; &lt;code&gt;ogive()&lt;/code&gt; &lt;/td&gt;
    &lt;td class=&#34;tg-xzvq&#34;&gt;Ogivas&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td class=&#34;tg-5lw0&#34;&gt; &lt;code&gt;polyfreq()&lt;/code&gt; &lt;/td&gt;
    &lt;td class=&#34;tg-5lw0&#34;&gt;Polígono de frequências&lt;/td&gt;
  &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td class=&#34;tg-5lw0&#34;&gt; &lt;code&gt;stickplot()&lt;/code&gt; &lt;/td&gt;
    &lt;td class=&#34;tg-5lw0&#34;&gt;Gráfico de hastes ou bastão&lt;/td&gt;
  &lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt; Exemplo &lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Considere a distribuição de frequência do número de erros encontrados em 20 conjunto de carac-  teres monitorado em um canal de comunicação&lt;/li&gt;
&lt;/ol&gt;
&lt;style type=&#34;text/css&#34;&gt;
.tg  {border-collapse:collapse;border-color:#93a1a1;border-spacing:0;}
.tg td{background-color:#fdf6e3;border-bottom-width:1px;border-color:#93a1a1;border-style:solid;border-top-width:1px;
  border-width:0px;color:#002b36;font-family:Arial, sans-serif;font-size:14px;overflow:hidden;padding:10px 5px;
  word-break:normal;}
.tg th{background-color:#657b83;border-bottom-width:1px;border-color:#93a1a1;border-style:solid;border-top-width:1px;
  border-width:0px;color:#fdf6e3;font-family:Arial, sans-serif;font-size:14px;font-weight:normal;overflow:hidden;
  padding:10px 5px;word-break:normal;}
.tg .tg-j4p1{background-color:#eee8d5;color:#191919;font-family:&#34;Lucida Sans Unicode&#34;, &#34;Lucida Grande&#34;, sans-serif !important;
  font-size:28px;font-style:italic;font-weight:bold;text-align:right;vertical-align:middle}
.tg .tg-1bo1{background-color:#ffffff;border-color:#fdf6e3;
  font-family:&#34;Lucida Sans Unicode&#34;, &#34;Lucida Grande&#34;, sans-serif !important;font-size:28px;font-style:italic;
  font-weight:bold;text-align:right;vertical-align:middle}
&lt;/style&gt;
&lt;table class=&#34;tg&#34;&gt;
&lt;thead&gt;
  &lt;tr&gt;
    &lt;th class=&#34;tg-j4p1&#34;&gt;&lt;span style=&#34;font-weight:700&#34;&gt;3&lt;/span&gt;&lt;/th&gt;
    &lt;th class=&#34;tg-j4p1&#34;&gt;&lt;span style=&#34;font-weight:700&#34;&gt;0&lt;/span&gt;&lt;/th&gt;
    &lt;th class=&#34;tg-j4p1&#34;&gt;&lt;span style=&#34;font-weight:700&#34;&gt;3&lt;/span&gt;&lt;/th&gt;
    &lt;th class=&#34;tg-j4p1&#34;&gt;&lt;span style=&#34;font-weight:700&#34;&gt;4&lt;/span&gt;&lt;/th&gt;
    &lt;th class=&#34;tg-j4p1&#34;&gt;&lt;span style=&#34;font-weight:700&#34;&gt;3&lt;/span&gt;&lt;/th&gt;
    &lt;th class=&#34;tg-j4p1&#34;&gt;&lt;span style=&#34;font-weight:700&#34;&gt;1&lt;/span&gt;&lt;/th&gt;
    &lt;th class=&#34;tg-j4p1&#34;&gt;&lt;span style=&#34;font-weight:700&#34;&gt;2&lt;/span&gt;&lt;/th&gt;
    &lt;th class=&#34;tg-j4p1&#34;&gt;&lt;span style=&#34;font-weight:700&#34;&gt;3&lt;/span&gt;&lt;/th&gt;
    &lt;th class=&#34;tg-j4p1&#34;&gt;&lt;span style=&#34;font-weight:700&#34;&gt;0&lt;/span&gt;&lt;/th&gt;
    &lt;th class=&#34;tg-j4p1&#34;&gt;&lt;span style=&#34;font-weight:700&#34;&gt;0&lt;/span&gt;&lt;/th&gt;
  &lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
  &lt;tr&gt;
    &lt;td class=&#34;tg-1bo1&#34;&gt;1&lt;/td&gt;
    &lt;td class=&#34;tg-1bo1&#34;&gt;1&lt;/td&gt;
    &lt;td class=&#34;tg-1bo1&#34;&gt;2&lt;/td&gt;
    &lt;td class=&#34;tg-1bo1&#34;&gt;1&lt;/td&gt;
    &lt;td class=&#34;tg-1bo1&#34;&gt;1&lt;/td&gt;
    &lt;td class=&#34;tg-1bo1&#34;&gt;1&lt;/td&gt;
    &lt;td class=&#34;tg-1bo1&#34;&gt;3&lt;/td&gt;
    &lt;td class=&#34;tg-1bo1&#34;&gt;2&lt;/td&gt;
    &lt;td class=&#34;tg-1bo1&#34;&gt;2&lt;/td&gt;
    &lt;td class=&#34;tg-1bo1&#34;&gt;1&lt;/td&gt;
  &lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Exemplo&lt;/h2&gt;
&lt;ol start=&#34;2&#34;&gt;
&lt;li&gt;Os dados representam a temperatura (°F) do anel de vedação de cada teste de acionamento ou lançamento real do motor do foguete Challenger.&lt;/li&gt;
&lt;/ol&gt;
&lt;style type=&#34;text/css&#34;&gt;
.tg  {border-collapse:collapse;border-color:#93a1a1;border-spacing:0;}
.tg td{background-color:#fdf6e3;border-bottom-width:1px;border-color:#93a1a1;border-style:solid;border-top-width:1px;
  border-width:0px;color:#002b36;font-family:Arial, sans-serif;font-size:14px;overflow:hidden;padding:10px 5px;
  word-break:normal;}
.tg th{background-color:#657b83;border-bottom-width:1px;border-color:#93a1a1;border-style:solid;border-top-width:1px;
  border-width:0px;color:#fdf6e3;font-family:Arial, sans-serif;font-size:14px;font-weight:normal;overflow:hidden;
  padding:10px 5px;word-break:normal;}
.tg .tg-61io{background-color:#eee8d5;color:#191919;font-size:28px;font-style:italic;font-weight:bold;text-align:left;
  vertical-align:middle}
.tg .tg-8svn{background-color:#fdf6e3;color:#191919;font-size:28px;font-style:italic;font-weight:bold;text-align:left;
  vertical-align:middle}
.tg .tg-aete{background-color:#fdf6e3;color:#191919;font-family:&#34;Lucida Sans Unicode&#34;, &#34;Lucida Grande&#34;, sans-serif !important;
  font-size:28px;font-style:italic;font-weight:bold;text-align:left;vertical-align:middle}
.tg .tg-4ynv{background-color:#eee8d5;color:#191919;font-family:&#34;Lucida Sans Unicode&#34;, &#34;Lucida Grande&#34;, sans-serif !important;
  font-size:28px;font-style:italic;font-weight:bold;text-align:left;vertical-align:middle}
.tg .tg-uika{color:#191919;font-size:28px;font-style:italic;font-weight:bold;text-align:left;vertical-align:middle}
&lt;/style&gt;
&lt;table class=&#34;tg&#34;&gt;
&lt;thead&gt;
  &lt;tr&gt;
    &lt;th class=&#34;tg-aete&#34;&gt;84&lt;/th&gt;
    &lt;th class=&#34;tg-aete&#34;&gt;49&lt;/th&gt;
    &lt;th class=&#34;tg-aete&#34;&gt;61&lt;/th&gt;
    &lt;th class=&#34;tg-aete&#34;&gt;40&lt;/th&gt;
    &lt;th class=&#34;tg-aete&#34;&gt;83&lt;/th&gt;
    &lt;th class=&#34;tg-aete&#34;&gt;67&lt;/th&gt;
    &lt;th class=&#34;tg-aete&#34;&gt;45&lt;/th&gt;
    &lt;th class=&#34;tg-aete&#34;&gt;66&lt;/th&gt;
    &lt;th class=&#34;tg-aete&#34;&gt;70&lt;/th&gt;
    &lt;th class=&#34;tg-aete&#34;&gt;69&lt;/th&gt;
    &lt;th class=&#34;tg-8svn&#34;&gt;80&lt;/th&gt;
    &lt;th class=&#34;tg-8svn&#34;&gt;58&lt;/th&gt;
  &lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
  &lt;tr&gt;
    &lt;td class=&#34;tg-4ynv&#34;&gt;68&lt;/td&gt;
    &lt;td class=&#34;tg-4ynv&#34;&gt;60&lt;/td&gt;
    &lt;td class=&#34;tg-4ynv&#34;&gt;67&lt;/td&gt;
    &lt;td class=&#34;tg-4ynv&#34;&gt;72&lt;/td&gt;
    &lt;td class=&#34;tg-4ynv&#34;&gt;73&lt;/td&gt;
    &lt;td class=&#34;tg-4ynv&#34;&gt;70&lt;/td&gt;
    &lt;td class=&#34;tg-4ynv&#34;&gt;57&lt;/td&gt;
    &lt;td class=&#34;tg-4ynv&#34;&gt;63&lt;/td&gt;
    &lt;td class=&#34;tg-4ynv&#34;&gt;70&lt;/td&gt;
    &lt;td class=&#34;tg-4ynv&#34;&gt;78&lt;/td&gt;
    &lt;td class=&#34;tg-61io&#34;&gt;52&lt;/td&gt;
    &lt;td class=&#34;tg-61io&#34;&gt;67&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td class=&#34;tg-uika&#34;&gt;53&lt;/td&gt;
    &lt;td class=&#34;tg-uika&#34;&gt;67&lt;/td&gt;
    &lt;td class=&#34;tg-uika&#34;&gt;75&lt;/td&gt;
    &lt;td class=&#34;tg-uika&#34;&gt;61&lt;/td&gt;
    &lt;td class=&#34;tg-uika&#34;&gt;70&lt;/td&gt;
    &lt;td class=&#34;tg-uika&#34;&gt;81&lt;/td&gt;
    &lt;td class=&#34;tg-uika&#34;&gt;76&lt;/td&gt;
    &lt;td class=&#34;tg-uika&#34;&gt;79&lt;/td&gt;
    &lt;td class=&#34;tg-uika&#34;&gt;75&lt;/td&gt;
    &lt;td class=&#34;tg-uika&#34;&gt;76&lt;/td&gt;
    &lt;td class=&#34;tg-uika&#34;&gt;58&lt;/td&gt;
    &lt;td class=&#34;tg-uika&#34;&gt;31&lt;/td&gt;
  &lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;style&gt;
.container{
  display: grid;
  text-align: left;
  grid-auto-flow: column;
}
.col {
  width: 500px;
  height: 300px;
  border: 3px solid #0094ff;
}
.col2 {
  width: 500px;
  height: 500px;
  border: 3px solid #0094ff;
}
.col3 {
  width: 500px;
  height: 400px;
  border: 3px solid #0094ff;
}

&lt;/style&gt;
&lt;section&gt;
&lt;h1&gt; &lt;code&gt;leem&lt;/code&gt; em ação &lt;/h1&gt;
&lt;hr&gt;
&lt;h2&gt; Importando os dados &lt;/h2&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;# Numero de erros
d1 &amp;lt;- read.table(&amp;quot;https://raw.githubusercontent.com/bendeivide/book-epaec/master/dados/cap02/nerros.txt&amp;quot;, h = TRUE)
(d1 &amp;lt;- d1$erros)

# Temperatura do foguete Challenger
d2 &amp;lt;- read.table(&amp;quot;https://raw.githubusercontent.com/bendeivide/book-epaec/master/dados/cap02/challenger.txt&amp;quot;, h = TRUE)
(d2 &amp;lt;- d2$chal)

&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre&gt;&lt;code&gt;##  [1] 3 1 0 1 3 2 4 1 3 1 1 1 2 3 3 2 0 2 0 1
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;##  [1] 84 49 61 40 83 67 45 66 70 69 80 58 68 60 67 72 73 70 57 63 70 78 52 67 53
## [26] 67 75 61 70 81 76 79 75 76 58 31
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h2&gt; Dados em rol &lt;/h2&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;sort(d1)
sort(d2)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;pre&gt;&lt;code&gt;##  [1] 0 0 0 1 1 1 1 1 1 1 2 2 2 2 3 3 3 3 3 4
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;##  [1] 31 40 45 49 52 53 57 58 58 60 61 61 63 66 67 67 67 67 68 69 70 70 70 70 72
## [26] 73 75 75 76 76 78 79 80 81 83 84
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h2&gt; Distribuição de frequências &lt;/h2&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col2&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;## Forma convencional:
aux &amp;lt;- new_leem(d1, 1)
tabd1 &amp;lt;- tabfreq(aux); tabd1
#-----
aux &amp;lt;- new_leem(d2, 2)
tabd2 &amp;lt;- tabfreq(aux); tabd2 
## Usando o operador &#39;pipe&#39; nativo
d1 |&amp;gt; new_leem(variable = 1) |&amp;gt; tabfreq() 
d2 |&amp;gt; new_leem(variable = 2) |&amp;gt; tabfreq() 
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col2&#34;&gt;
&lt;pre&gt;&lt;code&gt;##   Groups Fi   Fr Fac1 Fac2 Fp Fac1p Fac2p
## 1      0  3 0.15    3   20 15    15   100
## 2      1  7 0.35   10   17 35    50    85
## 3      2  4 0.20   14   10 20    70    50
## 4      3  5 0.25   19    6 25    95    30
## 5      4  1 0.05   20    1  5   100     5
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;##            Classe Fi   PM   Fr Fac1 Fac2 Fp  Fac1p  Fac2p
## 1 25.7 |---  36.3  1 31.0 0.03    1   36  3   2.78 100.00
## 2 36.3 |---  46.9  2 41.6 0.06    3   35  6   8.33  97.22
## 3 46.9 |---  57.5  4 52.2 0.11    7   33 11  19.44  91.67
## 4 57.5 |---  68.1 12 62.8 0.33   19   29 33  52.78  80.56
## 5 68.1 |---  78.7 12 73.4 0.33   31   17 33  86.11  47.22
## 6 78.7 |---  89.3  5 84.0 0.14   36    5 14 100.00  13.89
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h2&gt; Apresentação gráfica &lt;/h2&gt;
&lt;h3&gt;Gráfico de hastes ou bastão&lt;/h3&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col2&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;# Forma convencional:
aux1 &amp;lt;- new_leem(d1, variable = &amp;quot;discrete&amp;quot;)
aux2 &amp;lt;- tabfreq(aux1)
stickplot(aux2, 
          lwd=3, # largura da linha
          pcol = &amp;quot;red&amp;quot;, # cor da linha
          bgcol = &amp;quot;lightgray&amp;quot;, # cor do fundo
          panel.first = grid(col = &amp;quot;white&amp;quot;) # inserindo grid e sua cor
)
# Usando o pipe
d1 |&amp;gt; 
  new_leem(variable = &amp;quot;discrete&amp;quot;) |&amp;gt; 
  tabfreq() |&amp;gt; 
  stickplot(lwd=3, # largura da linha
            pcol = &amp;quot;red&amp;quot;, # cor da linha
            bgcol = &amp;quot;lightgray&amp;quot;, # cor do fundo
            panel.first = grid(col = &amp;quot;white&amp;quot;) # inserindo grid e sua cor
            )
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col2&#34;&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s04/index_files/figure-html/unnamed-chunk-11-1.png&#34; width=&#34;672&#34; /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h3&gt;Gráfico de barras&lt;/h3&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col2&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;# Forma convencional:
aux1 &amp;lt;- new_leem(d1, variable = 1)
aux2 &amp;lt;- tabfreq(aux1)
barplot(aux2, barcol = heat.colors(5))
# Usando o pipe
d1 |&amp;gt; 
  new_leem(variable = 1) |&amp;gt; 
    tabfreq() |&amp;gt; 
      barplot(barcol = heat.colors(5))
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col2&#34;&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s04/index_files/figure-html/unnamed-chunk-12-1.png&#34; width=&#34;672&#34; /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h3&gt;Histograma de frequências&lt;/h3&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;# Usando o pipe:
d2 |&amp;gt; 
  new_leem(variable = 2) |&amp;gt; 
    tabfreq() |&amp;gt; 
      hist(barcol = heat.colors(6))
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s04/index_files/figure-html/unnamed-chunk-13-1.png&#34; width=&#34;672&#34; /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h3&gt;Polígono&lt;/h3&gt;
&lt;h4&gt;Dados discretos&lt;/h4&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;# Usando o pipe:
d1 |&amp;gt; 
  new_leem(variable = 1) |&amp;gt; 
    tabfreq() |&amp;gt; 
      polyfreq(barcol = heat.colors(5),
           main = &amp;quot;Polígono de frequências e
Histograma de frequências&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s04/index_files/figure-html/unnamed-chunk-14-1.png&#34; width=&#34;672&#34; /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h3&gt;Polígono&lt;/h3&gt;
&lt;h4&gt;Dados contínuos&lt;/h4&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;# Usando o pipe:
d2 |&amp;gt; 
  new_leem(variable = 2) |&amp;gt; 
    tabfreq() |&amp;gt; 
      polyfreq(barcol = heat.colors(5),
           main = &amp;quot;Polígono de frequências e
Histograma de frequências&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s04/index_files/figure-html/unnamed-chunk-15-1.png&#34; width=&#34;672&#34; /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h3&gt;Polígono&lt;/h3&gt;
&lt;h4&gt;Sem as barras&lt;/h4&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;# Usando o pipe:
d2 |&amp;gt; 
  new_leem(variable = 2) |&amp;gt; 
    tabfreq() |&amp;gt; 
      polyfreq(bars = FALSE)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s04/index_files/figure-html/unnamed-chunk-16-1.png&#34; width=&#34;672&#34; /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h3&gt;Ogivas&lt;/h3&gt;
&lt;h4&gt;Dados discretos (Crescente)&lt;/h4&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;# Usando o pipe:
d1 |&amp;gt; 
  new_leem(variable = 1) |&amp;gt; 
    tabfreq() |&amp;gt; 
      ogive(bars = TRUE, barcol = &amp;quot;red&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s04/index_files/figure-html/unnamed-chunk-17-1.png&#34; width=&#34;672&#34; /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h3&gt;Ogivas&lt;/h3&gt;
&lt;h4&gt;Dados discretos (Decrescente)&lt;/h4&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;d1 |&amp;gt; 
  new_leem(variable = 1) |&amp;gt; 
   tabfreq() |&amp;gt; 
    ogive(decreasing = TRUE, 
        bars = TRUE, barcol = &amp;quot;yellow&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s04/index_files/figure-html/unnamed-chunk-18-1.png&#34; width=&#34;672&#34; /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h3&gt;Ogivas&lt;/h3&gt;
&lt;h4&gt;Dados discretos (Ambos)&lt;/h4&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;d1 |&amp;gt; 
  new_leem(variable = 1) |&amp;gt; 
  tabfreq() |&amp;gt; 
  ogive(both = TRUE, # ambas ogivas 
        bars = TRUE, # barras
        barcol = c(&amp;quot;red&amp;quot;, &amp;quot;yellow&amp;quot;))
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s04/index_files/figure-html/unnamed-chunk-19-1.png&#34; width=&#34;672&#34; /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h3&gt;Ogivas&lt;/h3&gt;
&lt;h4&gt;Dados contínuos (Crescente)&lt;/h4&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;d2 |&amp;gt; 
  new_leem(variable = 2) |&amp;gt; 
  tabfreq() |&amp;gt; 
  ogive(bars = TRUE, barcol = &amp;quot;red&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s04/index_files/figure-html/unnamed-chunk-20-1.png&#34; width=&#34;672&#34; /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h3&gt;Ogivas&lt;/h3&gt;
&lt;h4&gt;Dados contínuos (Decrescente)&lt;/h4&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;d2 |&amp;gt; 
  new_leem(variable = 2) |&amp;gt; 
  tabfreq() |&amp;gt; 
  ogive(decreasing = TRUE, 
        bars = TRUE, barcol = &amp;quot;yellow&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s04/index_files/figure-html/unnamed-chunk-21-1.png&#34; width=&#34;672&#34; /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h3&gt;Ogivas&lt;/h3&gt;
&lt;h4&gt;Dados contínuos (Ambos)&lt;/h4&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;d2 |&amp;gt; 
  new_leem(variable = 2) |&amp;gt; 
  tabfreq() |&amp;gt; 
  ogive(both = TRUE, # ambas ogivas 
        bars = TRUE, # barras
        barcol = c(&amp;quot;red&amp;quot;, &amp;quot;yellow&amp;quot;))
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s04/index_files/figure-html/unnamed-chunk-22-1.png&#34; width=&#34;672&#34; /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h3&gt;Ogivas&lt;/h3&gt;
&lt;h4&gt;Dados contínuos (Ambos + Histograma)&lt;/h4&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;d2 |&amp;gt; 
  new_leem(variable = 2) |&amp;gt; 
  tabfreq() |&amp;gt; 
  ogive(both = TRUE, # ambas ogivas 
        bars = TRUE, # barras
        barcol = c(&amp;quot;red&amp;quot;, &amp;quot;yellow&amp;quot;), # cor da barra das duas ogivas
        histogram = TRUE, # incluindo o histograma
        histcol = gray.colors(6), # cor do histograma
        bgcol = &amp;quot;purple&amp;quot;) # cor do fundo
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s04/index_files/figure-html/unnamed-chunk-23-1.png&#34; width=&#34;672&#34; /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;fundo02.png&#34;
  &gt;

&lt;h1 id=&#34;questões&#34;&gt;Questões?&lt;/h1&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Dúvidas e Sugestões&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/#contact&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Contato&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Estatística e Probabilidade</title>
      <link>http://bendeivide.github.io/slides/profmat-est/s11/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/profmat-est/s11/</guid>
      <description>
&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap.png&#34;
  &gt;

&lt;h1 id=&#34;estatística-e-probabilidade&#34;&gt;Estatística e Probabilidade&lt;/h1&gt;
&lt;p&gt;Aula 11 - Probabilidades
&lt;/br&gt;&lt;/p&gt;
&lt;p&gt;
  &lt;i class=&#34;fas fa-user-tie  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;https://bendeivide.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Ben Dêivide&lt;/a&gt; | 
  &lt;i class=&#34;fas fa-school  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;https://www.ufsj.edu.br/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;UFSJ&lt;/a&gt;
&lt;/br&gt;

  &lt;i class=&#34;fas fa-book  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;http://bendeivide.github.io/courses/epaec/&#34;&gt;Estatística e Probabilidade&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;selo-dc&#34;&gt;Selo DC&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/dc/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/profmat-est/s11/SeloDC-preto_hu7eace1d7dbb403f37b46437825b208a2_37049_1f8e03062ff2fd4b85b7997b55db9e55.webp 400w,
               /slides/profmat-est/s11/SeloDC-preto_hu7eace1d7dbb403f37b46437825b208a2_37049_28a718b08e0f1b8193cec5ac4d8216a2.webp 760w,
               /slides/profmat-est/s11/SeloDC-preto_hu7eace1d7dbb403f37b46437825b208a2_37049_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/profmat-est/s11/SeloDC-preto_hu7eace1d7dbb403f37b46437825b208a2_37049_1f8e03062ff2fd4b85b7997b55db9e55.webp&#34;
               width=&#34;384&#34;
               height=&#34;406&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;section&gt;
&lt;h2&gt;Teoria de conjuntos no contexto probabilístico
&lt;/h2&gt;
&lt;div id=&#34;def:expaleatorio&#34; class=&#34;definicao&#34; cap=5 titulo=&#34;(Experimento Aleatório)&#34;&gt;
&lt;p&gt;Todo experimento cujo resultado não pode ser previsto antes de sua execução, é chamado de experimento aleatório.&lt;/p&gt;
&lt;/br&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Exemplos&lt;/h2&gt;
&lt;div id=&#34;exem:espamos1&#34; class=&#34;exemplo&#34; cap=5 titulo=&#34;Espaço amostral&#34;&gt;
&lt;p&gt;Lançar um dado equilibrado e observar o resultado obtido na face superior do dado.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;exem:espamos2&#34; class=&#34;exemplo&#34; cap=5 titulo=&#34;Espaço amostral&#34;&gt;
&lt;p&gt;Observar o número de chamadas telefônicas que chegam a uma central telefônica em um determinado intervalo de tempo.&lt;/p&gt;
&lt;/div&gt;
&lt;div &lt;div id=&#34;exem:espamos2&#34; class=&#34;exemplo&#34; cap=5 titulo=&#34;Espaço amostral&#34;&gt;
&lt;p&gt;Para a escolha ao acaso de uma lâmpada que acabou de sair do processo de fabricação, verificar o tempo de duração da lâmpada em funcionamento.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Experimento aleatório&lt;/h2&gt;
&lt;p&gt;Em um contexto aplicado, podemos estar interessados em estudar a resistência de um fio de cobre a uma determinada corrente&lt;/p&gt;














&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/profmat-est/s11/expaleatorio_hu5a0b4df49306a6ef742584dc0fd72a48_101457_689ca7e4b39dd65b6cfdf93a7cced401.webp 400w,
               /slides/profmat-est/s11/expaleatorio_hu5a0b4df49306a6ef742584dc0fd72a48_101457_93c7f3ea0b91359b2e0af9511a60874d.webp 760w,
               /slides/profmat-est/s11/expaleatorio_hu5a0b4df49306a6ef742584dc0fd72a48_101457_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/profmat-est/s11/expaleatorio_hu5a0b4df49306a6ef742584dc0fd72a48_101457_689ca7e4b39dd65b6cfdf93a7cced401.webp&#34;
               width=&#34;630&#34;
               height=&#34;220&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Espaço amostral&lt;/h2&gt;
&lt;div id=&#34;def:espamostral&#34; class=&#34;definicao&#34; cap=5 titulo=&#34;(Espaço amostral)&#34;&gt;
&lt;p&gt;O conjunto de todos os resultados possíveis de um experimento, denotado por $ \Omega $, é chamado de espaço amostral.&lt;/p&gt;
&lt;/br&gt;
&lt;/div&gt;
&lt;/br&gt;
&lt;ul&gt;
&lt;li&gt;Cada um dos elementos do espaço amostral é representado por &lt;code&gt;\(\omega\)&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Relações:
&lt;ul&gt;
&lt;li&gt;Pertinência: &lt;code&gt;\(\omega \in \Omega\)&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Continência: &lt;code&gt;\(A \subset B \Leftrightarrow \omega \in A \Rightarrow \omega \in B\)&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Equivalência: &lt;code&gt;\(A = B \Leftrightarrow A \subset B \textrm{ e } B \subset A\)&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Espaços amostrais discretos e contínuos&lt;/h2&gt;
&lt;div id=&#34;def:espdisccont&#34; class=&#34;definicao&#34; cap=5 titulo=&#34;(Espaços amostrais discretos e contínuos)&#34;&gt;
&lt;p&gt;Um espaço amostral é discreto se o conjunto dos possíveis resultados são finito ou infinito contável (ou enumerável). Um espaço amostral é dito contínuo se o conjunto dos possíveis resultados são infinitos não contável (ou não enumerável). &lt;/p&gt;
&lt;/br&gt;
&lt;/div&gt;
&lt;/br&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Exemplo&lt;/h2&gt;
&lt;div id=&#34;exem:espdisccont&#34; class=&#34;exemplo&#34; font-size: &#34;12px&#34; cap=5 titulo=&#34;Câmera Flash&#34;&gt;
&lt;p&gt;Considere um experimento em que você seleciona uma câmera de telefone celular e registra o tempo de recarga de um &lt;i&gt;flash&lt;/i&gt;. Os resultados possíveis para o tempo dependem da resolução do temporizador e dos tempos máximo e mínimo de recarga. Entretanto, podemos definir inicialmente o espaço amostral em termos da reta real positiva ($\mathbb{R}_+$), isto é,&lt;/p&gt;
\begin{align*}
  \Omega = \mathbb{R}_+  &amp; = \{ x ~:~ x &gt; 0\}.
\end{align*}
&lt;p&gt;Se soubermos que os tempos de recarga estão entre $ 1,5 $ e $ 5 $ segundos, podemos definir o espaço amostral da seguinte forma:&lt;/p&gt;
\begin{align*}
  \Omega  &amp; = \{ x ~:~ 1,5 \leq x \leq 5\}.
\end{align*}
&lt;p&gt;Caso, consideremos o tempo de recarga como &#34;baixo&#34;, &#34;médio&#34; ou &#34;alto&#34;, reescrevemos o espaço amostral como:&lt;/p&gt;
\begin{align*}
  \Omega &amp; =  \{ \textrm{baixo}, \textrm{médio}, \textrm{alto} \}.
\end{align*}
&lt;/br&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Exemplo (continuação...)&lt;/h2&gt;
&lt;div id=&#34;exem:espdisccont&#34; class=&#34;exemplo&#34; cap=5 titulo=&#34;Câmera Flash&#34;&gt;
&lt;p&gt;Por fim, podemos considerar apenas o fato da câmera satisfazer ou não as especificações do tempo de recarga mínimo, e assim, podemos assumir como resultados para esse espaço amostral: &#34;sim&#34; ou não&#34;, isto é,&lt;/p&gt;
\begin{align*}
  \Omega &amp; =  \{\textrm{sim},~\textrm{não}\}.
\end{align*}
&lt;p&gt;Para as duas primeiras situações, temos exemplos de espaços amostrais contínuos, e nos dois últimos, exemplos de espaços amostrais discretos.&lt;/p&gt;
&lt;/br&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Subconjunto&lt;/h2&gt;
&lt;div id=&#34;def:subcj&#34; class=&#34;definicao&#34; cap=5 titulo=&#34;(Subconjunto)&#34;&gt;
&lt;p&gt;Se todo elemento do conjunto A é também elemento do conjunto B, então A é definido como um subconjunto de B, sendo representado $ A\subset B $ ou $ B\supset A $ (A está contido em B ou B contém A), em notação dizemos que:&lt;/p&gt;
\begin{align*}
  A \subset B \Leftrightarrow A \subseteq B \textrm{ e } A \neq B.
\end{align*}
&lt;/br&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Essa definição pode ser aplicada também a subconjuntos de $ \Omega $, como apresentado no Exemplo sobre subconjuntos, a seguir.&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Exemplo&lt;/h2&gt;
&lt;div id=&#34;exem:subconjunto&#34; class=&#34;exemplo&#34; cap=5 titulo=&#34;&#34;&gt;
&lt;p&gt;Sejam os subconjuntos de $ \Omega $ do experimento aleatório apresentado no Exemplo sobre espaços amostrais, dos quais temos:&lt;/p&gt;
\begin{align*}
B=\{ 1,2,3,4 \} \ \mbox{ e } \ A= \{ 1,2,3 \},
\end{align*}
&lt;p&gt;então A é um subconjunto de B, pois, os elementos que contém em A, também contém em B.&lt;/p&gt;
&lt;/br&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Evento&lt;/h2&gt;
&lt;div id=&#34;def:subcj&#34; class=&#34;definicao&#34; cap=5 titulo=&#34;(Evento)&#34;&gt;
&lt;/br&gt;
&lt;p&gt;Todo subconjunto do espaço amostral ($ \Omega $), representado por letras latinas em maiúsculo, A, B, $ \ldots $, é chamado de evento.&lt;/p&gt;
&lt;/br&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Exemplo&lt;/h2&gt;
&lt;div id=&#34;exem:subcj2&#34; class=&#34;exemplo&#34; cap=5 titulo=&#34;&#34;&gt;
&lt;p&gt;Um experimento lança três moedas honestas, e deseja-se verificar a face superior dessas moedas. Sabe-se que cada moeda apresenta duas faces: cara (H) e coroa (T). Dessa forma, o espaço amostral é dado por:&lt;/p&gt;
\begin{align*}
\Omega = &amp;\{(H,H,H),(H,H,T),(H,T,H),(H,T,T),\\
       &amp; (T,H,H),(T,H,T),(T,T,H),(T,T,T)\}.
\end{align*}
&lt;p&gt;Um evento retirado desse espaço amostral seria $ A=\{(H,H,H) $, $ (H,H,T) $, $ (H,T,T) \} $, ou seja, o evento em que dos três arremessos de moedas, tenha saído &#34;cara&#34; na primeira moeda.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Evento certo, impossível e elementar&lt;/h2&gt;
&lt;div id=&#34;def:eventosbasicos&#34; class=&#34;definicao&#34; cap=5 titulo=&#34;(Evento certo, impossível e elementar)&#34;&gt;
&lt;p&gt;Seja $ \Omega $ o espaço amostral do experimento. Então dizemos que $ \Omega $ é o evento certo, e $ \emptyset $ é o evento impossível, e o evento $ \{\omega\} $ é dito elementar.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Conjunto vazio&lt;/h2&gt;
&lt;div id=&#34;def:conjvazio&#34; class=&#34;definicao&#34; cap=5 titulo=&#34;(Conjunto vazio)&#34;&gt;
&lt;p&gt;Se o conjunto A não contém nenhum elemento, então A é chamado de conjunto nulo ou conjunto vazio, ou seja, $ A=\varnothing $ ou $ A=\{ \ \} $, isto é,&lt;/p&gt;
\begin{align*}
  A &amp; = \{\omega \in \Omega: \omega \neq \omega \}.
\end{align*}
&lt;/br&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;União de dois eventos&lt;/h2&gt;
&lt;div id=&#34;def:udoisevt&#34; class=&#34;definicao&#34; cap=5 titulo=&#34;(União de dois eventos)&#34;&gt;
&lt;p&gt;Sejam A e B, dois eventos quaisquer de $ \Omega $, então o conjunto de todos os elementos que estão em A ou B ou em ambos, é definido como o conjunto união de A e B, denotado por $ A\cup B $, tal que,&lt;/p&gt;
\begin{align*}
  A\cup B &amp; = \{\omega \in \Omega: ~\omega \in A \textrm{ ou } \omega \in B\}.
\end{align*}
&lt;/br&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Exemplo&lt;/h2&gt;
&lt;div id=&#34;exem:udoisevt&#34; class=&#34;exemplo&#34; cap=5 titulo=&#34;&#34;&gt;
&lt;p&gt;Sejam os conjuntos:&lt;/p&gt;
\begin{align*}
  A &amp; =\{1,2,3\} \ \mbox{e} \ B=\{3,4,5,6\},
\end{align*}
&lt;p&gt;então&lt;/p&gt;
\begin{align*}
  A\cup B &amp; =\{1,2,3,4,5,6\}.
\end{align*}
&lt;/br&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Interseção de dois eventos&lt;/h2&gt;
&lt;div id=&#34;def_inteventos&#34; class=&#34;definicao&#34; cap=5 titulo=&#34;(Interseção de dois eventos)&#34;&gt;
&lt;p&gt;Sejam A e B, dois eventos quaisquer de $ \Omega $, então o conjunto que contém todos os elementos que estão em A e B, é definido como a interseção de A e B, denotado por $ A\cap B $ ou $ AB $, tal que,&lt;/p&gt;
\begin{align*}
  A \cap B &amp; = \{\omega \in \Omega: ~\omega \in A \textrm{ e } \omega \in B\}.
\end{align*}
&lt;/br&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;ul&gt;
&lt;li&gt;Do Exemplo sobre união de eventos, temos que a intersecção de $ AB = {3} $.&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Eventos Disjuntos ou multuamente exclusivos&lt;/h2&gt;
&lt;div id=&#34;def:disjeventos&#34; class=&#34;definicao&#34; cap=5 titulo=&#34;(Eventos Disjuntos ou multuamente exclusivos)&#34;&gt;
&lt;p&gt;Sejam A e B, dois eventos quaisquer de $ \Omega $, então estes são disjuntos ou mutuamente exclusivos quando não existir elementos em comum entre A e B, isto é, $ A\cap B = \emptyset $.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Exemplo&lt;/h2&gt;
&lt;div id=&#34;exem:disjeventos&#34; class=&#34;exemplo&#34; cap=5 titulo=&#34;&#34;&gt;
&lt;p&gt;Sejam os eventos $ A=\{1,2,3,4\} $ e $ B=\{5,6\} $, então $ A\cap B=\varnothing $.&lt;/p&gt;
&lt;/br&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Eventos equivalentes&lt;/h2&gt;
&lt;div id=&#34;def:equieventos&#34; class=&#34;definicao&#34; cap=5 titulo=&#34;(Eventos equivalentes)&#34;&gt;
&lt;p&gt;Dois eventos $ A $ e $ B $ são definidos equivalentes, ou iguais, se $ A\subseteq B $ e $ B \subseteq A $.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Exemplo&lt;/h2&gt;
&lt;div id=&#34;exem:equieventos&#34; class=&#34;exemplo&#34; cap=5 titulo=&#34;&#34;&gt;
&lt;p&gt;Sejam os eventos $ A=\{1,2,3,4\} $ e $ B=\{5,6\} $, então $ A\cap B=\varnothing $.&lt;/p&gt;
&lt;/br&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Evento complementar&lt;/h2&gt;
&lt;div id=&#34;def:compevento&#34; class=&#34;definicao&#34; cap=5 titulo=&#34;(Evento Complementar)&#34;&gt;
&lt;p&gt;Seja $ A $ um evento de $ \Omega $. Então o complemento do evento A com respeito a $ \Omega $, denotado por $ \overline{A} $, $ A^c $, ou $ \Omega-A $, é o subconjunto dos elementos de $ \Omega $ exceto os elementos do evento A, isto é,&lt;/p&gt;
\begin{align*}\label{compeventos}
  A^c &amp; = \{\omega \in \Omega: ~ \omega \notin A\}.
\end{align*}
&lt;/br&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Exemplo&lt;/h2&gt;
&lt;div id=&#34;exem:compevento&#34; class=&#34;exemplo&#34; cap=5 titulo=&#34;&#34;&gt;
&lt;p&gt;Seja o espaço amostral  $ \Omega $ do experimento que consiste em arremessar três moedas honestas. Diremos que $ H $ consiste na face superior da moeda ser cara, e $ T $ coroa. Assim,&lt;/p&gt;
\begin{align*}
\Omega = &amp;\{(H,H,H),(H,H,T),(H,T,H),(H,T,T),\\
&amp; (T,H,H),(T,H,T),(T,T,H),(T,T,T)\}.
\end{align*}
&lt;p&gt;e um subconjunto de $ \Omega $, cujo evento será aparecer cara na primeira moeda, dado por&lt;/p&gt;
$$ A=\{(H,H,H),(H,H,T),(H,T,H), (H,T,T)\}. $$
&lt;p&gt;Então o complemento de A será:&lt;/p&gt;
$$ \overline{A}=\{(T,H,H),(T,H,T), (T,T,H), (T,T,T)\}. $$
&lt;/br&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Diferença de dois eventos&lt;/h2&gt;
&lt;div id=&#34;def:difeventos&#34; class=&#34;definicao&#34; cap=5 titulo=&#34;(Diferença de dois eventos)&#34;&gt;
&lt;p&gt;Sejam A e B dois eventos de $ \Omega $. O conjunto de todos os elementos de $ A $ que não estão em $ B $, serão denotados por $ A-B $ ou $ A\setminus B $, sendo definido por conjunto diferença, isto é,&lt;/p&gt;
\begin{align*}
  A - B &amp; = \{\omega \in \Omega: ~\omega \in A \textrm{ e } \omega \notin B\}.
\end{align*}
&lt;/br&gt;
&lt;/div&gt;
&lt;aside class=&#34;notes&#34;&gt;
  📝 A Definição  de diferença de conjuntos pode ser confundida com a Definição evento complementar, porém esta última se remete ao espaço amostral, e a diferença entre dois eventos se refere apenas a existência dos elementos de um evento que não estão em outro evento. Vejamos o Exemplo diferença de evendos, e depois compare com o Exemplo de evento complementar, para elucidar essas duas definições.
&lt;/aside&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Exemplo&lt;/h2&gt;
&lt;div id=&#34;exem:compevento&#34; class=&#34;exemplo&#34; cap=5 titulo=&#34;&#34;&gt;
&lt;p&gt; Sejam os conjuntos $ A=\{1,2,3,4\} $ e $ B =\{3,4\} $, então $ A-B=\{1,2\} $. &lt;/p&gt;
&lt;/br&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Partição&lt;/h2&gt;
&lt;div id=&#34;def:particao&#34; class=&#34;definicao&#34; cap=5 titulo=&#34;(Partição)&#34;&gt;
&lt;p&gt;Considerando uma sequência de eventos $ A_1 $, $ A_2 $, $ \ldots $, $ A_n $, não vazios, é uma partição do evento $ A $, se e somente se,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$ A = \bigcup_{i = 1}^{n}A_i $;&lt;/li&gt;
&lt;li&gt;$ A_1 $, $ A_2 $, $ \ldots $, $ A_n $ são multuamente disjuntos, tais que $ A_i \cap A_j, ~\forall i \neq j $.
&lt;/br&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Leis na teoria de conjuntos&lt;/h2&gt;
&lt;div id=&#34;def:leiconj&#34; class=&#34;definicao&#34; cap=5 titulo=&#34;(Leis na teoria de conjuntos)&#34;&gt;
&lt;p&gt;Considere três eventos $ A $, $ B $, e $ C $ definidos em $ \Omega $, então segue que:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Lei comutativa: $ A\cup B = B \cup A$ e  $A\cap B = B \cap A $;&lt;/li&gt;
&lt;li&gt;Lei associativa: $ A \cup (B\cup C)=(A\cup B)\cup C $;&lt;/li&gt;
&lt;li&gt;Lei distributiva: $ A \cup (B \cap C)=(A\cup B)\cap (A\cup C) $ e $ A \cap (B \cup C)=(A\cap B)\cup (A\cap C) $;&lt;/li&gt;
&lt;li&gt;Lei DeMorgan: $ (A \cup B)^c = A^c \cap B^c $ e $( A \cap B)^c = A^c \cup B^c $.
&lt;/br&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/br&gt;
&lt;div id=&#34;prova:leiconj&#34; class=&#34;prova&#34; cap=5 titulo=&#34;&#34;&gt;
&lt;p&gt;Ver livro &lt;a href=&#34;https://bendeivide.github.io/book-epaec/&#34;&gt;EPAEC&lt;/a&gt;!. &lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Identidades em conjuntos&lt;/h2&gt;
&lt;div id=&#34;def:identconj&#34; class=&#34;definicao&#34; cap=5 titulo=&#34;(Identidade em conjuntos)&#34;&gt;
&lt;p&gt;Sejam os eventos $ A $ e $ B $ definidos no espaço amostral  $ \Omega $, não vazio. Então, apresentamos as seguintes identidades:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$ A\cap A^c = \emptyset $;&lt;/li&gt;
&lt;li&gt;$ A \cup A^c = \Omega $;&lt;/li&gt;
&lt;li&gt;$ \Omega^c = \emptyset $;&lt;/li&gt;
&lt;li&gt;$ \emptyset^c = \Omega $;&lt;/li&gt;
&lt;li&gt;$ (A^C)^C=\overline{(\overline{A})}=A $, em outras palavras, o complemento de $ \overline{A} $ é igual a $ A $;&lt;/li&gt;
&lt;li&gt;$ A\Omega=A $ (Elemento neutro);&lt;/li&gt;
&lt;li&gt;$ A\cup \Omega=\Omega $;&lt;/li&gt;
&lt;li&gt;$ A \cap A = A $ (Idempotência);&lt;/li&gt;
&lt;li&gt;$ A\varnothing=\varnothing $ (Elemento absorvente);&lt;/li&gt;
&lt;li&gt;$ A\cup \varnothing = A $;&lt;/li&gt;
&lt;li&gt;$ A - B = A - (A \cap B) = A \cap B^c $;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;\(B = (B \cap A) \cup (B \cap A^c)\)&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;\(B - A = B \cap A^c\)&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;\(A \cup B = A \cup (B \cap A^c)\)&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;\(A \cup B = (A^c \cap B)\cup (A \cap B) \cup (A \cap B^c)\)&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/br&gt;
&lt;/div&gt;
&lt;/br&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h1 id=&#34;questões&#34;&gt;Questões?&lt;/h1&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Dúvidas e Sugestões&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/#contact&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Contato&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Estatística e Probabilidade</title>
      <link>http://bendeivide.github.io/slides/profmat-est/s12/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/profmat-est/s12/</guid>
      <description>
&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap.png&#34;
  &gt;

&lt;h1 id=&#34;estatística-e-probabilidade&#34;&gt;Estatística e Probabilidade&lt;/h1&gt;
&lt;p&gt;Aula 12 - Probabilidades (Parte II)
&lt;/br&gt;&lt;/p&gt;
&lt;p&gt;
  &lt;i class=&#34;fas fa-user-tie  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;https://bendeivide.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Ben Dêivide&lt;/a&gt; | 
  &lt;i class=&#34;fas fa-school  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;https://www.ufsj.edu.br/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;UFSJ&lt;/a&gt;
&lt;/br&gt;

  &lt;i class=&#34;fas fa-book  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;http://bendeivide.github.io/courses/epaec/&#34;&gt;Estatística e Probabilidade&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;selo-dc&#34;&gt;Selo DC&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/dc/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/profmat-est/s12/SeloDC-preto_hu7eace1d7dbb403f37b46437825b208a2_37049_1f8e03062ff2fd4b85b7997b55db9e55.webp 400w,
               /slides/profmat-est/s12/SeloDC-preto_hu7eace1d7dbb403f37b46437825b208a2_37049_28a718b08e0f1b8193cec5ac4d8216a2.webp 760w,
               /slides/profmat-est/s12/SeloDC-preto_hu7eace1d7dbb403f37b46437825b208a2_37049_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/profmat-est/s12/SeloDC-preto_hu7eace1d7dbb403f37b46437825b208a2_37049_1f8e03062ff2fd4b85b7997b55db9e55.webp&#34;
               width=&#34;384&#34;
               height=&#34;406&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;motivação&#34;&gt;Motivação&lt;/h2&gt;
&lt;p&gt; Na &lt;a href=&#34;https://bendeivide.github.io/slides/estprob/s02/&#34; target=&#34;_blank&#34;&gt;Aula 02&lt;/a&gt; vimos como uma das motivações...&lt;/p&gt;














&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/profmat-est/s12/epaec_exerc5.19_huf42f90654072e146aede07d81ef72130_118873_d2eb6c328bbca59128eb008a44841e3c.webp 400w,
               /slides/profmat-est/s12/epaec_exerc5.19_huf42f90654072e146aede07d81ef72130_118873_2422affad744e4d2bee6a7971f41e9ec.webp 760w,
               /slides/profmat-est/s12/epaec_exerc5.19_huf42f90654072e146aede07d81ef72130_118873_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/profmat-est/s12/epaec_exerc5.19_huf42f90654072e146aede07d81ef72130_118873_d2eb6c328bbca59128eb008a44841e3c.webp&#34;
               width=&#34;830&#34;
               height=&#34;420&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;motivação-1&#34;&gt;Motivação&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Veremos que por meio de algumas &lt;strong&gt;propriedades da probabilidade&lt;/strong&gt;, poderemos chegar a algumas soluções para esse problema&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;definições-de-probabilidades&#34;&gt;Definições de probabilidades&lt;/h2&gt;
&lt;div id=&#34;&#34; class=&#34;exemplo&#34; cap=5 titulo=&#34;&#34;&gt;
&lt;p&gt;Lançar um dado equilibrado e observar o resultado obtido na face superior do dado.considerando que esse dado é equilibrado, e o evento $ A\subset \Omega $, então podemos calcular a chance de $ A $ ocorrer pela la medida de probabilidade, da seguinte forma:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;\begin{align*} P(A) &amp;amp; = \frac{\#A}{6} = \frac{\textrm{número de resultados favoráveis a A}}{\textrm{número de resultados possíveis}}. \end{align*}&lt;/code&gt;
&lt;/br&gt;&lt;/p&gt;
&lt;p class=&#34;fragment&#34;&gt; Essa é a conhecida a probabilidade clássica!&lt;/p&gt;
&lt;/div&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;evento-aleatório&#34;&gt;Evento aleatório&lt;/h2&gt;
&lt;div id=&#34;def:aleateventos&#34; class=&#34;definicao&#34; cap=5 titulo=&#34;(Evento aleatório)&#34;&gt;
&lt;p&gt; Todo evento de $ \Omega $ que podemos atribuir uma probabilidade, chamamos de evento aleatório. &lt;/p&gt;
&lt;/br&gt;
&lt;/div&gt;
&lt;/br&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;medida-de-probabilidade&#34;&gt;Medida de probabilidade&lt;/h2&gt;
&lt;div id=&#34;def:medprob&#34; class=&#34;definicao&#34; cap=5 titulo=&#34;(Medida de probabilidade)&#34;&gt;
&lt;p&gt;Seja $ \Omega $ o espaço amostral, então uma função $ P $, tal que $ P:\Omega \to \mathbb{R} $, é chamada de medida de probabilidade ou probabilidade, aos eventos do espaço amostral satisfazendo os seguintes axiomas de Kolmogorov:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;$ P(\Omega) = 1 $;&lt;/li&gt;
&lt;li&gt;$ 0\leq  P(A) \leq 1$, $ \forall \ A \subset \Omega $;&lt;/li&gt;
&lt;li&gt;$ P(A_1 \cup A_2) = P(A_1) + P(A_2)$, com $A_1 \cap A_2 = \emptyset $, para $ A_1, ~A_2 \subset \Omega $.&lt;/li&gt;
&lt;/ol&gt;
&lt;/br&gt;
&lt;/div&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;exemplo&#34;&gt;Exemplo&lt;/h2&gt;
&lt;div id=&#34;&#34; class=&#34;exemplo&#34; cap=5 titulo=&#34;&#34;&gt;
&lt;p&gt;Uma peça moldada de injeção é igualmente provável de ser obtida, a partir de qualquer  uma das oito cavidades de um molde.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Qual é o espaço amostral?&lt;/li&gt;
&lt;li&gt;Qual é a probabilidade de a peça ser proveniente da cavidade 1 ou 2?&lt;/li&gt;
&lt;li&gt;Qual é a probabilidade de a peça não ser proveniente nem da cavidade 3 nem da 4?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nesse caso, (a) o espaço amostral é $ \Omega = \{1, 2, 3, 4, 5, 6, 7, 8\} $. Como a peça moldada de injeção é igualmente provável, então (b) a probabilidade de a peça ser proveniente da cavidade 1 ou 2, é dada por:&lt;/p&gt;
\[\begin{aligned}
  P(\{1\} \cup \{2\}) &amp;amp; = P(\{1\}) + P(\{2\}), \quad \textrm{(Eventos disjuntos)}\\
                      &amp;amp; = 1 / 8 + 1 / 8\\
                      &amp;amp; = 2 / 8.
\end{aligned}\]
&lt;/div&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;exemplo-continuação&#34;&gt;Exemplo (continuação&amp;hellip;)&lt;/h2&gt;
&lt;div id=&#34;&#34; class=&#34;exemplo&#34; cap=5 titulo=&#34;&#34;&gt;
&lt;p&gt;Por fim, (c) a probabilidade de a peça não ser proveniente nem da cavidade 3 nem da 4, é dada por:&lt;/p&gt;
\[\begin{aligned}
  P(\{3\}^c \cap \{4\}^c) &amp;amp; = P[(\{3\} \cup \{4\})^c], \quad \textrm{(Lei DeMorgan)}\\
                          &amp;amp; = 1 - P(\{3\} \cup \{4\}), \quad \textrm{(Evento complementar)}\\
                          &amp;amp; = 1 - [P(\{3\}) + P( \{4\})], \quad \textrm{(Eventos disjuntos)}\\
                          &amp;amp; = 1 - [1 / 8 + 1 /8]\\
                          &amp;amp; = 1 - 2 /8\\
                          &amp;amp; = 6 / 8.
\end{aligned}\]
&lt;/div&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap2.png&#34;
  &gt;

&lt;h2 id=&#34;propriedades-da-medida-de-probabilidade&#34;&gt;Propriedades da medida de probabilidade&lt;/h2&gt;
&lt;div id=&#34;teo:propadicao&#34; class=&#34;teorema&#34; cap=5 titulo=&#34;(Regra da adição de probabilidades)&#34;&gt;
Considere um espaço amostral e dois eventos não vazios $ A $ e $ B $, então a probabilidade de ocorrência do evento $ A $ ou do evento $ B $ é igual a:
\[\begin{aligned}
P(A\cup B) &amp;amp;  = P(A)+P(B)-P(A\cap B).
\end{aligned}\]
Caso os eventos $ A $ e $ B $ sejam mutuamente exclusivos, isto é, $ P(A\cap B)=0 $, então:
\[\begin{aligned}
P(A\cup B) &amp;amp; = P(A)+P(B).
\end{aligned}\]
Essa regra pode ser estendida para $ n $ eventos mutuamente exclusivos:
$ A_1 $, $ A_2 $, $ \ldots $, $ A_n $, isto é,
\[\begin{aligned}
P(A_1\cup A_2\cup \ldots \cup A_n)= P(A_1)+P(A_2)+\ldots+P(A_n).
\end{aligned}\]
&lt;/br&gt;
&lt;/div&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;style&gt;
    ol.alphaList {list-style-type: lower-alpha;}
&lt;/style&gt;
&lt;h2 id=&#34;exemplo-1&#34;&gt;Exemplo&lt;/h2&gt;
&lt;div id=&#34;&#34; class=&#34;exemplo&#34; cap=5 titulo=&#34;&#34;&gt;
&lt;p&gt;
Uma empresa de eletricidade oferece uma taxa vitalícia de energia a qualquer lar cuja utilização de energia esteja abaixo de $ 240 $ kWh durante um determinado mês. Represente por $ A $ o evento de um lar selecionado aleatoriamente em um comunidade que não excede a utilização da taxa vitalícia em janeiro e por $ B $ o evento análogo para o mês de julho ($ A $ e $ B $ se referem ao mesmo lar). Suponha que $ P(A) = 0,8 $, $ P(B) = 0,7 $ e $ P(A \cup B) = 0,9 $. Calcule:
&lt;ol type=&#34;a&#34; class=&#34;alphaList&#34;&gt;
  &lt;li&gt;$ P(A \cap B) $;&lt;/li&gt;
  &lt;li&gt;A probabilidade de a quantia da taxa vitalícia ser excedida em exatamente um dos dois meses. Descreva esse evento em termos de $ A $ e $ B $. &lt;/li&gt;
&lt;/ol&gt;
Considere,
\[\begin{aligned}
  A &amp;amp; = \{\omega \in \Omega: \omega = \textrm{``lar X que não excede 240kWh em janeiro&#39;&#39;}\}, \\
  B &amp;amp; = \{\omega \in \Omega: \omega = \textrm{``lar X que não excede 240kWh em julho&#39;&#39;}\}.\\
\end{aligned}\]
Então, para o primeiro ítem (a), temos que:
\[\begin{aligned}
  P(A\cup B) &amp;amp; = P(A) + P(B) - P(A \cap B).
\end{aligned}\]
&lt;/p&gt;
&lt;/div&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;exemplo-continuação-1&#34;&gt;Exemplo (continuação&amp;hellip;)&lt;/h2&gt;
&lt;div id=&#34;&#34; class=&#34;exemplo&#34; cap=5 titulo=&#34;&#34;&gt;
&lt;p&gt;
Isso ocorre porque os eventos não são disjuntos, uma vez que os dois eventos consistem no mesmo &lt;i&gt;lar X&lt;/i&gt;, em ser selecionado. Assim, podemos obter $ P(A \cap B) $, dado por:
\[\begin{aligned}
  P(A\cap B) &amp;amp; = P(A) + P(B) - P(A \cup B) \\
             &amp;amp; =  0,8 + 0,7 - 0,9 \\
             &amp;amp; = 0,6.
\end{aligned}\]
No caso do ítem (b), o evento que representa o &lt;i&gt;lar X de a quantia vitalícia ser excedida em exatamente um dos dois meses&lt;/i&gt; por ser representado por: $ (A^c \cap B) \cup (A \cap B^c) $, uma vez que,&lt;/p&gt;
\[\begin{aligned}
  A^c  = \{\omega \in \Omega: \omega = \textrm{``lar X que exceder 240kWh em janeiro&#39;&#39;}\}, \\
  B^c  = \{\omega \in \Omega: \omega = \textrm{``lar X que exceder 240kWh em julho&#39;&#39;}\}.\\
\end{aligned}\]
&lt;p&gt;Podemos ainda observar que $ A \cup B = (A^c \cap B)\cup (A \cap B) \cup (A \cap B^c) $, e que cada um dos eventos dentro do parêntese são disjuntos dois a dois, logo,&lt;/p&gt;
\[\begin{aligned}
  P(A \cup B) &amp;amp; = P[(A^c \cap B)\cup (A \cap B) \cup (A \cap B^c)]\\
              &amp;amp; = P[(A^c \cap B) \cup (A \cap B^c)] + P(A \cap B).
\end{aligned}\]
&lt;/div&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;exemplo-continuação-&#34;&gt;Exemplo (continuação&amp;hellip; )&lt;/h2&gt;
&lt;div id=&#34;&#34; class=&#34;exemplo&#34; cap=5 titulo=&#34;&#34;&gt;
Desse modo, percebemos que $ P[(A^c \cap B) \cup (A \cap B^c)] = P(A \cup B) - P(A \cap B) $, logo,
\[\begin{aligned}
  P[(A^c \cap B) \cup (A \cap B^c)] &amp;amp; = 0,9 - 0,6 = 0,3.
\end{aligned}\]
&lt;/div&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap2.png&#34;
  &gt;

&lt;h2 id=&#34;probabilidade-de-um-evento-complementar&#34;&gt;Probabilidade de um evento complementar&lt;/h2&gt;
&lt;div id=&#34;teo:propcomplementar&#34; class=&#34;teorema&#34; cap=5 titulo=&#34;(Probabilidade de um evento complementar)&#34;&gt;
&lt;p&gt;
Considere um espaço amostral e o evento, não vazio, $ A $, então a probabilidade do evento complementar $ A^c $ ocorrer, é dado por:
\[\begin{aligned}
P(A^C)=1-P(A).
\end{aligned}\]
Essa situação é consequência da regra da adição para $ A\subset\Omega $, e substituindo $ B $ por $ A^C $, temos
\[\begin{aligned}
P(A\cup A^C) &amp;amp; = P(A)+P(A^C)-P(A\cap A^C),\\
P(\Omega)    &amp;amp; = P(A)+P(A^C)-0,\\
1            &amp;amp; = P(A)+P(A^C),
\end{aligned}\]
logo segue a expressão anterior.
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;exemplo-2&#34;&gt;Exemplo&lt;/h2&gt;
&lt;div id=&#34;&#34; class=&#34;exemplo&#34; cap=5 titulo=&#34;&#34;&gt;
Usando os resultados do Exemplo anterior, podemos calcular a probabilidade de $ A^c $, como:
\[\begin{aligned}
  P(A^c) &amp;amp = 1 - 0,8 = 0,2.
\end{aligned}\]
Isso representa a chance do &lt;i&gt;lar X&lt;/i&gt; exceder a energia acima de 240kWh, em janeiro.
&lt;/div&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap2.png&#34;
  &gt;

&lt;h2 id=&#34;probabilidade-condicional&#34;&gt;Probabilidade condicional&lt;/h2&gt;
&lt;div id=&#34;def:probcond&#34; class=&#34;definicao&#34; cap=5 titulo=&#34;(Probabilidade condicional)&#34;&gt;
&lt;p&gt;
Dados dois eventos $ A $ e $ B $ definidos em  $ \Omega $, então a probabilidade condicional do evento $ A $ dado que ocorreu o evento $ B $, denotado por $ P(A|B) $, é definida por:
\[\begin{aligned}
	P(A|B) = \frac{P(A \cap B)}{P(B)},
\end{aligned}\]
para $ P(B) &gt; 0 $.
&lt;/p&gt;
&lt;/br&gt;
&lt;/div&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;exemplo-motivação&#34;&gt;Exemplo (Motivação)&lt;/h2&gt;
&lt;div id=&#34;&#34; class=&#34;exemplo&#34; cap=5 titulo=&#34;&#34;&gt;
&lt;p&gt;Baseado no problema de Paulo, denotaremos os eventos:
&lt;ul&gt;
  &lt;li&gt;evento $ D $ as sandálias produzidas com defeitos pela empresa;&lt;/li&gt;
  &lt;li&gt;$ M_1 $ o evento que representa as sandálias produzidas pela máquina $ M_1 $;&lt;/li&gt;
  &lt;li&gt;$ M_2 $ o evento que representa as sandálias produzidas pela máquina $ M_2 $, e;&lt;/li&gt;
  &lt;li&gt;$ M_3 $ o evento que representa as sandálias produzidas pela máquina $ M_3 $.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Desse modo podemos representar, a probabilidade desses defeitos da seguinte forma: $ P(D|M_1) = 0,01 $, $ P(D|M_2) = 0,02 $, e $ P(D|M_3) = 0,03 $. Assim, percebemos que a probabilidade do evento $ D $ não pode ser observada facilmente, pois o defeito dos produtos produzidos pelas máquinas está condicionado a cada máquina.&lt;/p&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;aside class=&#34;notes&#34;&gt;
📝 Enfatizar:
&lt;ul&gt;
&lt;li&gt;Essas probabilidades apresentam uma alteração no espaço amostral para cada evento, porque esses resultados mostram a chance de defeito do produto, dado o conhecimento de que máquina foi produzido, é o que chamamos de restrição do espaço amostral.&lt;/li&gt;
&lt;li&gt;$ P(A|B) $ é uma medida de probabilidade?&lt;/li&gt;
&lt;/ul&gt;
&lt;/aside&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap2.png&#34;
  &gt;

&lt;h2 id=&#34;regra-do-produto-de-probabilidade&#34;&gt;Regra do produto de probabilidade&lt;/h2&gt;
&lt;div id=&#34;teo:regprodprob&#34; class=&#34;teorema&#34; cap=5 titulo=&#34;(Regra do produto de probabilidade)&#34;&gt;
&lt;p&gt;
Seja os eventos não vazios $ A_1,A_2,\ldots,A_n $ em $ \Omega $, com $ P(\bigcap^{n}_{i=1}A_i)&gt;0 $, então a probabilidade do produto desses eventos é dado por
$$ P(A_1\cap A_2\cap \ldots \cap A_n)=P(A_1)P(A_2|A_1)\ldots P(A_n|A_1\cap A_2 \cap \ldots \cap A_{n-1}). $$
&lt;/p&gt;
&lt;/div&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap2.png&#34;
  &gt;

&lt;h2 id=&#34;partição-de--omega-&#34;&gt;Partição de $ \Omega $&lt;/h2&gt;
&lt;div id=&#34;def:partomega&#34; class=&#34;definicao&#34; cap=5 titulo=&#34;(Partição do espaço amostral)&#34;&gt;
&lt;p&gt;
Se a sequência $ A_1, A_2, \ldots, $ são disjuntos dois a dois, não vazios, e $ \bigcup^{\infty}_{i=1}A_i=\Omega $, então dizemos que essa sequência forma uma partição de $ \Omega $.
&lt;/p&gt;
&lt;/br&gt;
&lt;/div&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;teorema-da-probabilidade-total&#34;&gt;Teorema da probabilidade total&lt;/h2&gt;
&lt;div id=&#34;teo:probtotal&#34; class=&#34;teorema&#34; cap=5 titulo=&#34;(Teorema da probabilidade total)&#34;&gt;
&lt;p&gt;
Seja uma sequência de eventos $ A_1, A_2, \ldots, A_n $ de $ \Omega $, disjuntos, tal que $ \bigcup^{n}_{i = 1}A_i = \Omega $, e $ B $ um evento de $ \Omega $, não vazio, então a probabilidade de $ B $ é dada por:
\[\begin{aligned}
	P(B) = \sum_{i = 1}^{n}P(B|A_i)P(A_i),
\end{aligned}\]
para $ P(A_i) &gt; 0 $, sendo $ i = 1, 2, \ldots, n $.
&lt;/p&gt;
&lt;/div&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;exemplo-motivação-1&#34;&gt;Exemplo (Motivação)&lt;/h2&gt;
&lt;div id=&#34;&#34; class=&#34;exemplo&#34; cap=5 titulo=&#34;&#34;&gt;
&lt;p&gt;Voltando ao problema de Paulo, como $ P(M_1) = 0,50 $, $ P(M_2) = 0,40) $ e $ P(M_3) = 0,10 $, então a probabilidade de uma sandália ter defeito é
\[\begin{aligned}
	P(D) = &amp; \sum_{i = 1}^{3}P(D|M_i)P(M_i)\\
	= &amp; P(D|M_1)P(M_1) + P(D|M_2)P(M_2) + P(D|M_3)P(M_3)\\
	= &amp; 0,01 \times 0,50 + 0,02 \times 0,40 + 0,03 \times 0,10\\
	= &amp; 0,016.
\end{aligned}\]
&lt;/p&gt;
&lt;/div&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap2.png&#34;
  &gt;

&lt;h2 id=&#34;independência-de-dois-eventos&#34;&gt;Independência de dois eventos&lt;/h2&gt;
&lt;div id=&#34;def:partomega&#34; class=&#34;definicao&#34; cap=5 titulo=&#34;(Independência de dois eventos)&#34;&gt;
&lt;p&gt;
Considere o espaço amostral $ \Omega $. Dois eventos $ A $ e $ B $ de $ \Omega $ são independentes se satisfaz ao menos uma das seguintes condições:
&lt;ol type=&#34;a&#34; class=&#34;alphaList&#34;&gt;
  &lt;li&gt;$ P(A \cap B) = P(A)P(B) $;&lt;/li&gt;
  &lt;li&gt;$ P(A|B) = P(A) $, para $ P(B) &gt; 0 $; &lt;/li&gt;
  &lt;li&gt;$ P(B|A) = P(B) $, para $ P(A) &gt; 0 $. &lt;/li&gt;
&lt;/ol&gt;
&lt;/p&gt;
&lt;/br&gt;
&lt;/div&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;continuação&#34;&gt;continuação&amp;hellip;&lt;/h2&gt;
&lt;div id=&#34;&#34; class=&#34;exemplo&#34; cap=5 titulo=&#34;&#34;&gt;
É fácil mostrar que (I) implica em (II), (II) implica em (III), e (III) implica em (I).
&lt;ul&gt;
&lt;li&gt;$ (i) \to (ii) $: Se $ P(AB) = P(A)P(B) $, então:&lt;/li&gt;
&lt;/ul&gt;
$$ P(A|B) = \frac{P(AB)}{P(A)} = \frac{P(A)P(B)}{P(B)} = P(A), \quad \textrm{para } P(B) &gt; 0; $$
&lt;ul&gt;
&lt;li&gt;$ (ii) \to (iii) $: Se $ P(A|B) = P(A) $, então:&lt;/li&gt;
&lt;/ul&gt;
$$  P(B|A) = \frac{P(BA)}{P(A)} = \frac{P(A|B)P(B)}{P(A)} = P(B), \quad \textrm{para } P(A) &gt; 0; $$
&lt;ul&gt;
&lt;li&gt;$ (iii) \to (i) $: Se $ P(B|A) = P(B) $, então:&lt;/li&gt;
&lt;/ul&gt;
$$ P(AB) = P(B|A)P(A) = P(B)P(A), \textrm{para } P(A) &gt; 0. $$
&lt;/div&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;continuação-1&#34;&gt;continuação&amp;hellip;&lt;/h2&gt;
&lt;div id=&#34;&#34; class=&#34;exemplo&#34; cap=5 titulo=&#34;&#34;&gt;
A intuição para independência fica justificada pelo fato de que $ A $ é independente de $ B $ tanto na ocorrência quanto a não ocorrência de $ B $ e isso não muda em nada a probabilidade da ocorrência de $ A $, isto é, $ P(A|B) = P(A) $ e  $ P(A|B^c) = P( A) $. Essas duas expressões significam que
\[\begin{aligned}
  P(A\cap B) &amp; = P(B)P(A|B) = P(B)P(A)\\
  P(A\cap B^c) &amp; = P(B^c)P(A|B^c) = P(B^c)P(A).
\end{aligned}\]
&lt;/div&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;teorema-de-independência-de-dois-eventos&#34;&gt;Teorema de independência de dois eventos&lt;/h2&gt;
&lt;div id=&#34;teo:probtotal&#34; class=&#34;teorema&#34; cap=5 titulo=&#34;(Teorema de independência de dois eventos)&#34;&gt;
&lt;p&gt;Se A e B são eventos independentes, não vazio, definidos em $ \Omega $, então&lt;/p&gt;
&lt;ul &gt;
  &lt;li&gt;$ A $ e $ B^c $ também são independentes;&lt;/li&gt;
  &lt;li&gt;$ A^c $ e $ B $ também são independentes; &lt;/li&gt;
  &lt;li&gt;$ A^c $ e $ B^c $ também são independentes. &lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;exemplo-3&#34;&gt;Exemplo&lt;/h2&gt;
&lt;div id=&#34;&#34; class=&#34;exemplo&#34; cap=5 titulo=&#34;&#34;&gt;
Sejam os resultados possíveis de um dado honesto, cujo espaço amostral é $ \Omega = \{1, 2, 3, 4, 5, 6\} $. Considere um evento que representa o conjunto dos números ímpares desse espaço amostral, $ A = \{1, 3, 5\} $, e outro evento que consite nos múltiplos de 3, $ B = \{3, 6\} $. A probabilidade de $ A $ é $ P(A) = 1/2 $, a probabilidade de B é $ P(B) = 1/3 $, e a probabilidade da interseção entre A e B é $ P(A \cap B) = 1/6 $. Veja que dado que o evento B ocorra, ou não ocorra $ B^c = \{1, 2, 4, 5\} $, a probabilidade do evento A é a mesma, veja:
&lt;p&gt;&lt;code&gt;\begin{align*} P(A|B) &amp;amp; = \frac{1/6}{1/3} = 1/2\\ P(A|B^c) &amp;amp; = \frac{2/6}{4/6} = 1/2. \end{align*}&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Que é o mesmo que entender que $ P(A) \times P(B) = 1/6 = P(A\cap B) $. Logo, $ A $ e $ B $ são eventos independentes.&lt;/p&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;exemplo-4&#34;&gt;Exemplo&lt;/h2&gt;
&lt;div id=&#34;&#34; class=&#34;exemplo&#34; cap=5 titulo=&#34;&#34;&gt;
Seja um experimento cujo objetivo é verificar a face superior de um tetraedro, isto é, $ \Omega = \{1, 2, 3, 4\} $. Sejam os eventos em $ \Omega $, $ A = \{1, 4\} $, $ B = \{2, 4\} $ e $ C = \{3, 4\} $. Considerando o tetraedro honesto e que cada valor é equiprovável, assim $ P(A) = P(B) = P(C) = 1/2 $. Observamos que estes eventos são independentes dois a dois, isto é, $ P(A\cap B) = 1/4 = P(A)P(B) $, $ P(A\cap C) = 1/4 = P(A)P(C) $ e $ P(B\cap C) = 1/4 = P(B)P(C) $. Porém, $ P(A\cap B \cap C) = 1/4 \neq P(A) P(B) P(C) $. Logo, os eventos A, B e C não são independentes três a três.
&lt;/div&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;independência-de-uma-sequência-de-eventos&#34;&gt;Independência de uma sequência de eventos&lt;/h2&gt;
&lt;div id=&#34;def:indseqeventos&#34; class=&#34;definicao&#34; cap=5 titulo=&#34;(Independência de uma sequência de eventos)&#34;&gt;
&lt;p&gt;Considere o espaço amostral $ \Omega $. Uma sequência de eventos $ A_1, A_2, \ldots, A_n $ de $ \Omega $ são independentes se e somente se:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;\begin{align*} P(A_i \cap A_j) &amp;amp; = P(A_i)P(A_j), \quad \textrm{para } i \neq j; \\ P(A_i \cap A_j \cap A_k) &amp;amp; = P(A_i)P(A_j)P(A_k), \quad \textrm{para } i \neq j \neq k; \\ \vdots &amp;amp;  \nonumber\\ P(\cap_{i = 1}^{n} A_i) &amp;amp; = \prod_{i = 1}^{n}P(A_i). \end{align*}&lt;/code&gt;
&lt;/br&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;exemplo-motivação-2&#34;&gt;Exemplo (Motivação)&lt;/h2&gt;
&lt;div id=&#34;&#34; class=&#34;exemplo&#34; cap=5 titulo=&#34;&#34;&gt;
Paulo poderia indagar, se os eventos $ M_i $ e $ D $ são independentes ou dependentes. Contudo, pela Definição de independência, temos que
&lt;p&gt;&lt;code&gt;\begin{align*} P(D|M_i) &amp;amp; \neq P(D) = 0,016 \Rightarrow D \textrm{ e } M_i \textrm{, para } i = 1, 2, 3, \end{align*}&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;logo, não são independentes.&lt;/p&gt;
&lt;/div&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;teorema-de-bayes&#34;&gt;Teorema de Bayes&lt;/h2&gt;
&lt;div id=&#34;teo:teobayes&#34; class=&#34;teorema&#34; cap=5 titulo=&#34;(Teorema de Bayes)&#34;&gt;
Considere o espaço amostral $ \Omega $. Considere uma sequência de eventos $ A_1, A_2, \ldots, A_n $ de $ \Omega $, disjuntos, tal que $ \bigcup^{n}_{i = 1}A_i = \Omega $, e $ B $ um evento de $ \Omega $, então a probabilidade de $ A_k $, para $ k = 1, 2, \ldots, n $, dado que ocorreu o evento $ B $,  denotado por $ P(A_k|B) $, é dado por:
&lt;p&gt;&lt;code&gt;\begin{aligned} P(A_k|B) = \frac{P(B|A_k)P(A_k)}{\sum_{i = 1}^{n}P(B|A_i)P(A_i)}, \qquad k = 1, 2, \ldots, n, \end{aligned}&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;para $ P(A_k) &amp;gt; 0 $ e $ P(A_i) &amp;gt; 0 $, sendo $ i = 1, 2, \ldots, n $.&lt;/p&gt;
&lt;/div&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;exemplo-motivação-3&#34;&gt;Exemplo (Motivação)&lt;/h2&gt;
&lt;div id=&#34;&#34; class=&#34;exemplo&#34; cap=5 titulo=&#34;&#34;&gt;
Com esse resultado, Paulo agora pode tomar uma decisão mais plausível, isto é, dado um defeito numa determinada sandália produzida na fábrica, qual a probabilidade desta ter sido produzida em cada uma das máquinas?
&lt;p&gt;&lt;code&gt;\begin{aligned} P(M_1|D) = \frac{0,01 \times 0,50}{0,016} = 0,3125\\ P(M_2|D) = \frac{0,02 \times 0,40}{0,016} = 0,5000\\ P(M_3|D) = \frac{0,03 \times 0,10}{0,016} = 0,1875\\ \end{aligned}&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;A tomada de decisão será substituir a máquina $ M_2 $. Poderíamos ter tomado uma decisão equivocada se não fosse o teorema de Bayes.&lt;/p&gt;
&lt;/div&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h1 id=&#34;questões&#34;&gt;Questões?&lt;/h1&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Dúvidas e Sugestões&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/#contact&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Contato&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Estatística e Probabilidade</title>
      <link>http://bendeivide.github.io/slides/profmat-est/s14/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/profmat-est/s14/</guid>
      <description>
&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap.png&#34;
  &gt;

&lt;h1 id=&#34;estatística-e-probabilidade&#34;&gt;Estatística e Probabilidade&lt;/h1&gt;
&lt;p&gt;Aula 14 - Variáveis aleatórias e Distribuições de probabilidades discretas
&lt;/br&gt;&lt;/p&gt;
&lt;p&gt;
  &lt;i class=&#34;fas fa-user-tie  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;https://bendeivide.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Ben Dêivide&lt;/a&gt; | 
  &lt;i class=&#34;fas fa-school  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;https://www.ufsj.edu.br/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;UFSJ&lt;/a&gt;
&lt;/br&gt;

  &lt;i class=&#34;fas fa-book  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;http://bendeivide.github.io/courses/epaec/&#34;&gt;Estatística e Probabilidade&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;selo-dc&#34;&gt;Selo DC&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/dc/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/profmat-est/s14/SeloDC-preto_hu7eace1d7dbb403f37b46437825b208a2_37049_1f8e03062ff2fd4b85b7997b55db9e55.webp 400w,
               /slides/profmat-est/s14/SeloDC-preto_hu7eace1d7dbb403f37b46437825b208a2_37049_28a718b08e0f1b8193cec5ac4d8216a2.webp 760w,
               /slides/profmat-est/s14/SeloDC-preto_hu7eace1d7dbb403f37b46437825b208a2_37049_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/profmat-est/s14/SeloDC-preto_hu7eace1d7dbb403f37b46437825b208a2_37049_1f8e03062ff2fd4b85b7997b55db9e55.webp&#34;
               width=&#34;384&#34;
               height=&#34;406&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;motivação&#34;&gt;Motivação&lt;/h2&gt;
&lt;div id=&#34;&#34; class=&#34;exemplo&#34; cap=5 titulo=&#34;&#34;&gt;
Para explicar a definição de uma variável aleatória será considerado o exemplo, no qual duas variedades de uma espécie $ A $ ( $ A_1 $, $ A_2 $ ) e três de outra espécie $ E $ ( $ E_1 $, $ E_2 $ e $ E_3 $ ) são disponibilizados para uma pesquisa. Uma amostra de duas variedades ($ n=2 $) é extraída. O espaço amostral dos resultados desse experimento, segue,
&lt;p&gt;&lt;code&gt;\begin{aligned} \Omega =  \{(A_1,A_2), (A_1,E_1), (A_1,E_2), (A_1,E_3), (A_2,E_1), (A_2,E_2), (A_2,E_3), (E_1,E_2),  (E_1,E_3), (E_2,E_3) \} \end{aligned}&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;experimento-1&#34;&gt;Experimento 1&lt;/h2&gt;
&lt;div class=&#34;r-stack&#34;&gt;
  &lt;img class=&#34;fragment fade-in-then-out&#34; src=&#34;binom1.png&#34; data-fragment-index=&#34;1&#34; width=&#34;650&#34; height=&#34;500&#34;&gt;
  &lt;img class=&#34;fragment fade-in-then-out&#34; src=&#34;binom2.png&#34; data-fragment-index=&#34;2&#34; width=&#34;650&#34; height=&#34;500&#34;&gt;
  &lt;img class=&#34;fragment fade-in-then-out&#34; src=&#34;binom3.png&#34;  data-fragment-index=&#34;3&#34; width=&#34;650&#34; height=&#34;500&#34;&gt;
  &lt;img class=&#34;fragment fade-in-then-out&#34; src=&#34;binom4.png&#34; data-fragment-index=&#34;4&#34; width=&#34;650&#34; height=&#34;500&#34;&gt;
  &lt;img class=&#34;fragment fade-in-then-out&#34; src=&#34;binom5.png&#34; data-fragment-index=&#34;5&#34; width=&#34;650&#34; height=&#34;500&#34;&gt;
  &lt;img class=&#34;fragment fade-in-then-out&#34; src=&#34;binom6.png&#34;  data-fragment-index=&#34;6&#34; width=&#34;650&#34; height=&#34;500&#34;&gt;
  &lt;img class=&#34;fragment fade-in-then-out&#34; src=&#34;binom7.png&#34; data-fragment-index=&#34;7&#34; width=&#34;650&#34; height=&#34;500&#34;&gt;
  &lt;img class=&#34;fragment fade-in-then-out&#34; src=&#34;binom8.png&#34; data-fragment-index=&#34;8&#34; width=&#34;650&#34; height=&#34;500&#34;&gt;
  &lt;img class=&#34;fragment fade-in-then-out&#34; src=&#34;binom9.png&#34; data-fragment-index=&#34;9&#34; width=&#34;650&#34; height=&#34;500&#34;&gt;
  &lt;img class=&#34;fragment fade-in-then-out&#34; src=&#34;binom10.png&#34; data-fragment-index=&#34;10&#34; width=&#34;650&#34; height=&#34;500&#34;&gt;
  &lt;img class=&#34;fragment fade-in-then-out&#34; src=&#34;binom11.png&#34; data-fragment-index=&#34;11&#34; width=&#34;650&#34; height=&#34;500&#34;&gt;
  &lt;img class=&#34;fragment fade-in-then-out&#34; src=&#34;binom12.png&#34; data-fragment-index=&#34;12&#34; width=&#34;650&#34; height=&#34;500&#34;&gt;
  &lt;img class=&#34;fragment fade-in-then-out&#34; src=&#34;binom13.png&#34; data-fragment-index=&#34;13&#34; width=&#34;650&#34; height=&#34;500&#34;&gt;
  &lt;img class=&#34;fragment fade-in-then-out&#34; src=&#34;binom14.png&#34; data-fragment-index=&#34;14&#34; width=&#34;650&#34; height=&#34;500&#34;&gt;
  &lt;img class=&#34;fragment fade-in-then-out&#34; src=&#34;binom15.png&#34; data-fragment-index=&#34;15&#34; width=&#34;650&#34; height=&#34;500&#34;&gt;
  &lt;img class=&#34;fragment fade-in-then-out&#34; src=&#34;binom16.png&#34;  data-fragment-index=&#34;16&#34; width=&#34;650&#34; height=&#34;500&#34;&gt;
  &lt;img class=&#34;fragment current-visible&#34; src=&#34;binom17.png&#34; data-fragment-index=&#34;17&#34; width=&#34;650&#34; height=&#34;500&#34;&gt;
  &lt;img class=&#34;fragment&#34; src=&#34;binom18.png&#34; width=&#34;650&#34; height=&#34;500&#34;&gt;
&lt;/div&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h1 id=&#34;questões&#34;&gt;Questões?&lt;/h1&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Dúvidas e Sugestões&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/#contact&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Contato&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Lançamento do livro R básico</title>
      <link>http://bendeivide.github.io/slides/lancamentorbasico/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/lancamentorbasico/</guid>
      <description>
&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;hardcover.png&#34;
  &gt;

&lt;h1 id=&#34;r-básico&#34;&gt;R Básico&lt;/h1&gt;
&lt;p&gt;
  &lt;i class=&#34;fas fa-user-tie  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;https://bendeivide.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Ben Dêivide&lt;/a&gt; | 
  &lt;i class=&#34;fas fa-user-tie  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;https://digoarthur.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Diego Arthur&lt;/a&gt;&lt;br&gt;

  &lt;i class=&#34;fas fa-school  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;https://www.ufsj.edu.br/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;UFSJ&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;hardcover.png&#34;
  &gt;

&lt;section&gt;
&lt;h2&gt;Como foi o início?&lt;/h2&gt;
&lt;ul&gt;
&lt;li class=&#34;fragment&#34; data-fragment-index=&#34;1&#34;&gt;
&lt;p&gt;Pandemia (2020-2021)&lt;/p&gt;
&lt;/li&gt;
&lt;li class=&#34;fragment&#34; data-fragment-index=&#34;2&#34;&gt;
&lt;p&gt;Catel/UFSJ&lt;/p&gt;
&lt;/li&gt;
&lt;li class=&#34;fragment&#34; data-fragment-index=&#34;3&#34;&gt;
&lt;p&gt;Cursos sobre a &lt;a href=&#34;https://bendeivide.github.io/cursor/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;linguagem R&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li class=&#34;fragment&#34; data-fragment-index=&#34;4&#34;&gt;
&lt;p&gt;Parceria com &lt;a href=&#34;https://digoarthur.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Diego&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li class=&#34;fragment&#34; data-fragment-index=&#34;5&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/project/projape/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Projeto aprender por ensinar (PAPE)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;hardcover.png&#34;
  &gt;

&lt;h2 id=&#34;coleção-ear&#34;&gt;Coleção EAR&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;R básico (Volume I) ✔&lt;/li&gt;
&lt;li&gt;R intermediário (Volume II)&lt;/li&gt;
&lt;li&gt;R avançado (Volume III)&lt;/li&gt;
&lt;li&gt;Documentações em R (Volume IV)&lt;/li&gt;
&lt;li&gt;Desenvolvimento de pacotes R (Volume V)&lt;/li&gt;
&lt;li&gt;Gráficos (Volume VI)&lt;/li&gt;
&lt;li&gt;Banco de dados (Volume VII)&lt;/li&gt;
&lt;li&gt;IGU (Volume VIII)&lt;/li&gt;
&lt;li&gt;POO no R (Volume IX)&lt;/li&gt;
&lt;li&gt;Funções do pacote &lt;code&gt;base&lt;/code&gt; (Volume X)&lt;/li&gt;
&lt;li&gt;&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;hardcover.png&#34;
  &gt;

&lt;section&gt;
&lt;h2&gt;Agradecimentos &lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Rodrigo Ronchi Rossi Costa (UFSJ)&lt;/li&gt;
&lt;li&gt;Fernando Augusto Teixeira (UFSJ)&lt;/li&gt;
&lt;li&gt;Sérgio de Oliveira (UFSJ)&lt;/li&gt;
&lt;li&gt;Jose Eloy Ottoni (UFSJ)&lt;/li&gt;
&lt;li&gt;Daniel Furtado Ferreira (UFLA)&lt;/li&gt;
&lt;li&gt;Janilson Pinheiro de Assis (UFERSA)&lt;/li&gt;
&lt;li&gt;Wesley de Oliveira Santos (UFERSA)&lt;/li&gt;
&lt;li&gt;Allanna Darlene  Vilaça (UNIFACVEST)&lt;/li&gt;
&lt;li&gt;Tiago Olivoto (UFSC)&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Agradecimentos &lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Felipe Andrade  Velozo (UNIFAL)&lt;/li&gt;
&lt;li&gt;Julio Cezar Gonçalves de Freitas (UFPA)&lt;/li&gt;
&lt;li&gt;Regina Albanese Pose (USCS)&lt;/li&gt;
&lt;li&gt;Dulcídia Carlos Guezimane Ernesto (UFLA)&lt;/li&gt;
&lt;li&gt;José Edimar Vieira Costa Júnior (UFLA)&lt;/li&gt;
&lt;li&gt;André da Silva Pereira (UPF)&lt;/li&gt;
&lt;li&gt;Miguel Angel Acosta Chinchilla (&lt;em&gt;Alliance Bioversity&lt;/em&gt; - CIAT)&lt;/li&gt;
&lt;li&gt;Daniel Vicente Batista (Univesp)&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;hardcover.png&#34;
  &gt;

&lt;h2 id=&#34;curiosidades-do-r-básico&#34;&gt;Curiosidades do R básico&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Tempo: 1 ano&lt;/li&gt;
&lt;li&gt;Escrito em &lt;code&gt;\(\LaTeX\)&lt;/code&gt; (PDF)
&lt;ul&gt;
&lt;li&gt;classe &lt;em&gt;memoir&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Escrito com o pacote &lt;a href=&#34;https://bookdown.org/yihui/bookdown/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;bookdown&lt;/a&gt; (Versão em HTML)
&lt;ul&gt;
&lt;li&gt;Ultrapassou as 2500 linhas de comando&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;124 exercícios propostos&lt;/li&gt;
&lt;li&gt;$&amp;gt;$120 Códigos R numerados, sem contabilizar os não numerados&lt;/li&gt;
&lt;li&gt;339 páginas e 321 numeradas&lt;/li&gt;
&lt;li&gt;Publicado em 28/08/2022&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;hardcover.png&#34;
  &gt;

&lt;section&gt;
&lt;h2&gt;Estrutura do R básico&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Objetivo: Sintaxe e semântica do R (Introdutório)&lt;/li&gt;
&lt;li&gt;11 capítulos
&lt;ul&gt;
&lt;li&gt;Capítulo 1: Entendendo a coleção EAR&lt;/li&gt;
&lt;li&gt;Capítulo 2: História e instalação do R&lt;/li&gt;
&lt;li&gt;Capítulo 3: Como o R trabalha&lt;/li&gt;
&lt;li&gt;Capítulo 4: Objetos e estruturas de dados&lt;/li&gt;
&lt;li&gt;Capítulo 5: Importação e exportação de dados&lt;/li&gt;
&lt;li&gt;Capítulo 6: Funções no R&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Estrutura do R básico&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;11 capítulos
&lt;ul&gt;
&lt;li&gt;Capítulo 7: Boas práticas de como escrever um código&lt;/li&gt;
&lt;li&gt;Capítulo 8: Pacotes&lt;/li&gt;
&lt;li&gt;Capítulo 9: Ambientes e caminho de busca&lt;/li&gt;
&lt;li&gt;Capítulo 10: Interfaces com outras linguagens&lt;/li&gt;
&lt;li&gt;Capítulo 11: Considerações e preparação para o Volume II&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Capa/lateral/fundo&lt;/h2&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/lancamentorbasico/cover-back-front_hu3ce330fa360ba6e4db62da5bce0917e8_4645749_00da4cf45303c5812d852b1a6a7f785f.webp 400w,
               /slides/lancamentorbasico/cover-back-front_hu3ce330fa360ba6e4db62da5bce0917e8_4645749_2d3c75e90137881f78d6463e7dd9815d.webp 760w,
               /slides/lancamentorbasico/cover-back-front_hu3ce330fa360ba6e4db62da5bce0917e8_4645749_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/lancamentorbasico/cover-back-front_hu3ce330fa360ba6e4db62da5bce0917e8_4645749_00da4cf45303c5812d852b1a6a7f785f.webp&#34;
               width=&#34;760&#34;
               height=&#34;521&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;/section&gt;
&lt;hr&gt;
&lt;section data-background-iframe=&#34;/books/eambr01&#34; data-background-interactive&gt;
	&lt;div style=&#34;position: absolute; width: 40%; right: 0; box-shadow: 0 1px 4px rgba(0,0,0,0.5), 0 5px 25px rgba(0,0,0,0.2); background-color: rgba(0, 0, 0, 0.9); color: #fff; padding: 20px; font-size: 20px; text-align: left;&#34;&gt;
		&lt;h2&gt;Página do livro R básico&lt;/h2&gt;
		&lt;p&gt;Todo o material do livro está disponível na página: &lt;a href=&#34;https://bendeivide.github.io/books/eambr01/&#34;&gt;https://bendeivide.github.io/books/eambr01/&lt;/a&gt;.&lt;/p&gt;
	&lt;/div&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;hardcover.png&#34;
  &gt;

&lt;h2 id=&#34;filosofia-de-publicação-selo-dc&#34;&gt;Filosofia de publicação (Selo DC)&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/dc/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/lancamentorbasico/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_57f4d021c573f1cdb22f5303fccfacd9.webp 400w,
               /slides/lancamentorbasico/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_e3124639f3c96b16d12396d9954194c3.webp 760w,
               /slides/lancamentorbasico/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/lancamentorbasico/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_57f4d021c573f1cdb22f5303fccfacd9.webp&#34;
               width=&#34;385&#34;
               height=&#34;406&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;hardcover.png&#34;
  &gt;

&lt;h2 id=&#34;mais-sobre-o-r-básico&#34;&gt;Mais sobre o R básico&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/books/eambr01/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Página do R básico&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;hardcover.png&#34;
  &gt;

&lt;h1 id=&#34;obrigado&#34;&gt;Obrigado!&lt;/h1&gt;
&lt;p&gt;Sugestões, perguntas, críticas&amp;hellip;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Lançamento do livro R básico (UNIFAL/MG)</title>
      <link>http://bendeivide.github.io/slides/lancamentorbasico-unifal/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/lancamentorbasico-unifal/</guid>
      <description>
&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;hardcover.png&#34;
  &gt;

&lt;h1 id=&#34;r-básico&#34;&gt;R Básico&lt;/h1&gt;
&lt;p&gt;
  &lt;i class=&#34;fas fa-user-tie  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;https://bendeivide.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Ben Dêivide&lt;/a&gt; |

  &lt;i class=&#34;fas fa-school  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;https://www.ufsj.edu.br/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;UFSJ&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;hardcover.png&#34;
  &gt;

&lt;section&gt;
&lt;h2&gt;Como foi o início?&lt;/h2&gt;
&lt;ul&gt;
&lt;li class=&#34;fragment&#34; data-fragment-index=&#34;1&#34;&gt;
&lt;p&gt;Pandemia (2020-2021)&lt;/p&gt;
&lt;/li&gt;
&lt;li class=&#34;fragment&#34; data-fragment-index=&#34;2&#34;&gt;
&lt;p&gt;Catel/UFSJ&lt;/p&gt;
&lt;/li&gt;
&lt;li class=&#34;fragment&#34; data-fragment-index=&#34;3&#34;&gt;
&lt;p&gt;Cursos sobre a &lt;a href=&#34;https://bendeivide.github.io/cursor/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;linguagem R&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li class=&#34;fragment&#34; data-fragment-index=&#34;4&#34;&gt;
&lt;p&gt;Parceria com &lt;a href=&#34;https://digoarthur.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Diego&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li class=&#34;fragment&#34; data-fragment-index=&#34;5&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/project/projape/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Projeto aprender por ensinar (PAPE)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;hardcover.png&#34;
  &gt;

&lt;h2 id=&#34;coleção-ear&#34;&gt;Coleção EAR&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;R básico (Volume I) ✔&lt;/li&gt;
&lt;li&gt;R intermediário (Volume II)&lt;/li&gt;
&lt;li&gt;R avançado (Volume III)&lt;/li&gt;
&lt;li&gt;Documentações em R (Volume IV)&lt;/li&gt;
&lt;li&gt;Desenvolvimento de pacotes R (Volume V)&lt;/li&gt;
&lt;li&gt;Gráficos (Volume VI)&lt;/li&gt;
&lt;li&gt;Banco de dados (Volume VII)&lt;/li&gt;
&lt;li&gt;IGU (Volume VIII)&lt;/li&gt;
&lt;li&gt;POO no R (Volume IX)&lt;/li&gt;
&lt;li&gt;Funções do pacote &lt;code&gt;base&lt;/code&gt; (Volume X)&lt;/li&gt;
&lt;li&gt;&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- --- --&gt;
&lt;!-- 
&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;hardcover.png&#34;
  &gt;
 --&gt;
&lt;!-- &lt;section&gt; --&gt;
&lt;!-- &lt;h2&gt;Agradecimentos &lt;/h2&gt; --&gt;
&lt;!--   - Rodrigo Ronchi Rossi Costa (UFSJ) --&gt;
&lt;!--   - Fernando Augusto Teixeira (UFSJ)  --&gt;
&lt;!--   - Sérgio de Oliveira (UFSJ) --&gt;
&lt;!--   - Jose Eloy Ottoni (UFSJ) --&gt;
&lt;!--   - Daniel Furtado Ferreira (UFLA) --&gt;
&lt;!--   - Janilson Pinheiro de Assis (UFERSA) --&gt;
&lt;!--   - Wesley de Oliveira Santos (UFERSA) --&gt;
&lt;!--   - Allanna Darlene  Vilaça (UNIFACVEST) --&gt;
&lt;!--   - Tiago Olivoto (UFSC) --&gt;
&lt;!-- &lt;/section&gt; --&gt;
&lt;!-- &lt;section&gt; --&gt;
&lt;!-- &lt;h2&gt;Agradecimentos &lt;/h2&gt; --&gt;
&lt;!--   - Felipe Andrade  Velozo (UNIFAL) --&gt;
&lt;!--   - Julio Cezar Gonçalves de Freitas (UFPA) --&gt;
&lt;!--   - Regina Albanese Pose (USCS) --&gt;
&lt;!--   - Dulcídia Carlos Guezimane Ernesto (UFLA) --&gt;
&lt;!--   - José Edimar Vieira Costa Júnior (UFLA) --&gt;
&lt;!--   - André da Silva Pereira (UPF) --&gt;
&lt;!--   - Miguel Angel Acosta Chinchilla (*Alliance Bioversity* - CIAT)  --&gt;
&lt;!--   - Daniel Vicente Batista (Univesp)  --&gt;
&lt;!-- &lt;/section&gt; --&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;hardcover.png&#34;
  &gt;

&lt;h2 id=&#34;curiosidades-do-r-básico&#34;&gt;Curiosidades do R básico&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Tempo: 1 ano&lt;/li&gt;
&lt;li&gt;Escrito em &lt;code&gt;\(\LaTeX\)&lt;/code&gt; (PDF)
&lt;ul&gt;
&lt;li&gt;classe &lt;em&gt;memoir&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Escrito com o pacote &lt;a href=&#34;https://bookdown.org/yihui/bookdown/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;bookdown&lt;/a&gt; (Versão em HTML)
&lt;ul&gt;
&lt;li&gt;Ultrapassou as 2500 linhas de comando&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;124 exercícios propostos&lt;/li&gt;
&lt;li&gt;$&amp;gt;$120 Códigos R numerados, sem contabilizar os não numerados&lt;/li&gt;
&lt;li&gt;339 páginas e 321 numeradas&lt;/li&gt;
&lt;li&gt;Publicado em 28/08/2022&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;hardcover.png&#34;
  &gt;

&lt;section&gt;
&lt;h2&gt;Estrutura do R básico&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Objetivo: Sintaxe e semântica do R (Introdutório)&lt;/li&gt;
&lt;li&gt;11 capítulos
&lt;ul&gt;
&lt;li&gt;Capítulo 1: Entendendo a coleção EAR&lt;/li&gt;
&lt;li&gt;Capítulo 2: História e instalação do R&lt;/li&gt;
&lt;li&gt;Capítulo 3: Como o R trabalha&lt;/li&gt;
&lt;li&gt;Capítulo 4: Objetos e estruturas de dados&lt;/li&gt;
&lt;li&gt;Capítulo 5: Importação e exportação de dados&lt;/li&gt;
&lt;li&gt;Capítulo 6: Funções no R&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Estrutura do R básico&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;11 capítulos
&lt;ul&gt;
&lt;li&gt;Capítulo 7: Boas práticas de como escrever um código&lt;/li&gt;
&lt;li&gt;Capítulo 8: Pacotes&lt;/li&gt;
&lt;li&gt;Capítulo 9: Ambientes e caminho de busca&lt;/li&gt;
&lt;li&gt;Capítulo 10: Interfaces com outras linguagens&lt;/li&gt;
&lt;li&gt;Capítulo 11: Considerações e preparação para o Volume II&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;O que veremos no livro?&lt;/h2&gt;
&lt;pre data-id=&#34;code-animation&#34;&gt;
&lt;code class=&#34;hljs&#34; data-trim data-line-numbers=&#34;|2,5|1-6&#34;&gt;
&lt;script type=&#34;text/template&#34;&gt;
  x &lt;- 10
  lobstr::obj_addr(x)
  ## [1] &#34;0xf8a104fc20&#34;
  y &lt;- x
  lobstr::obj_addr(y)
  ## [1] &#34;0xf8a104fc20&#34;
&lt;/script&gt;
&lt;/code&gt;
&lt;/pre&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt; Ilustração &lt;/h2&gt;














&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/lancamentorbasico-unifal/y=x=10_hud064575b8f0af6084abdce16d604d280_35386_68692ec504b290b034f8c838fb8db20a.webp 400w,
               /slides/lancamentorbasico-unifal/y=x=10_hud064575b8f0af6084abdce16d604d280_35386_15c6873244455d4c68831bc1ac435847.webp 760w,
               /slides/lancamentorbasico-unifal/y=x=10_hud064575b8f0af6084abdce16d604d280_35386_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/lancamentorbasico-unifal/y=x=10_hud064575b8f0af6084abdce16d604d280_35386_68692ec504b290b034f8c838fb8db20a.webp&#34;
               width=&#34;730&#34;
               height=&#34;380&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt; Objeto e Ambiente &lt;/h2&gt;














&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/lancamentorbasico-unifal/objamb_hu90f54417d64275fdfd02177500a3edb8_84634_8708be3b7e9712bbc8c049d901b3c1d9.webp 400w,
               /slides/lancamentorbasico-unifal/objamb_hu90f54417d64275fdfd02177500a3edb8_84634_1d82851f0dcb635bd55f6ee452d5eee4.webp 760w,
               /slides/lancamentorbasico-unifal/objamb_hu90f54417d64275fdfd02177500a3edb8_84634_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/lancamentorbasico-unifal/objamb_hu90f54417d64275fdfd02177500a3edb8_84634_8708be3b7e9712bbc8c049d901b3c1d9.webp&#34;
               width=&#34;730&#34;
               height=&#34;380&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/section&gt;
&lt;section&gt;
&lt;h2&gt;Capa/lateral/fundo&lt;/h2&gt;
&lt;p&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/lancamentorbasico-unifal/cover-back-front_hu3ce330fa360ba6e4db62da5bce0917e8_4645749_00da4cf45303c5812d852b1a6a7f785f.webp 400w,
               /slides/lancamentorbasico-unifal/cover-back-front_hu3ce330fa360ba6e4db62da5bce0917e8_4645749_2d3c75e90137881f78d6463e7dd9815d.webp 760w,
               /slides/lancamentorbasico-unifal/cover-back-front_hu3ce330fa360ba6e4db62da5bce0917e8_4645749_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/lancamentorbasico-unifal/cover-back-front_hu3ce330fa360ba6e4db62da5bce0917e8_4645749_00da4cf45303c5812d852b1a6a7f785f.webp&#34;
               width=&#34;760&#34;
               height=&#34;521&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;hardcover.png&#34;
  &gt;

&lt;h2 id=&#34;filosofia-de-publicação-selo-dc&#34;&gt;Filosofia de publicação (Selo DC)&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/dc/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/lancamentorbasico-unifal/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_57f4d021c573f1cdb22f5303fccfacd9.webp 400w,
               /slides/lancamentorbasico-unifal/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_e3124639f3c96b16d12396d9954194c3.webp 760w,
               /slides/lancamentorbasico-unifal/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/lancamentorbasico-unifal/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_57f4d021c573f1cdb22f5303fccfacd9.webp&#34;
               width=&#34;385&#34;
               height=&#34;406&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;section data-background-iframe=&#34;/books/eambr01&#34; data-background-interactive&gt;
	&lt;div style=&#34;position: absolute; width: 40%; right: 0; box-shadow: 0 1px 4px rgba(0,0,0,0.5), 0 5px 25px rgba(0,0,0,0.2); background-color: rgba(0, 0, 0, 0.9); color: #fff; padding: 20px; font-size: 20px; text-align: left;&#34;&gt;
		&lt;h2&gt;Página do livro R básico&lt;/h2&gt;
		&lt;p&gt;Todo o material do livro está disponível na página: &lt;a href=&#34;https://bendeivide.github.io/books/eambr01/&#34;&gt;https://bendeivide.github.io/books/eambr01/&lt;/a&gt;.&lt;/p&gt;
	&lt;/div&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;hardcover.png&#34;
  &gt;

&lt;h2 id=&#34;mais-sobre-o-r-básico&#34;&gt;Mais sobre o R básico&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/books/eambr01/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Página do R básico&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;hardcover.png&#34;
  &gt;

&lt;h1 id=&#34;obrigado&#34;&gt;Obrigado!&lt;/h1&gt;
&lt;p&gt;Sugestões, perguntas, críticas&amp;hellip;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Linhas de Pesquisa</title>
      <link>http://bendeivide.github.io/slides/linhapesquisa/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/linhapesquisa/</guid>
      <description>&lt;h1 id=&#34;linha-de-pesquisa&#34;&gt;Linha de Pesquisa&lt;/h1&gt;
&lt;p&gt;
  &lt;i class=&#34;fas fa-user-tie  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;https://bendeivide.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Ben Dêivide&lt;/a&gt; | 
  &lt;i class=&#34;fas fa-school  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;https://www.ufsj.edu.br/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;UFSJ&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;bio&#34;&gt;Bio&lt;/h2&gt;
&lt;p&gt;Estudo Estatística computacional, mais especificamente, o ambiente R. Estudos na área de Estatística Experimental e Probabilidade, como também no ensino da Estatística, Professor, Adjunto, C1. Atualmente trabalho na Universidade Federal de São João del-Rei (UFSJ), campus Alto Paraopeba, Ouro Branco/MG.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;linha-de-pesquisa-1&#34;&gt;Linha de Pesquisa&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Estatística computacional com ênfase em desenvolvimento de pacotes estatísticos&lt;/li&gt;
&lt;li&gt;Estatística Experimental&lt;/li&gt;
&lt;li&gt;Procedimentos de Comparações Múltiplas&lt;/li&gt;
&lt;li&gt;Ensino da estatística&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h1 id=&#34;contato&#34;&gt;Contato&lt;/h1&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Profissional&lt;/a&gt; | &lt;a href=&#34;https://ufsj.edu.br/bendeivide&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Institucional&lt;/a&gt; | &lt;a href=&#34;https://bendeivide.github.io/#contact&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;E-mail&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>MA41 - Probabilidade e Estatística</title>
      <link>http://bendeivide.github.io/slides/profmat-est/s01/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>http://bendeivide.github.io/slides/profmat-est/s01/</guid>
      <description>
&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap.png&#34;
  &gt;

&lt;h1 id=&#34;ma41---prob--est&#34;&gt;MA41 - Prob &amp;amp; Est&lt;/h1&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/courses/epaec/normal/#ementa&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Aula 01 - Tópicos 1, 2, 3&lt;/a&gt;
&lt;/br&gt;&lt;/p&gt;
&lt;p&gt;
  &lt;i class=&#34;fas fa-user-tie  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;https://bendeivide.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Ben Dêivide&lt;/a&gt; | 
  &lt;i class=&#34;fas fa-school  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;https://www.ufsj.edu.br/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;UFSJ&lt;/a&gt;
&lt;/br&gt;

  &lt;i class=&#34;fas fa-book  pr-1 fa-fw&#34;&gt;&lt;/i&gt; &lt;a href=&#34;http://bendeivide.github.io/courses/epaec/&#34;&gt;Estatística e Probabilidade&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;selo-dc&#34;&gt;Selo DC&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/dc/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;















&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/profmat-est/s01/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_57f4d021c573f1cdb22f5303fccfacd9.webp 400w,
               /slides/profmat-est/s01/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_e3124639f3c96b16d12396d9954194c3.webp 760w,
               /slides/profmat-est/s01/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/profmat-est/s01/SeloDC-branco_huae8c12316a547ca332088bbaf622ec6b_34348_57f4d021c573f1cdb22f5303fccfacd9.webp&#34;
               width=&#34;385&#34;
               height=&#34;406&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;section data-background-iframe=&#34;/courses/epaec&#34; data-background-interactive&gt;
	&lt;div style=&#34;position: absolute; width: 40%; right: 0; box-shadow: 0 1px 4px rgba(0,0,0,0.5), 0 5px 25px rgba(0,0,0,0.2); background-color: rgba(0, 0, 0, 0.9); color: #fff; padding: 20px; font-size: 20px; text-align: left;&#34;&gt;
		&lt;h2&gt;Material do curso&lt;/h2&gt;
		&lt;p&gt;Todo o material será disponível na página &lt;a href=&#34;https://bendeivide.github.io/courses/estcomp/&#34;&gt;Ben Dêivide&lt;/a&gt;.&lt;/p&gt;
	&lt;/div&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;!-- https://revealjs.com/transitions/ --&gt;
&lt;section data-transition=&#34;zoom&#34;&gt;
  &lt;h2&gt;Introdução&lt;/h2&gt;
  &lt;p&gt; Nossa vida atual é assim hoje ... &lt;/p&gt;
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  &lt;figure  id=&#34;figure-imagens-gratispngcom&#34;&gt;
    &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
      &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;Imagens: gratispng.com&#34; srcset=&#34;
                 /slides/profmat-est/s01/programador_hu85c5d9c20779881f2ae8deae4e3d792a_590442_0769bc3bdb3596bca3f6a01e3f6b0394.webp 400w,
                 /slides/profmat-est/s01/programador_hu85c5d9c20779881f2ae8deae4e3d792a_590442_198182e3dda60929a57504574af4d842.webp 760w,
                 /slides/profmat-est/s01/programador_hu85c5d9c20779881f2ae8deae4e3d792a_590442_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
                 src=&#34;http://bendeivide.github.io/slides/profmat-est/s01/programador_hu85c5d9c20779881f2ae8deae4e3d792a_590442_0769bc3bdb3596bca3f6a01e3f6b0394.webp&#34;
                 width=&#34;530&#34;
                 height=&#34;380&#34;
                 loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
    &lt;/div&gt;&lt;figcaption&gt;
        Imagens: gratispng.com
      &lt;/figcaption&gt;&lt;/figure&gt;
&lt;/section&gt;
&lt;section data-transition-speed=&#34;fast&#34;&gt;
&lt;h2&gt;Introdução&lt;/h2&gt;
&lt;p&gt; Nossa vida atual é assim hoje ... &lt;/p&gt;














&lt;figure  id=&#34;figure-imagens-gratispngcom&#34;&gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;Imagens: gratispng.com&#34; srcset=&#34;
               /slides/profmat-est/s01/dados_hu887ba6b7f9c0e641f75b5f82feacab54_163105_453a07f9082a2771b97ce6d020dc4ec8.webp 400w,
               /slides/profmat-est/s01/dados_hu887ba6b7f9c0e641f75b5f82feacab54_163105_1d078c7aaef4a058d23d40388727b8be.webp 760w,
               /slides/profmat-est/s01/dados_hu887ba6b7f9c0e641f75b5f82feacab54_163105_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/profmat-est/s01/dados_hu887ba6b7f9c0e641f75b5f82feacab54_163105_453a07f9082a2771b97ce6d020dc4ec8.webp&#34;
               width=&#34;530&#34;
               height=&#34;380&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      Imagens: gratispng.com
    &lt;/figcaption&gt;&lt;/figure&gt;
&lt;/section&gt;
&lt;section data-transition-speed=&#34;fast&#34;&gt;
&lt;h2&gt;Introdução&lt;/h2&gt;
&lt;p&gt; Usamos para tudo ... &lt;/p&gt;














&lt;figure  id=&#34;figure-imagens-gratispngcom&#34;&gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;Imagens: gratispng.com&#34; srcset=&#34;
               /slides/profmat-est/s01/emojis_huf8050f69e6ce2d326df2bbe686aea7ea_72356_5f58a4399a031452fdf2f7b4567ce22a.webp 400w,
               /slides/profmat-est/s01/emojis_huf8050f69e6ce2d326df2bbe686aea7ea_72356_ea8f7f14ad53afdff9b10b7854945999.webp 760w,
               /slides/profmat-est/s01/emojis_huf8050f69e6ce2d326df2bbe686aea7ea_72356_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/profmat-est/s01/emojis_huf8050f69e6ce2d326df2bbe686aea7ea_72356_5f58a4399a031452fdf2f7b4567ce22a.webp&#34;
               width=&#34;530&#34;
               height=&#34;380&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      Imagens: gratispng.com
    &lt;/figcaption&gt;&lt;/figure&gt;
&lt;/section&gt;
&lt;section data-transition-speed=&#34;fast&#34;&gt;
&lt;h2&gt;Introdução&lt;/h2&gt;
&lt;p&gt; Pesquisar ... &lt;/p&gt;














&lt;figure  id=&#34;figure-imagens-gratispngcom&#34;&gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;Imagens: gratispng.com&#34; srcset=&#34;
               /slides/profmat-est/s01/searching_hu749c487df7c6eff3fe551052b606a39d_94218_979a7958ebfc5597f19575ecd9f05006.webp 400w,
               /slides/profmat-est/s01/searching_hu749c487df7c6eff3fe551052b606a39d_94218_4f5e7490b68d33a29e8fb42d353e8930.webp 760w,
               /slides/profmat-est/s01/searching_hu749c487df7c6eff3fe551052b606a39d_94218_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/profmat-est/s01/searching_hu749c487df7c6eff3fe551052b606a39d_94218_979a7958ebfc5597f19575ecd9f05006.webp&#34;
               width=&#34;530&#34;
               height=&#34;380&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      Imagens: gratispng.com
    &lt;/figcaption&gt;&lt;/figure&gt;
&lt;/section&gt;
&lt;section data-transition-speed=&#34;fast&#34;&gt;
&lt;h2&gt;Introdução&lt;/h2&gt;
&lt;p&gt; Contratempos ... &lt;/p&gt;














&lt;figure  id=&#34;figure-imagens-gratispngcom&#34;&gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;Imagens: gratispng.com&#34; srcset=&#34;
               /slides/profmat-est/s01/quebrando_pc_hub4a3ac35862bea0b486522facdebe990_189986_dd3a418c0515058ffb1d8bd7f924ff87.webp 400w,
               /slides/profmat-est/s01/quebrando_pc_hub4a3ac35862bea0b486522facdebe990_189986_d8e1aa3e09274d0d674507d64e36b02f.webp 760w,
               /slides/profmat-est/s01/quebrando_pc_hub4a3ac35862bea0b486522facdebe990_189986_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/profmat-est/s01/quebrando_pc_hub4a3ac35862bea0b486522facdebe990_189986_dd3a418c0515058ffb1d8bd7f924ff87.webp&#34;
               width=&#34;530&#34;
               height=&#34;380&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      Imagens: gratispng.com
    &lt;/figcaption&gt;&lt;/figure&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;!-- https://revealjs.com/transitions/ --&gt;
&lt;section data-transition=&#34;zoom&#34;&gt;
  &lt;h2&gt;Dados&lt;/h2&gt;
  &lt;p&gt; Em meio a tudo isso, uma coisa acontece ... &lt;/p&gt;
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  &lt;figure  id=&#34;figure-imagens-gratispngcom&#34;&gt;
    &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
      &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;Imagens: gratispng.com&#34; srcset=&#34;
                 /slides/profmat-est/s01/dados02_huaa69fdfff67864a40a8e5e6a627be466_18369921_7684bd630a966bea4c66d8f3e27710af.webp 400w,
                 /slides/profmat-est/s01/dados02_huaa69fdfff67864a40a8e5e6a627be466_18369921_88e47f38d0b957e637a120fc53fed28d.webp 760w,
                 /slides/profmat-est/s01/dados02_huaa69fdfff67864a40a8e5e6a627be466_18369921_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
                 src=&#34;http://bendeivide.github.io/slides/profmat-est/s01/dados02_huaa69fdfff67864a40a8e5e6a627be466_18369921_7684bd630a966bea4c66d8f3e27710af.webp&#34;
                 width=&#34;530&#34;
                 height=&#34;380&#34;
                 loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
    &lt;/div&gt;&lt;figcaption&gt;
        Imagens: gratispng.com
      &lt;/figcaption&gt;&lt;/figure&gt;
&lt;/section&gt;
&lt;section data-transition-speed=&#34;fast&#34;&gt;
&lt;h2&gt;Dados&lt;/h2&gt;
&lt;p&gt; Essas informações são processadas ... &lt;/p&gt;














&lt;figure  id=&#34;figure-imagens-gratispngcom&#34;&gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;Imagens: gratispng.com&#34; srcset=&#34;
               /slides/profmat-est/s01/infra_comp_hub6808cefc104d832c78f51c1fe99f225_205407_d992efe6d9441dba596dd57504563239.webp 400w,
               /slides/profmat-est/s01/infra_comp_hub6808cefc104d832c78f51c1fe99f225_205407_cc5813b7ab49e6ce51f87ec864d8bd40.webp 760w,
               /slides/profmat-est/s01/infra_comp_hub6808cefc104d832c78f51c1fe99f225_205407_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/profmat-est/s01/infra_comp_hub6808cefc104d832c78f51c1fe99f225_205407_d992efe6d9441dba596dd57504563239.webp&#34;
               width=&#34;530&#34;
               height=&#34;380&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      Imagens: gratispng.com
    &lt;/figcaption&gt;&lt;/figure&gt;
&lt;/section&gt;
&lt;section data-transition-speed=&#34;fast&#34;&gt;
&lt;h2&gt;Dados&lt;/h2&gt;
&lt;p&gt; Analisadas ... &lt;/p&gt;














&lt;figure  id=&#34;figure-imagens-gratispngcom&#34;&gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;Imagens: gratispng.com&#34; srcset=&#34;
               /slides/profmat-est/s01/exp_user_hu8f5c0e0d7f084260f0d10501891b1393_29133_6ef8d184a5fe1679c0d6b7abc1011d81.webp 400w,
               /slides/profmat-est/s01/exp_user_hu8f5c0e0d7f084260f0d10501891b1393_29133_87aaaa3da49d73051be18accb8582e5a.webp 760w,
               /slides/profmat-est/s01/exp_user_hu8f5c0e0d7f084260f0d10501891b1393_29133_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/profmat-est/s01/exp_user_hu8f5c0e0d7f084260f0d10501891b1393_29133_6ef8d184a5fe1679c0d6b7abc1011d81.webp&#34;
               width=&#34;530&#34;
               height=&#34;380&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      Imagens: gratispng.com
    &lt;/figcaption&gt;&lt;/figure&gt;
&lt;/section&gt;
&lt;section data-transition-speed=&#34;fast&#34;&gt;
&lt;h2&gt;Dados&lt;/h2&gt;
&lt;p&gt; E assim, todos esses dados ... &lt;/p&gt;














&lt;figure  id=&#34;figure-imagens-gratispngcom&#34;&gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;Imagens: gratispng.com&#34; srcset=&#34;
               /slides/profmat-est/s01/analise02_hu9ea620b0e1d37040944340d01dd78f2b_515291_8778f4bc4322cd248911f541b900c98e.webp 400w,
               /slides/profmat-est/s01/analise02_hu9ea620b0e1d37040944340d01dd78f2b_515291_7a54132dfe8825d6cab37da7f5bfd4ed.webp 760w,
               /slides/profmat-est/s01/analise02_hu9ea620b0e1d37040944340d01dd78f2b_515291_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/profmat-est/s01/analise02_hu9ea620b0e1d37040944340d01dd78f2b_515291_8778f4bc4322cd248911f541b900c98e.webp&#34;
               width=&#34;530&#34;
               height=&#34;380&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      Imagens: gratispng.com
    &lt;/figcaption&gt;&lt;/figure&gt;
&lt;/section&gt;
&lt;section data-transition-speed=&#34;fast&#34;&gt;
&lt;h2&gt;Dados&lt;/h2&gt;
&lt;p&gt; ... que os usuários repassam ... &lt;/p&gt;














&lt;figure  id=&#34;figure-imagens-gratispngcom&#34;&gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;Imagens: gratispng.com&#34; srcset=&#34;
               /slides/profmat-est/s01/analise03_hub2e1dffd2cc65cb9ada91baab78eae39_412393_ecbf33cd9eab19e34cbc14286fd53e75.webp 400w,
               /slides/profmat-est/s01/analise03_hub2e1dffd2cc65cb9ada91baab78eae39_412393_6104309efe8272d3b6d06f70cad0b52b.webp 760w,
               /slides/profmat-est/s01/analise03_hub2e1dffd2cc65cb9ada91baab78eae39_412393_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/profmat-est/s01/analise03_hub2e1dffd2cc65cb9ada91baab78eae39_412393_ecbf33cd9eab19e34cbc14286fd53e75.webp&#34;
               width=&#34;530&#34;
               height=&#34;380&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      Imagens: gratispng.com
    &lt;/figcaption&gt;&lt;/figure&gt;
&lt;/section&gt;
&lt;section data-transition-speed=&#34;fast&#34;&gt;
&lt;h1&gt;Dados &gt; \$&lt;/h1&gt;
&lt;/section&gt;
&lt;section data-transition-speed=&#34;fast&#34;&gt;
&lt;h2&gt;Dados&lt;/h2&gt;
&lt;p&gt; E aí, o Vale do silício é o que tem que ser! &lt;/p&gt;














&lt;figure  id=&#34;figure-imagens-oficinadanetcombr&#34;&gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;Imagens: oficinadanet.com.br&#34; srcset=&#34;
               /slides/profmat-est/s01/vale_silicio_hu2e878ae56d4a55650a6917f7b07e2ae0_84455_e4d52bf7f5244f20b8c1cbb9bbc42621.webp 400w,
               /slides/profmat-est/s01/vale_silicio_hu2e878ae56d4a55650a6917f7b07e2ae0_84455_927ece7d5689dccd421079d10c92cf95.webp 760w,
               /slides/profmat-est/s01/vale_silicio_hu2e878ae56d4a55650a6917f7b07e2ae0_84455_1200x1200_fit_q75_h2_lanczos.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/profmat-est/s01/vale_silicio_hu2e878ae56d4a55650a6917f7b07e2ae0_84455_e4d52bf7f5244f20b8c1cbb9bbc42621.webp&#34;
               width=&#34;530&#34;
               height=&#34;380&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      Imagens: oficinadanet.com.br
    &lt;/figcaption&gt;&lt;/figure&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;!-- https://revealjs.com/transitions/ --&gt;
&lt;section data-transition=&#34;zoom&#34;&gt;
  &lt;h2&gt;Motivação inicial &lt;/h2&gt;
  &lt;p&gt; Definições gerais da estatística (Exemplo do livro EPAEC) &lt;/p&gt;
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  &lt;figure  &gt;
    &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
      &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
                 /slides/profmat-est/s01/epaec_exerc5.19_huf42f90654072e146aede07d81ef72130_118873_d2eb6c328bbca59128eb008a44841e3c.webp 400w,
                 /slides/profmat-est/s01/epaec_exerc5.19_huf42f90654072e146aede07d81ef72130_118873_2422affad744e4d2bee6a7971f41e9ec.webp 760w,
                 /slides/profmat-est/s01/epaec_exerc5.19_huf42f90654072e146aede07d81ef72130_118873_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
                 src=&#34;http://bendeivide.github.io/slides/profmat-est/s01/epaec_exerc5.19_huf42f90654072e146aede07d81ef72130_118873_d2eb6c328bbca59128eb008a44841e3c.webp&#34;
                 width=&#34;830&#34;
                 height=&#34;420&#34;
                 loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
    &lt;/div&gt;&lt;/figure&gt;
&lt;/section&gt;
&lt;section data-transition-speed=&#34;fast&#34;&gt;
&lt;h2&gt;Motivação inicial&lt;/h2&gt;
&lt;p&gt; Definições gerais da estatística... &lt;/p&gt;














&lt;figure  id=&#34;figure-imagem-livro-epaec&#34;&gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;Imagem: Livro EPAEC&#34; srcset=&#34;
               /slides/profmat-est/s01/prodcons_hu5910991e216a6cca12abe1fdcd74a6f7_5529_41d76642fcdda6f48ac510a3ac9a6405.webp 400w,
               /slides/profmat-est/s01/prodcons_hu5910991e216a6cca12abe1fdcd74a6f7_5529_18a6dc64c476a8c99164f36faf38e895.webp 760w,
               /slides/profmat-est/s01/prodcons_hu5910991e216a6cca12abe1fdcd74a6f7_5529_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/profmat-est/s01/prodcons_hu5910991e216a6cca12abe1fdcd74a6f7_5529_41d76642fcdda6f48ac510a3ac9a6405.webp&#34;
               width=&#34;530&#34;
               height=&#34;380&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;figcaption&gt;
      Imagem: Livro EPAEC
    &lt;/figcaption&gt;&lt;/figure&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;método-científico&#34;&gt;Método Científico&lt;/h2&gt;
&lt;iframe width=&#34;760&#34; height=&#34;515&#34; src=&#34;https://www.youtube.com/embed/QPeS1v7l6yk&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;!-- https://revealjs.com/transitions/ --&gt;
&lt;section data-transition=&#34;zoom&#34;&gt;
  &lt;h2&gt;Definições Gerais da Estatística&lt;/h2&gt;
  &lt;aside class=&#34;notes&#34;&gt;
    📝 Mostrar a relação do Método científico com as Definições gerais da estatística (Smoothdraw)
  &lt;/aside&gt;
  &lt;iframe width=&#34;760&#34; height=&#34;515&#34; src=&#34;https://www.youtube.com/embed/mASLUwyaC5Q&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;/section&gt;
&lt;section data-transition-speed=&#34;fast&#34;&gt;
&lt;h2&gt;Definições Gerais da Estatística&lt;/h2&gt;
&lt;aside class=&#34;notes&#34;&gt;
    📝 Mostrar a relação do Método científico com as Definições gerais da estatística (Smoothdraw)
  &lt;/aside&gt;
&lt;iframe width=&#34;760&#34; height=&#34;515&#34; src=&#34;https://www.youtube.com/embed/xvORKHMVUr8&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;/section&gt;
&lt;hr&gt;
&lt;h2 id=&#34;natureza-das-variáveis&#34;&gt;Natureza das variáveis&lt;/h2&gt;
&lt;iframe width=&#34;760&#34; height=&#34;515&#34; src=&#34;https://www.youtube.com/embed/LIg6uLzCRmU&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;técnicas-de-somatório&#34;&gt;Técnicas de Somatório&lt;/h2&gt;
  &lt;aside class=&#34;notes&#34;&gt;
    📝 Fazer alguns exemplos na sala digital (Smoothdraw)
  &lt;/aside&gt;
&lt;iframe width=&#34;760&#34; height=&#34;515&#34; src=&#34;https://www.youtube.com/embed/tWCxCyZZHes&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;section&gt;
  &lt;h2&gt;Motivação inicial&lt;/h2&gt;
  &lt;h3&gt; Dados (Primeiro tipo) &lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;##    [1] 100.93730855  90.78737290  31.43347250  70.04161421 114.72725633
##    [6] 119.48971504  39.59619123  81.81619913  18.66636591  87.17608029
##   [11] 155.08897515 137.78907540  88.08832220 149.37223517 137.06950642
##   [16] 104.46736332  52.25280719  90.24248077 146.27606310 124.14892624
##   [21]  70.18446816  -9.26434191  66.25670311  -5.95305960  36.74009892
##   [26]  81.31692224  65.62222848  56.39205866  94.91194969  87.31097349
##   [31]   7.31297728  96.10269670 148.42831703 109.24629800  31.00282108
##   [36]  28.22428188 118.10436143  12.04566231  83.77279952  67.42185057
##   [41] 154.32756997  61.87275600  58.56687325 141.72369515  51.61740066
##   [46]  98.55923323 111.62625763  84.93956592  66.11927084 132.76138181
##   [51]  79.96812265  83.27217175 168.39769766 206.88835518 125.29096323
##   [56] 139.31711921  54.88940279 126.64484962  67.70528732 114.54937442
##   [61]  38.12027656  77.19118624  58.48386726 117.00578218 153.31881978
##   [66] 160.80629190 136.78453288  75.93956913 128.13723814  37.68401441
##   [71] 119.04611063  28.47863736  47.57772476  89.07482247  25.50318816
##   [76] 158.63531406  26.00864892  78.48060920  47.41806790 176.12931720
##   [81] 129.64140273  88.86692455 135.64471381 135.83004169 122.01209322
##   [86] 107.94153107 132.98820692 211.02598315  40.80274630  96.30220828
##   [91]  79.18226626  90.42588281 103.47723907 157.76741590 129.74786735
##   [96]  29.01774458  19.66613773 144.64629498 107.40839776 161.35141951
##  [101]  61.90978304 120.96877029  48.00283177 135.57869830  68.33934925
##  [106] 128.15873322 133.04933429  17.09745713 151.40839885 156.39768070
##  [111]  35.99226983 156.44341137  76.79327364  84.21198952 146.21465734
##  [116] 103.85723620 151.99618026 137.09431034 162.77724291 147.54594832
##  [121]  75.93171964 110.14408890  98.41301281  40.22098498 131.18406184
##  [126]  54.25977582 112.43790039  46.86886034  81.80088764  39.65025733
##  [131] 171.46063907 131.67179455   0.15921912  65.90839135  76.99722603
##  [136]  50.84654029 124.76658564 136.29087501 133.36493659 147.73932182
##  [141]  16.23339104  39.74073038   1.83737554 173.53761549 118.62361693
##  [146] 153.29396670 126.53249342 105.09917229 166.88912329 104.36173842
##  [151]  80.44478963  87.50662577 157.75523729  56.76363801  56.66608288
##  [156] -16.05085152 130.44150845 157.50030241  40.02011641  20.99996227
##  [161] 132.65830968  72.52957574 126.05272627  65.02984668  78.05453426
##  [166]  66.13403519 147.95705974  26.59133353 109.18819463  28.24264087
##  [171]  43.13000509  79.26773366 107.19671441 153.10121653  71.46030486
##  [176] 163.85906882 111.41446603  84.55934677 147.99145653 127.44111874
##  [181] 121.27565469 132.17500176  31.98469282  90.07469468 130.96513384
##  [186] 203.41048025  84.73576229 114.06228061 134.56586684 102.31807191
##  [191] 105.65146808 149.76659371  65.94243193  36.14713767  26.56511251
##  [196]  84.32629667  14.81702537  32.47426719  44.89531614  45.02284927
##  [201] 160.77568881 116.54382426 169.51375596 143.60234925  45.95914887
##  [206] 124.79107957 152.63137781  36.26750249  90.31666358  35.24581787
##  [211] 107.09401423 163.08575260  78.42498360   8.86437052 117.62719794
##  [216]  32.57742793 135.38441590  79.45545316  77.69774100  47.94218492
##  [221]  83.53876419  85.85891879 121.62145627  84.61964525  97.16818461
##  [226] 136.67577101 104.86558098 181.54458683 128.03053495 166.47823822
##  [231]  86.05882522  36.66342279  87.54258030 100.89942073 118.85363636
##  [236] 139.80042788  57.96612915 -10.27358754  43.59720045  32.93450206
##  [241] 180.25570214 137.22118642 143.10411030 119.75779077 125.45593482
##  [246]  93.87249371 104.62923236  82.10600428  82.01723878 151.42853604
##  [251] 153.89462962 146.58906076  26.96030665  54.69622119  65.98260843
##  [256] 153.15830184  65.37934239  43.31858674  45.26922831  49.35481906
##  [261] 120.51386629 123.88702210 -16.49397725 100.81277326 149.01767616
##  [266] 140.31741324 105.98004444 -21.83078022 101.55112381  83.21266510
##  [271]  86.81119190  82.20737696  75.94226009 111.13677339 221.49551593
##  [276] 174.81490594  64.13958986  76.64730499 133.14617264 215.00884455
##  [281] 116.37550706 103.19317408  43.02195300 159.02051018 102.06942385
##  [286]  39.32032183 103.65978883  87.13377028 113.34032055 169.38621629
##  [291] 109.65398175 129.61583113  58.50127365 119.62866408 119.24338053
##  [296] 152.55223329 157.78987423  48.27810205  87.27659671 163.68421330
##  [301] 175.12723195 129.52047336  68.46572743 139.61747686 106.26922851
##  [306] 116.13774856  77.72083953 138.34219672  29.82484891  41.19766102
##  [311] 125.57982346 165.83826319 219.64564735  96.61152958  89.81074668
##  [316] 199.82172261 177.16088972  38.58311869 232.22439961 137.85068541
##  [321] 152.76725961 147.89724477 141.69395288  91.53622150  79.77831785
##  [326] 114.78007869  88.40627464  77.59608842 101.11553983 102.22336486
##  [331] 124.03605826 131.78099276  -0.03711965  65.46722481  93.46774053
##  [336]  82.78741085  97.37935880 104.80619603 113.32035266 127.73967376
##  [341] 161.77229393 114.25666907  77.06035361 131.17390109  63.80024542
##  [346] 180.97093517  69.16632949 119.22705287 205.72606564  48.57163169
##  [351]  55.66060172 163.55730007  19.74572794 156.11366915 207.92193209
##  [356] 121.41233065 160.05893452 151.58450581 132.69371264 200.60408866
##  [361] 154.73149209 136.32046770  30.01714317  35.61024184  51.57922612
##  [366]  13.16571211 141.58486790  62.05234457 207.75385005  78.83705599
##  [371]  99.71750317 120.01808643  81.71610990  78.54280824 112.23485634
##  [376] 210.98881244 115.71349040  71.81074627  25.71519208 120.76492965
##  [381]  73.59681587  82.47646913 136.53109686  72.16879175  27.51197319
##  [386]  47.40017859  65.85806906  69.35294107 194.53900175  92.72947332
##  [391]  68.02881397  79.44119774 117.13959392  43.33766227 103.30351513
##  [396] 101.89998830 146.05323738 206.74828192  70.00865342 162.22232293
##  [401]  96.02714914 159.08757749 209.30720313 120.30874654  63.08204477
##  [406]   2.17566485   2.49771492  52.95010922 159.88933843  68.78803048
##  [411]  93.35651724  99.13895389  77.01853589 173.64683953 208.46598063
##  [416] -50.07156532  11.40072085  81.75803886 118.72668903  38.29610367
##  [421] 123.74467110 161.65287285  70.34356716 137.61312197 130.60227534
##  [426]  88.56713174  64.75803251 161.47580236 175.92575649 167.25470902
##  [431]  93.81542355 146.69512268 100.97484228 141.54260549  84.77526660
##  [436]  97.03593614 150.36983487  31.11024570  49.78986365  98.83598475
##  [441] 177.33736369  62.03183745 150.33963287 113.71074582  95.98088177
##  [446]  54.82237523 123.65725515 169.42444890 101.73730469  35.37074860
##  [451] 158.19837525  23.83077015 -25.91675268  64.62353847  85.62835586
##  [456]  78.23458443  82.84606146  98.03445580 144.34829939  82.00257996
##  [461]  63.55228647 187.58728096  95.69807049 155.31815079  99.04110814
##  [466]  25.32699108 235.03183115  62.81527889 153.25974905  98.39591342
##  [471]  73.00201553   3.71782162 150.39156881  86.03826016  37.52170724
##  [476] 162.42455639  90.38933117 145.59881155  -7.91348400 164.48052662
##  [481]  78.59450172  87.24985535 166.35791194 141.93450603  26.74996614
##  [486]  69.18736511 105.30529197   7.79916211  19.17885731 111.38383521
##  [491] 146.06083510  83.43982803 164.36170155 102.86304012 -10.19665626
##  [496]  73.85448259 154.03926551  87.84293312  54.52767189  56.58502463
##  [501] 143.47375225  65.99952011 108.66072694  92.02809805 139.67497163
##  [506] 184.71752457 161.99843432 101.47183716 182.86072495 156.56115701
##  [511]  29.87946839 107.83852306 143.37542982  98.33824214 147.70322782
##  [516] 156.50483626 119.68486560 118.84041640  87.41285465 125.20474454
##  [521]  33.50982643  94.08502737  68.33757667 133.88456724  85.10591176
##  [526] 131.39611236 183.92153640 -20.00012703  32.50785575 160.10039479
##  [531] 164.69213597  97.02028269  65.74688274  27.32803478 164.70632806
##  [536] 158.80845447 143.20225391 -14.83662617  30.40949940  30.70616275
##  [541]  46.34765780  52.92872484  70.67828451 151.73606100 122.94811033
##  [546]  40.32774640 139.59446358  11.38475446  70.61387890  35.88148437
##  [551]  84.39326695  65.06123497 -32.19248839 141.25111884 115.34631566
##  [556]  97.09802709 146.32847054  89.06540697 149.65667487   3.83328288
##  [561]  47.36424078 144.51988810 277.05701388 137.07553713  89.62643730
##  [566] 108.99692271 171.31824247  77.84166053 118.35949933 134.79108481
##  [571] 146.67223643 174.59445413 157.97614951 111.33979785  35.22674076
##  [576]  96.86106542 149.66414684  49.70345300  62.45075262 187.20081912
##  [581]  40.61999543  79.15147911  21.50899203  85.97629824  70.73365181
##  [586] 133.01595988  68.12437255  73.04891834 147.57601168  94.72100771
##  [591]  81.29653636  91.18837096 113.82416540 111.81662963 203.08370797
##  [596]  35.49700071 128.55947237 189.26951134 110.64701215 144.23460730
##  [601]  54.90148678  97.26250210  32.16226445 115.86152886 169.78595597
##  [606]  39.43880916  89.79291696  22.37743370 125.90248343  79.05798484
##  [611]  14.52733922 224.15813357 124.90168675  66.30658974  55.65093022
##  [616]  13.43113246 130.22745607  56.43624609 136.26708232  98.46340099
##  [621]  94.13888128 104.91114693  66.15713891  97.53768225  71.96401200
##  [626] 219.95774326  95.50639492  58.91757911  85.65191192 106.56394370
##  [631]  46.89580248 136.67905179 116.13460992  82.55101143 164.17628321
##  [636]  49.27559756  74.49678629  91.64151269  84.86661072 201.32352362
##  [641] 145.04528192 106.77145202  89.93555229  59.65816295 132.20620619
##  [646]  83.16704397  13.41482444 113.09603313  54.16512009  71.57177624
##  [651]  56.70897791 141.27469559  59.99338579 148.79150434 235.00377654
##  [656]  93.23052016  94.69844180  32.79680974 122.15609143 148.05588708
##  [661]  87.92820917 104.14774456  81.91376211 116.69300999 113.28047105
##  [666] 250.64528733  82.76349312 153.12787266  63.51574630 102.82738605
##  [671] 123.39148560  81.36773747 110.50808438 164.48041528  18.65802251
##  [676]  60.82317452 125.54565517 160.88130280 115.25546238 110.51468167
##  [681] 123.44329828   4.78287139 161.92011423 119.54994457  98.44005416
##  [686]  19.05997391 122.56331391  65.45783182 170.27228110  14.93286561
##  [691] 109.61227986  64.85216193  59.57220683  68.09006292 186.86727140
##  [696] -13.02391316  19.37639531 132.68700994 145.14403643 137.73042439
##  [701]  88.65946156  65.20156862 125.33236787 130.81171468  16.65603627
##  [706]  83.18728871 125.35899284  15.13046492  89.65363880  80.07014859
##  [711]  40.56900863 122.62827021 110.37948520  39.49388119 138.37075271
##  [716]  70.04861544  21.95136136  50.21679785 154.66255042 145.85714430
##  [721]  61.34753224  76.20820912  43.46484080  78.55822842  58.02081751
##  [726]  69.95066635  61.30546109  55.37538244  98.21340765  84.79109488
##  [731] -50.60818918  -0.42615289  97.68142953  82.02314677  90.24891691
##  [736]  24.27649323  55.39834764  56.86467543 127.59770740  90.58830433
##  [741]  83.74266282  73.15307754  81.42612936 136.14035118 160.28459417
##  [746] 159.20765628 133.55952177 158.77510367 109.42632364 124.95317984
##  [751]   2.61908443 121.03686231 158.67381249  27.68842215  81.66243970
##  [756]  69.61018826 115.99356887 154.99238361  79.69816862 220.53732134
##  [761] 157.94499424 116.91947958 122.80886720  84.29776668 170.21720101
##  [766]  79.48650255  95.59487419 116.24377974 159.25499001  87.22457133
##  [771] 144.22239604  75.57194652  63.63119134  40.58723635  73.10287920
##  [776] 105.96756087 165.90890477 172.15402788 112.45131058 140.78511634
##  [781]  63.26960968 112.90766390  57.35696156 110.78243793  64.53948940
##  [786] 135.54327616  77.63140706  83.08508479 125.86167111 104.93517972
##  [791] 137.18428079  86.07249293 126.95358403  95.58302652  62.71212459
##  [796]  21.99607744 154.14782627 -17.05280013 110.31526330 138.23712856
##  [801]  -6.25342905 126.05893332  97.67885500  42.52641395 131.46691539
##  [806]  63.67642620  80.67913388  66.41428051 145.01930952 144.34208453
##  [811] 119.51390559  53.62442549 137.29196144 124.74120783  98.90342691
##  [816] 129.40111631 137.82455370  75.29868637  63.33421857  99.94898030
##  [821] 140.29128484 155.46546909  84.51602589  54.57108759 113.15130638
##  [826]  98.95410962  89.38287462  48.44480401 106.97553698 108.31089923
##  [831]  50.76701755 101.13170354 139.26650163  41.04052379 195.53953888
##  [836]  73.09992525 144.21382145 107.36548184  49.57863186 141.90944961
##  [841]  41.58804313 122.71590665 110.62864338  72.34568263 101.17150126
##  [846] 132.40894452  12.86026324 129.75813305  56.07354935 132.22187856
##  [851]  68.54507487  95.08999052 134.21088496  30.76569845 177.74727930
##  [856]  59.28293291  57.81844571 151.24637129 105.78516882 112.07470199
##  [861]  30.45919292 176.30304223 102.32581184 161.99911798 115.42863177
##  [866] 139.28138023 155.87393524  99.75088638  91.07908949 134.81145345
##  [871] 126.08986042  77.60867049 120.27003020  63.15177877 112.78740072
##  [876]  85.75332475  98.44393375  75.70705565  93.24559579  25.96406386
##  [881] 162.81845628 110.45208250 115.65783948 153.75741193  85.66874127
##  [886]  98.40112863  62.86333017 204.26100961 142.74452052 150.02229981
##  [891]  40.79410450  22.94487224  89.41334996 108.51762850  65.46113128
##  [896] 184.88603695  96.36550187  64.11955719  79.17427808 209.67933805
##  [901] 127.11739129 151.18338045 140.64130544 165.05135387 128.39782055
##  [906]  93.99642789  75.39986469 110.03859877 108.23996494 134.68288481
##  [911] 106.66621267  63.02684207  80.12405924 112.85793197  85.99130404
##  [916] 150.39837961 157.76098120  89.86025254  83.92952265  18.94730415
##  [921] 128.40526295 133.56401236 173.01297609  18.11403129 164.92505411
##  [926]  92.31500856 178.95744228 202.76175928 164.22433254 120.87016586
##  [931] 157.99268036 124.57951279 155.10043589 128.42852151  81.80414574
##  [936] 106.84781854 136.21377136 176.99908030 149.34961674  52.69890010
##  [941]  69.36596579 164.34432952  72.16749200  98.85111389 166.23705613
##  [946] 113.19488345 142.06695095  86.79312555 144.33846460 111.27428778
##  [951] 127.24163623 158.81253634  84.32123791 125.26883443 176.98506493
##  [956] 174.55013553 112.18447423  79.23428368  -1.75863811  67.83210511
##  [961] 102.69107405  80.52190580 193.89127767  27.11966366 136.19276892
##  [966]  39.09618692  84.71205651 101.21988583 117.61330506 141.18948778
##  [971] 129.88932805 164.78187322  71.09669104 108.64874902  70.94018770
##  [976]  60.87047018  16.65853979  64.32633758  74.66620861  65.24080279
##  [981] 127.08039056  70.94613518 121.54160255 133.58505948  78.32463472
##  [986]  60.95082856 120.81490912  58.91897002 110.55379452 137.74115849
##  [991] 189.00548763 133.29738410  99.46330902  39.94726968  67.83011078
##  [996] 139.86461552 126.41241372 114.18348694  99.39303476  90.40431113
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3&gt; Dados (Segundo tipo) &lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;##    [1] -50.60818918 -50.07156532 -32.19248839 -25.91675268 -21.83078022
##    [6] -20.00012703 -17.05280013 -16.49397725 -16.05085152 -14.83662617
##   [11] -13.02391316 -10.27358754 -10.19665626  -9.26434191  -7.91348400
##   [16]  -6.25342905  -5.95305960  -1.75863811  -0.42615289  -0.03711965
##   [21]   0.15921912   1.83737554   2.17566485   2.49771492   2.61908443
##   [26]   3.71782162   3.83328288   4.78287139   7.31297728   7.79916211
##   [31]   8.86437052  11.38475446  11.40072085  12.04566231  12.86026324
##   [36]  13.16571211  13.41482444  13.43113246  14.52733922  14.81702537
##   [41]  14.93286561  15.13046492  16.23339104  16.65603627  16.65853979
##   [46]  17.09745713  18.11403129  18.65802251  18.66636591  18.94730415
##   [51]  19.05997391  19.17885731  19.37639531  19.66613773  19.74572794
##   [56]  20.99996227  21.50899203  21.95136136  21.99607744  22.37743370
##   [61]  22.94487224  23.83077015  24.27649323  25.32699108  25.50318816
##   [66]  25.71519208  25.96406386  26.00864892  26.56511251  26.59133353
##   [71]  26.74996614  26.96030665  27.11966366  27.32803478  27.51197319
##   [76]  27.68842215  28.22428188  28.24264087  28.47863736  29.01774458
##   [81]  29.82484891  29.87946839  30.01714317  30.40949940  30.45919292
##   [86]  30.70616275  30.76569845  31.00282108  31.11024570  31.43347250
##   [91]  31.98469282  32.16226445  32.47426719  32.50785575  32.57742793
##   [96]  32.79680974  32.93450206  33.50982643  35.22674076  35.24581787
##  [101]  35.37074860  35.49700071  35.61024184  35.88148437  35.99226983
##  [106]  36.14713767  36.26750249  36.66342279  36.74009892  37.52170724
##  [111]  37.68401441  38.12027656  38.29610367  38.58311869  39.09618692
##  [116]  39.32032183  39.43880916  39.49388119  39.59619123  39.65025733
##  [121]  39.74073038  39.94726968  40.02011641  40.22098498  40.32774640
##  [126]  40.56900863  40.58723635  40.61999543  40.79410450  40.80274630
##  [131]  41.04052379  41.19766102  41.58804313  42.52641395  43.02195300
##  [136]  43.13000509  43.31858674  43.33766227  43.46484080  43.59720045
##  [141]  44.89531614  45.02284927  45.26922831  45.95914887  46.34765780
##  [146]  46.86886034  46.89580248  47.36424078  47.40017859  47.41806790
##  [151]  47.57772476  47.94218492  48.00283177  48.27810205  48.44480401
##  [156]  48.57163169  49.27559756  49.35481906  49.57863186  49.70345300
##  [161]  49.78986365  50.21679785  50.76701755  50.84654029  51.57922612
##  [166]  51.61740066  52.25280719  52.69890010  52.92872484  52.95010922
##  [171]  53.62442549  54.16512009  54.25977582  54.52767189  54.57108759
##  [176]  54.69622119  54.82237523  54.88940279  54.90148678  55.37538244
##  [181]  55.39834764  55.65093022  55.66060172  56.07354935  56.39205866
##  [186]  56.43624609  56.58502463  56.66608288  56.70897791  56.76363801
##  [191]  56.86467543  57.35696156  57.81844571  57.96612915  58.02081751
##  [196]  58.48386726  58.50127365  58.56687325  58.91757911  58.91897002
##  [201]  59.28293291  59.57220683  59.65816295  59.99338579  60.82317452
##  [206]  60.87047018  60.95082856  61.30546109  61.34753224  61.87275600
##  [211]  61.90978304  62.03183745  62.05234457  62.45075262  62.71212459
##  [216]  62.81527889  62.86333017  63.02684207  63.08204477  63.15177877
##  [221]  63.26960968  63.33421857  63.51574630  63.55228647  63.63119134
##  [226]  63.67642620  63.80024542  64.11955719  64.13958986  64.32633758
##  [231]  64.53948940  64.62353847  64.75803251  64.85216193  65.02984668
##  [236]  65.06123497  65.20156862  65.24080279  65.37934239  65.45783182
##  [241]  65.46113128  65.46722481  65.62222848  65.74688274  65.85806906
##  [246]  65.90839135  65.94243193  65.98260843  65.99952011  66.11927084
##  [251]  66.13403519  66.15713891  66.25670311  66.30658974  66.41428051
##  [256]  67.42185057  67.70528732  67.83011078  67.83210511  68.02881397
##  [261]  68.09006292  68.12437255  68.33757667  68.33934925  68.46572743
##  [266]  68.54507487  68.78803048  69.16632949  69.18736511  69.35294107
##  [271]  69.36596579  69.61018826  69.95066635  70.00865342  70.04161421
##  [276]  70.04861544  70.18446816  70.34356716  70.61387890  70.67828451
##  [281]  70.73365181  70.94018770  70.94613518  71.09669104  71.46030486
##  [286]  71.57177624  71.81074627  71.96401200  72.16749200  72.16879175
##  [291]  72.34568263  72.52957574  73.00201553  73.04891834  73.09992525
##  [296]  73.10287920  73.15307754  73.59681587  73.85448259  74.49678629
##  [301]  74.66620861  75.29868637  75.39986469  75.57194652  75.70705565
##  [306]  75.93171964  75.93956913  75.94226009  76.20820912  76.64730499
##  [311]  76.79327364  76.99722603  77.01853589  77.06035361  77.19118624
##  [316]  77.59608842  77.60867049  77.63140706  77.69774100  77.72083953
##  [321]  77.84166053  78.05453426  78.23458443  78.32463472  78.42498360
##  [326]  78.48060920  78.54280824  78.55822842  78.59450172  78.83705599
##  [331]  79.05798484  79.15147911  79.17427808  79.18226626  79.23428368
##  [336]  79.26773366  79.44119774  79.45545316  79.48650255  79.69816862
##  [341]  79.77831785  79.96812265  80.07014859  80.12405924  80.44478963
##  [346]  80.52190580  80.67913388  81.29653636  81.31692224  81.36773747
##  [351]  81.42612936  81.66243970  81.71610990  81.75803886  81.80088764
##  [356]  81.80414574  81.81619913  81.91376211  82.00257996  82.01723878
##  [361]  82.02314677  82.10600428  82.20737696  82.47646913  82.55101143
##  [366]  82.76349312  82.78741085  82.84606146  83.08508479  83.16704397
##  [371]  83.18728871  83.21266510  83.27217175  83.43982803  83.53876419
##  [376]  83.74266282  83.77279952  83.92952265  84.21198952  84.29776668
##  [381]  84.32123791  84.32629667  84.39326695  84.51602589  84.55934677
##  [386]  84.61964525  84.71205651  84.73576229  84.77526660  84.79109488
##  [391]  84.86661072  84.93956592  85.10591176  85.62835586  85.65191192
##  [396]  85.66874127  85.75332475  85.85891879  85.97629824  85.99130404
##  [401]  86.03826016  86.05882522  86.07249293  86.79312555  86.81119190
##  [406]  87.13377028  87.17608029  87.22457133  87.24985535  87.27659671
##  [411]  87.31097349  87.41285465  87.50662577  87.54258030  87.84293312
##  [416]  87.92820917  88.08832220  88.40627464  88.56713174  88.65946156
##  [421]  88.86692455  89.06540697  89.07482247  89.38287462  89.41334996
##  [426]  89.62643730  89.65363880  89.79291696  89.81074668  89.86025254
##  [431]  89.93555229  90.07469468  90.24248077  90.24891691  90.31666358
##  [436]  90.38933117  90.40431113  90.42588281  90.58830433  90.78737290
##  [441]  91.07908949  91.18837096  91.53622150  91.64151269  92.02809805
##  [446]  92.31500856  92.72947332  93.23052016  93.24559579  93.35651724
##  [451]  93.46774053  93.81542355  93.87249371  93.99642789  94.08502737
##  [456]  94.13888128  94.69844180  94.72100771  94.91194969  95.08999052
##  [461]  95.50639492  95.58302652  95.59487419  95.69807049  95.98088177
##  [466]  96.02714914  96.10269670  96.30220828  96.36550187  96.61152958
##  [471]  96.86106542  97.02028269  97.03593614  97.09802709  97.16818461
##  [476]  97.26250210  97.37935880  97.53768225  97.67885500  97.68142953
##  [481]  98.03445580  98.21340765  98.33824214  98.39591342  98.40112863
##  [486]  98.41301281  98.44005416  98.44393375  98.46340099  98.55923323
##  [491]  98.83598475  98.85111389  98.90342691  98.95410962  99.04110814
##  [496]  99.13895389  99.39303476  99.46330902  99.71750317  99.75088638
##  [501]  99.94898030 100.81277326 100.89942073 100.93730855 100.97484228
##  [506] 101.11553983 101.13170354 101.17150126 101.21988583 101.47183716
##  [511] 101.55112381 101.73730469 101.89998830 102.06942385 102.22336486
##  [516] 102.31807191 102.32581184 102.69107405 102.82738605 102.86304012
##  [521] 103.19317408 103.30351513 103.47723907 103.65978883 103.85723620
##  [526] 104.14774456 104.36173842 104.46736332 104.62923236 104.80619603
##  [531] 104.86558098 104.91114693 104.93517972 105.09917229 105.30529197
##  [536] 105.65146808 105.78516882 105.96756087 105.98004444 106.26922851
##  [541] 106.56394370 106.66621267 106.77145202 106.84781854 106.97553698
##  [546] 107.09401423 107.19671441 107.36548184 107.40839776 107.83852306
##  [551] 107.94153107 108.23996494 108.31089923 108.51762850 108.64874902
##  [556] 108.66072694 108.99692271 109.18819463 109.24629800 109.42632364
##  [561] 109.61227986 109.65398175 110.03859877 110.14408890 110.31526330
##  [566] 110.37948520 110.45208250 110.50808438 110.51468167 110.55379452
##  [571] 110.62864338 110.64701215 110.78243793 111.13677339 111.27428778
##  [576] 111.33979785 111.38383521 111.41446603 111.62625763 111.81662963
##  [581] 112.07470199 112.18447423 112.23485634 112.43790039 112.45131058
##  [586] 112.78740072 112.85793197 112.90766390 113.09603313 113.15130638
##  [591] 113.19488345 113.28047105 113.32035266 113.34032055 113.71074582
##  [596] 113.82416540 114.06228061 114.18348694 114.25666907 114.54937442
##  [601] 114.72725633 114.78007869 115.25546238 115.34631566 115.42863177
##  [606] 115.65783948 115.71349040 115.86152886 115.99356887 116.13460992
##  [611] 116.13774856 116.24377974 116.37550706 116.54382426 116.69300999
##  [616] 116.91947958 117.00578218 117.13959392 117.61330506 117.62719794
##  [621] 118.10436143 118.35949933 118.62361693 118.72668903 118.84041640
##  [626] 118.85363636 119.04611063 119.22705287 119.24338053 119.48971504
##  [631] 119.51390559 119.54994457 119.62866408 119.68486560 119.75779077
##  [636] 120.01808643 120.27003020 120.30874654 120.51386629 120.76492965
##  [641] 120.81490912 120.87016586 120.96877029 121.03686231 121.27565469
##  [646] 121.41233065 121.54160255 121.62145627 122.01209322 122.15609143
##  [651] 122.56331391 122.62827021 122.71590665 122.80886720 122.94811033
##  [656] 123.39148560 123.44329828 123.65725515 123.74467110 123.88702210
##  [661] 124.03605826 124.14892624 124.57951279 124.74120783 124.76658564
##  [666] 124.79107957 124.90168675 124.95317984 125.20474454 125.26883443
##  [671] 125.29096323 125.33236787 125.35899284 125.45593482 125.54565517
##  [676] 125.57982346 125.86167111 125.90248343 126.05272627 126.05893332
##  [681] 126.08986042 126.41241372 126.53249342 126.64484962 126.95358403
##  [686] 127.08039056 127.11739129 127.24163623 127.44111874 127.59770740
##  [691] 127.73967376 128.03053495 128.13723814 128.15873322 128.39782055
##  [696] 128.40526295 128.42852151 128.55947237 129.40111631 129.52047336
##  [701] 129.61583113 129.64140273 129.74786735 129.75813305 129.88932805
##  [706] 130.22745607 130.44150845 130.60227534 130.81171468 130.96513384
##  [711] 131.17390109 131.18406184 131.39611236 131.46691539 131.67179455
##  [716] 131.78099276 132.17500176 132.20620619 132.22187856 132.40894452
##  [721] 132.65830968 132.68700994 132.69371264 132.76138181 132.98820692
##  [726] 133.01595988 133.04933429 133.14617264 133.29738410 133.36493659
##  [731] 133.55952177 133.56401236 133.58505948 133.88456724 134.21088496
##  [736] 134.56586684 134.68288481 134.79108481 134.81145345 135.38441590
##  [741] 135.54327616 135.57869830 135.64471381 135.83004169 136.14035118
##  [746] 136.19276892 136.21377136 136.26708232 136.29087501 136.32046770
##  [751] 136.53109686 136.67577101 136.67905179 136.78453288 137.06950642
##  [756] 137.07553713 137.09431034 137.18428079 137.22118642 137.29196144
##  [761] 137.61312197 137.73042439 137.74115849 137.78907540 137.82455370
##  [766] 137.85068541 138.23712856 138.34219672 138.37075271 139.26650163
##  [771] 139.28138023 139.31711921 139.59446358 139.61747686 139.67497163
##  [776] 139.80042788 139.86461552 140.29128484 140.31741324 140.64130544
##  [781] 140.78511634 141.18948778 141.25111884 141.27469559 141.54260549
##  [786] 141.58486790 141.69395288 141.72369515 141.90944961 141.93450603
##  [791] 142.06695095 142.74452052 143.10411030 143.20225391 143.37542982
##  [796] 143.47375225 143.60234925 144.21382145 144.22239604 144.23460730
##  [801] 144.33846460 144.34208453 144.34829939 144.51988810 144.64629498
##  [806] 145.01930952 145.04528192 145.14403643 145.59881155 145.85714430
##  [811] 146.05323738 146.06083510 146.21465734 146.27606310 146.32847054
##  [816] 146.58906076 146.67223643 146.69512268 147.54594832 147.57601168
##  [821] 147.70322782 147.73932182 147.89724477 147.95705974 147.99145653
##  [826] 148.05588708 148.42831703 148.79150434 149.01767616 149.34961674
##  [831] 149.37223517 149.65667487 149.66414684 149.76659371 150.02229981
##  [836] 150.33963287 150.36983487 150.39156881 150.39837961 151.18338045
##  [841] 151.24637129 151.40839885 151.42853604 151.58450581 151.73606100
##  [846] 151.99618026 152.55223329 152.63137781 152.76725961 153.10121653
##  [851] 153.12787266 153.15830184 153.25974905 153.29396670 153.31881978
##  [856] 153.75741193 153.89462962 154.03926551 154.14782627 154.32756997
##  [861] 154.66255042 154.73149209 154.99238361 155.08897515 155.10043589
##  [866] 155.31815079 155.46546909 155.87393524 156.11366915 156.39768070
##  [871] 156.44341137 156.50483626 156.56115701 157.50030241 157.75523729
##  [876] 157.76098120 157.76741590 157.78987423 157.94499424 157.97614951
##  [881] 157.99268036 158.19837525 158.63531406 158.67381249 158.77510367
##  [886] 158.80845447 158.81253634 159.02051018 159.08757749 159.20765628
##  [891] 159.25499001 159.88933843 160.05893452 160.10039479 160.28459417
##  [896] 160.77568881 160.80629190 160.88130280 161.35141951 161.47580236
##  [901] 161.65287285 161.77229393 161.92011423 161.99843432 161.99911798
##  [906] 162.22232293 162.42455639 162.77724291 162.81845628 163.08575260
##  [911] 163.55730007 163.68421330 163.85906882 164.17628321 164.22433254
##  [916] 164.34432952 164.36170155 164.48041528 164.48052662 164.69213597
##  [921] 164.70632806 164.78187322 164.92505411 165.05135387 165.83826319
##  [926] 165.90890477 166.23705613 166.35791194 166.47823822 166.88912329
##  [931] 167.25470902 168.39769766 169.38621629 169.42444890 169.51375596
##  [936] 169.78595597 170.21720101 170.27228110 171.31824247 171.46063907
##  [941] 172.15402788 173.01297609 173.53761549 173.64683953 174.55013553
##  [946] 174.59445413 174.81490594 175.12723195 175.92575649 176.12931720
##  [951] 176.30304223 176.98506493 176.99908030 177.16088972 177.33736369
##  [956] 177.74727930 178.95744228 180.25570214 180.97093517 181.54458683
##  [961] 182.86072495 183.92153640 184.71752457 184.88603695 186.86727140
##  [966] 187.20081912 187.58728096 189.00548763 189.26951134 193.89127767
##  [971] 194.53900175 195.53953888 199.82172261 200.60408866 201.32352362
##  [976] 202.76175928 203.08370797 203.41048025 204.26100961 205.72606564
##  [981] 206.74828192 206.88835518 207.75385005 207.92193209 208.46598063
##  [986] 209.30720313 209.67933805 210.98881244 211.02598315 215.00884455
##  [991] 219.64564735 219.95774326 220.53732134 221.49551593 224.15813357
##  [996] 232.22439961 235.00377654 235.03183115 250.64528733 277.05701388
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3&gt; Dados (Terceiro tipo) &lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;## 
## Tabela de frequência 
## Tipo de variável: continuous
## 
##                Classes  Fi     PM   Fr Fac1 Fac2 Fp Fac1p Fac2p
## 1  -62.31 |---  -38.91   2 -50.61 0.00    2 1000  0   0.2 100.0
## 2  -38.91 |---  -15.51   7 -27.21 0.01    9  998  1   0.9  99.8
## 3    -15.51 |---  7.89  21  -3.81 0.02   30  991  2   3.0  99.1
## 4     7.89 |---  31.29  59  19.59 0.06   89  970  6   8.9  97.0
## 5    31.29 |---  54.69  86  42.99 0.09  175  911  9  17.5  91.1
## 6    54.69 |---  78.09 147  66.39 0.15  322  825 15  32.2  82.5
## 7   78.09 |---  101.49 188  89.79 0.19  510  678 19  51.0  67.8
## 8  101.49 |---  124.89 156 113.19 0.16  666  490 16  66.6  49.0
## 9  124.89 |---  148.29 160 136.59 0.16  826  334 16  82.6  33.4
## 10 148.29 |---  171.69 114 159.99 0.11  940  174 11  94.0  17.4
## 11 171.69 |---  195.09  31 183.39 0.03  971   60  3  97.1   6.0
## 12 195.09 |---  218.49  19 206.79 0.02  990   29  2  99.0   2.9
## 13 218.49 |---  241.89   8 230.19 0.01  998   10  1  99.8   1.0
## 14 241.89 |---  265.29   1 253.59 0.00  999    2  0  99.9   0.2
## 15 265.29 |---  288.69   1 276.99 0.00 1000    1  0 100.0   0.1
## 
##  ============================================== 
## Classes: Agrupamento de classes 
## Fi: Frequência absoluta 
## PM: Ponto médio 
## Fr: Frequência relativa 
## Fac1: Frequência acumulada (abaixo de) 
## Fac2: Frequência acumulada (acima de) 
## Fp: Frequência percentual 
## Fac1p: Frequência acumulada percentual (abaixo de) 
## Fac2p: Frequência acumulada percentual (acima de)
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3&gt; Dados (Quarto tipo) &lt;/h3&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s01/index_files/figure-html/unnamed-chunk-4-1.png&#34; width=&#34;672&#34; /&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;coleta-dados-brutos&#34;&gt;Coleta (Dados brutos)&lt;/h2&gt;
&lt;p&gt;Dados elaborados sobre o número de erros encontrados em 20 conjunto de caracteres monitorado em um canal de comunicação&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:right&#34;&gt;3&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;0&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;3&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;4&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;3&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;2&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;3&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;0&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;2&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;3&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;2&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;2&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;dados-em-rol-ou-elaborados&#34;&gt;Dados em rol ou elaborados&lt;/h2&gt;
&lt;p&gt;Dados elaborados sobre o número de erros encontrados em 20 conjunto de caracteres monitorado em um canal de comunicação&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:right&#34;&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:right&#34;&gt;0&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;0&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;0&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:right&#34;&gt;2&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;2&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;2&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;2&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;3&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;3&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;3&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;3&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;3&lt;/td&gt;
&lt;td style=&#34;text-align:right&#34;&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;section&gt;
&lt;h2&gt; Distribuição de frequência &lt;/h2&gt;
&lt;h3&gt;Frequência absoluta&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:center&#34;&gt;Número de erros &lt;code&gt;\((x_i)\)&lt;/code&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;Frequência simples ($f_i$)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;0&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;1&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;2&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;3&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;4&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;Total&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;20&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h3&gt;Frequência relativa&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:center&#34;&gt;Número de erros &lt;code&gt;\((x_i)\)&lt;/code&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(f_i\)&lt;/code&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(f_{r_i}\)&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(3\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(3 / 20 = 0,15\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(1\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(7\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(7 / 20 = 0,35\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(2\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(4\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(4 / 20 = 0,20\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(3\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(5\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(5 / 20 = 0,25\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(4\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(1\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(1 / 20 = 0,05\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h3&gt;Frequência percentual&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:center&#34;&gt;Número de erros &lt;code&gt;\((x_i)\)&lt;/code&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(f_i\)&lt;/code&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(f_{r_i}\)&lt;/code&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(f_{\%_i}\)&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(3\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,15\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,15 \times 100 = 15\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(1\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(7\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,35\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,35 \times 100 = 35\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(2\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(4\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,20\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,20 \times 100 = 20\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(3\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(5\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,25\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,25 \times 100 = 25\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(4\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(1\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,05\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,05 \times 100 = 5\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;Total&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(20\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(1\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(100\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h3&gt;Tabela completa&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:center&#34;&gt;Número de erros &lt;code&gt;\((x_i)\)&lt;/code&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(f_i\)&lt;/code&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(f_{r_i}\)&lt;/code&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(f_{\%_i}\)&lt;/code&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(f_{ac\downarrow_i}\)&lt;/code&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(f_{ac\uparrow_i}\)&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(3\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,15\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(15\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(3\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(20\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(1\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(7\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,35\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(35\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(10\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(17\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(2\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(4\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,20\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(35\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(14\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(10\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(3\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(5\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,25\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(25\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(19\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(6\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(4\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(1\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(0,05\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(5\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(20\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(1\)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;Total&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(20\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(1\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;&lt;code&gt;\(100\)&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;section&gt;
&lt;h2&gt;Tabela para V. contínua (Algoritmo) &lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:center&#34;&gt;Classe&lt;/th&gt;
&lt;th style=&#34;text-align:center&#34;&gt;$ F_i $&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;$ Li_{1a} \vdash  Ls_{1a} $&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;$ f_1 $&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;$ Li_{2a} \vdash  Ls_{2a} $&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;$ f_2 $&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;$ \vdots $&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;$ \vdots $&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:center&#34;&gt;$ Li_{ka}  \vdash Ls_{ka} $&lt;/td&gt;
&lt;td style=&#34;text-align:center&#34;&gt;$ f_k $&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;pre&gt; 1º Passo - Número de classes &lt;/pre&gt;
&lt;p&gt;&lt;code&gt;\begin{align} k &amp;amp; \approx \left\{\begin{array}{ll} \sqrt{\textrm{número de elementos}}, &amp;amp; n \leq 100 \\ 5log_{10}(\textrm{número de elementos}), &amp;amp; n &amp;gt; 100 \end{array}\right. \end{align}&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt; 2º Passo - Amplitude total &lt;/pre&gt;
&lt;p&gt;&lt;code&gt;\begin{align} A_t &amp;amp; = \max_i(X_i) - \min_i(X_i), \end{align}&lt;/code&gt;
para &lt;code&gt;\(i \in \mathbb{N}^{+}\)&lt;/code&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;pre&gt; 3º Passo - Amplitude de classe &lt;/pre&gt;
&lt;p&gt;&lt;code&gt;\begin{align} c &amp;amp; = \left\{\begin{array}{ll} \frac{A_t}{k - 1}, &amp;amp; \textrm{Amostra} \\ \frac{A_t}{k}, &amp;amp; \textrm{População}. \end{array}\right. \end{align}&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt; 4º Passo - LI da primeira classe &lt;/pre&gt;
&lt;p&gt;&lt;code&gt;\begin{align} Li_{1a} &amp;amp; = \left\{\begin{array}{ll} X_{(1)} - c / 2, &amp;amp; \textrm{Amostra} \\ X_{(1)}, &amp;amp; \textrm{População}. \end{array}\right. \end{align}&lt;/code&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt; Em resumo... &lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Calcular &lt;code&gt;\(k\)&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;Calcular &lt;code&gt;\(A_t\)&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;Calcular &lt;code&gt;\(c\)&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;Calcular &lt;code&gt;\(Li_{1a}\)&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;Determinar as classes,&lt;/li&gt;
&lt;li&gt;Calcular o ponto médio, e&lt;/li&gt;
&lt;li&gt;Calcular as frequências como apresentadas no início dessa seção.&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h2 id=&#34;gráficos&#34;&gt;Gráficos&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Gráfico de Haste ou bastão&lt;/li&gt;
&lt;li&gt;Gráfico de barras&lt;/li&gt;
&lt;li&gt;Gráfico de Pizza&lt;/li&gt;
&lt;li&gt;Histograma de frequências&lt;/li&gt;
&lt;li&gt;Ogivas&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;section&gt;
&lt;h2&gt; Uso do pacote &lt;code&gt;leem&lt;/code&gt; &lt;/h2&gt;














&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/profmat-est/s01/leem_hu7b1031bcd7f556bee541df85c0c5375e_34750_3761f4b815fffe33ceb7dbc21c169f83.webp 400w,
               /slides/profmat-est/s01/leem_hu7b1031bcd7f556bee541df85c0c5375e_34750_3705f9ee693abc73a6049df605c75df5.webp 760w,
               /slides/profmat-est/s01/leem_hu7b1031bcd7f556bee541df85c0c5375e_34750_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/profmat-est/s01/leem_hu7b1031bcd7f556bee541df85c0c5375e_34750_3761f4b815fffe33ceb7dbc21c169f83.webp&#34;
               width=&#34;150&#34;
               height=&#34;150&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;p&gt;Instalação&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;install.packages(&amp;quot;devtools&amp;quot;)
devtools::install_github(&amp;quot;bendeivide/leem&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Anexando e carregando&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;library(leem)
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt; Funções &lt;/h2&gt;
&lt;!-- | Função     | Finalidade                  | --&gt;
&lt;!-- |:-----------|:----------------------------| --&gt;
&lt;!-- | new_leem() | Construtor da classe *leem* | --&gt;
&lt;!-- | tabfreq()  | Disatribuição de frequência | --&gt;
&lt;!-- | hist()     | Hitograma de frequência     | --&gt;
&lt;!-- | ogive()    | Ogivas                      | --&gt;
&lt;!-- | polyfreq() | Polígono de frequências     | --&gt;
&lt;style type=&#34;text/css&#34;&gt;
.tg  {border-collapse:collapse;border-color:#93a1a1;border-spacing:0;}
.tg td{background-color:#fdf6e3;border-bottom-width:1px;border-color:#93a1a1;border-style:solid;border-top-width:1px;
  border-width:0px;color:#002b36;font-family:Arial, sans-serif;font-size:14px;overflow:hidden;padding:10px 5px;
  word-break:normal;}
.tg th{background-color:#657b83;border-bottom-width:1px;border-color:#93a1a1;border-style:solid;border-top-width:1px;
  border-width:0px;color:#fdf6e3;font-family:Arial, sans-serif;font-size:14px;font-weight:normal;overflow:hidden;
  padding:10px 5px;word-break:normal;}
.tg .tg-5lw0{background-color:#eee8d5;border-color:#ffffff;
  font-family:&#34;Lucida Sans Unicode&#34;, &#34;Lucida Grande&#34;, sans-serif !important;font-size:28px;text-align:left;
  vertical-align:middle}
.tg .tg-xzvq{border-color:#ffffff;font-family:&#34;Lucida Sans Unicode&#34;, &#34;Lucida Grande&#34;, sans-serif !important;font-size:28px;
  text-align:left;vertical-align:middle}
.tg .tg-vqs5{border-color:#ffffff;font-family:&#34;Lucida Sans Unicode&#34;, &#34;Lucida Grande&#34;, sans-serif !important;font-size:28px;
  font-weight:bold;text-align:left;vertical-align:middle}
&lt;/style&gt;
&lt;table class=&#34;tg&#34;&gt;
&lt;thead&gt;
  &lt;tr&gt;
    &lt;th class=&#34;tg-vqs5&#34;&gt;Função&lt;/th&gt;
    &lt;th class=&#34;tg-vqs5&#34;&gt;Finalidade&lt;/th&gt;
  &lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
  &lt;tr&gt;
    &lt;td class=&#34;tg-5lw0&#34;&gt; &lt;code&gt;base::sort()&lt;/code&gt;  &lt;/td&gt;
    &lt;td class=&#34;tg-5lw0&#34;&gt;Dados em rol &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td class=&#34;tg-5lw0&#34;&gt; &lt;code&gt;new_leem()&lt;/code&gt;  &lt;/td&gt;
    &lt;td class=&#34;tg-5lw0&#34;&gt;Construtor da classe &lt;i&gt;leem&lt;/i&gt; &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td class=&#34;tg-xzvq&#34;&gt; &lt;code&gt;tabfreq()&lt;/code&gt;  &lt;/td&gt;
    &lt;td class=&#34;tg-xzvq&#34;&gt;Distribuição de frequência&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td class=&#34;tg-5lw0&#34;&gt; &lt;code&gt;hist()&lt;/code&gt; &lt;/td&gt;
    &lt;td class=&#34;tg-5lw0&#34;&gt;Hitograma de frequência&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td class=&#34;tg-xzvq&#34;&gt; &lt;code&gt;ogive()&lt;/code&gt; &lt;/td&gt;
    &lt;td class=&#34;tg-xzvq&#34;&gt;Ogivas&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td class=&#34;tg-5lw0&#34;&gt; &lt;code&gt;polyfreq()&lt;/code&gt; &lt;/td&gt;
    &lt;td class=&#34;tg-5lw0&#34;&gt;Polígono de frequências&lt;/td&gt;
  &lt;/tr&gt;
   &lt;tr&gt;
    &lt;td class=&#34;tg-5lw0&#34;&gt; &lt;code&gt;stickchart()&lt;/code&gt; &lt;/td&gt;
    &lt;td class=&#34;tg-5lw0&#34;&gt;Gráfico de hastes ou bastão&lt;/td&gt;
  &lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt; Exemplo &lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Considere a distribuição de frequência do número de erros encontrados em 20 conjunto de carac-  teres monitorado em um canal de comunicação&lt;/li&gt;
&lt;/ol&gt;
&lt;style type=&#34;text/css&#34;&gt;
.tg  {border-collapse:collapse;border-color:#93a1a1;border-spacing:0;}
.tg td{background-color:#fdf6e3;border-bottom-width:1px;border-color:#93a1a1;border-style:solid;border-top-width:1px;
  border-width:0px;color:#002b36;font-family:Arial, sans-serif;font-size:14px;overflow:hidden;padding:10px 5px;
  word-break:normal;}
.tg th{background-color:#657b83;border-bottom-width:1px;border-color:#93a1a1;border-style:solid;border-top-width:1px;
  border-width:0px;color:#fdf6e3;font-family:Arial, sans-serif;font-size:14px;font-weight:normal;overflow:hidden;
  padding:10px 5px;word-break:normal;}
.tg .tg-j4p1{background-color:#eee8d5;color:#191919;font-family:&#34;Lucida Sans Unicode&#34;, &#34;Lucida Grande&#34;, sans-serif !important;
  font-size:28px;font-style:italic;font-weight:bold;text-align:right;vertical-align:middle}
.tg .tg-1bo1{background-color:#ffffff;border-color:#fdf6e3;
  font-family:&#34;Lucida Sans Unicode&#34;, &#34;Lucida Grande&#34;, sans-serif !important;font-size:28px;font-style:italic;
  font-weight:bold;text-align:right;vertical-align:middle}
&lt;/style&gt;
&lt;table class=&#34;tg&#34;&gt;
&lt;thead&gt;
  &lt;tr&gt;
    &lt;th class=&#34;tg-j4p1&#34;&gt;&lt;span style=&#34;font-weight:700&#34;&gt;3&lt;/span&gt;&lt;/th&gt;
    &lt;th class=&#34;tg-j4p1&#34;&gt;&lt;span style=&#34;font-weight:700&#34;&gt;0&lt;/span&gt;&lt;/th&gt;
    &lt;th class=&#34;tg-j4p1&#34;&gt;&lt;span style=&#34;font-weight:700&#34;&gt;3&lt;/span&gt;&lt;/th&gt;
    &lt;th class=&#34;tg-j4p1&#34;&gt;&lt;span style=&#34;font-weight:700&#34;&gt;4&lt;/span&gt;&lt;/th&gt;
    &lt;th class=&#34;tg-j4p1&#34;&gt;&lt;span style=&#34;font-weight:700&#34;&gt;3&lt;/span&gt;&lt;/th&gt;
    &lt;th class=&#34;tg-j4p1&#34;&gt;&lt;span style=&#34;font-weight:700&#34;&gt;1&lt;/span&gt;&lt;/th&gt;
    &lt;th class=&#34;tg-j4p1&#34;&gt;&lt;span style=&#34;font-weight:700&#34;&gt;2&lt;/span&gt;&lt;/th&gt;
    &lt;th class=&#34;tg-j4p1&#34;&gt;&lt;span style=&#34;font-weight:700&#34;&gt;3&lt;/span&gt;&lt;/th&gt;
    &lt;th class=&#34;tg-j4p1&#34;&gt;&lt;span style=&#34;font-weight:700&#34;&gt;0&lt;/span&gt;&lt;/th&gt;
    &lt;th class=&#34;tg-j4p1&#34;&gt;&lt;span style=&#34;font-weight:700&#34;&gt;0&lt;/span&gt;&lt;/th&gt;
  &lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
  &lt;tr&gt;
    &lt;td class=&#34;tg-1bo1&#34;&gt;1&lt;/td&gt;
    &lt;td class=&#34;tg-1bo1&#34;&gt;1&lt;/td&gt;
    &lt;td class=&#34;tg-1bo1&#34;&gt;2&lt;/td&gt;
    &lt;td class=&#34;tg-1bo1&#34;&gt;1&lt;/td&gt;
    &lt;td class=&#34;tg-1bo1&#34;&gt;1&lt;/td&gt;
    &lt;td class=&#34;tg-1bo1&#34;&gt;1&lt;/td&gt;
    &lt;td class=&#34;tg-1bo1&#34;&gt;3&lt;/td&gt;
    &lt;td class=&#34;tg-1bo1&#34;&gt;2&lt;/td&gt;
    &lt;td class=&#34;tg-1bo1&#34;&gt;2&lt;/td&gt;
    &lt;td class=&#34;tg-1bo1&#34;&gt;1&lt;/td&gt;
  &lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Exemplo&lt;/h2&gt;
&lt;ol start=&#34;2&#34;&gt;
&lt;li&gt;Os dados representam a temperatura (°F) do anel de vedação de cada teste de acionamento ou lançamento real do motor do foguete Challenger.&lt;/li&gt;
&lt;/ol&gt;
&lt;style type=&#34;text/css&#34;&gt;
.tg  {border-collapse:collapse;border-color:#93a1a1;border-spacing:0;}
.tg td{background-color:#fdf6e3;border-bottom-width:1px;border-color:#93a1a1;border-style:solid;border-top-width:1px;
  border-width:0px;color:#002b36;font-family:Arial, sans-serif;font-size:14px;overflow:hidden;padding:10px 5px;
  word-break:normal;}
.tg th{background-color:#657b83;border-bottom-width:1px;border-color:#93a1a1;border-style:solid;border-top-width:1px;
  border-width:0px;color:#fdf6e3;font-family:Arial, sans-serif;font-size:14px;font-weight:normal;overflow:hidden;
  padding:10px 5px;word-break:normal;}
.tg .tg-61io{background-color:#eee8d5;color:#191919;font-size:28px;font-style:italic;font-weight:bold;text-align:left;
  vertical-align:middle}
.tg .tg-8svn{background-color:#fdf6e3;color:#191919;font-size:28px;font-style:italic;font-weight:bold;text-align:left;
  vertical-align:middle}
.tg .tg-aete{background-color:#fdf6e3;color:#191919;font-family:&#34;Lucida Sans Unicode&#34;, &#34;Lucida Grande&#34;, sans-serif !important;
  font-size:28px;font-style:italic;font-weight:bold;text-align:left;vertical-align:middle}
.tg .tg-4ynv{background-color:#eee8d5;color:#191919;font-family:&#34;Lucida Sans Unicode&#34;, &#34;Lucida Grande&#34;, sans-serif !important;
  font-size:28px;font-style:italic;font-weight:bold;text-align:left;vertical-align:middle}
.tg .tg-uika{color:#191919;font-size:28px;font-style:italic;font-weight:bold;text-align:left;vertical-align:middle}
&lt;/style&gt;
&lt;table class=&#34;tg&#34;&gt;
&lt;thead&gt;
  &lt;tr&gt;
    &lt;th class=&#34;tg-aete&#34;&gt;84&lt;/th&gt;
    &lt;th class=&#34;tg-aete&#34;&gt;49&lt;/th&gt;
    &lt;th class=&#34;tg-aete&#34;&gt;61&lt;/th&gt;
    &lt;th class=&#34;tg-aete&#34;&gt;40&lt;/th&gt;
    &lt;th class=&#34;tg-aete&#34;&gt;83&lt;/th&gt;
    &lt;th class=&#34;tg-aete&#34;&gt;67&lt;/th&gt;
    &lt;th class=&#34;tg-aete&#34;&gt;45&lt;/th&gt;
    &lt;th class=&#34;tg-aete&#34;&gt;66&lt;/th&gt;
    &lt;th class=&#34;tg-aete&#34;&gt;70&lt;/th&gt;
    &lt;th class=&#34;tg-aete&#34;&gt;69&lt;/th&gt;
    &lt;th class=&#34;tg-8svn&#34;&gt;80&lt;/th&gt;
    &lt;th class=&#34;tg-8svn&#34;&gt;58&lt;/th&gt;
  &lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
  &lt;tr&gt;
    &lt;td class=&#34;tg-4ynv&#34;&gt;68&lt;/td&gt;
    &lt;td class=&#34;tg-4ynv&#34;&gt;60&lt;/td&gt;
    &lt;td class=&#34;tg-4ynv&#34;&gt;67&lt;/td&gt;
    &lt;td class=&#34;tg-4ynv&#34;&gt;72&lt;/td&gt;
    &lt;td class=&#34;tg-4ynv&#34;&gt;73&lt;/td&gt;
    &lt;td class=&#34;tg-4ynv&#34;&gt;70&lt;/td&gt;
    &lt;td class=&#34;tg-4ynv&#34;&gt;57&lt;/td&gt;
    &lt;td class=&#34;tg-4ynv&#34;&gt;63&lt;/td&gt;
    &lt;td class=&#34;tg-4ynv&#34;&gt;70&lt;/td&gt;
    &lt;td class=&#34;tg-4ynv&#34;&gt;78&lt;/td&gt;
    &lt;td class=&#34;tg-61io&#34;&gt;52&lt;/td&gt;
    &lt;td class=&#34;tg-61io&#34;&gt;67&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td class=&#34;tg-uika&#34;&gt;53&lt;/td&gt;
    &lt;td class=&#34;tg-uika&#34;&gt;67&lt;/td&gt;
    &lt;td class=&#34;tg-uika&#34;&gt;75&lt;/td&gt;
    &lt;td class=&#34;tg-uika&#34;&gt;61&lt;/td&gt;
    &lt;td class=&#34;tg-uika&#34;&gt;70&lt;/td&gt;
    &lt;td class=&#34;tg-uika&#34;&gt;81&lt;/td&gt;
    &lt;td class=&#34;tg-uika&#34;&gt;76&lt;/td&gt;
    &lt;td class=&#34;tg-uika&#34;&gt;79&lt;/td&gt;
    &lt;td class=&#34;tg-uika&#34;&gt;75&lt;/td&gt;
    &lt;td class=&#34;tg-uika&#34;&gt;76&lt;/td&gt;
    &lt;td class=&#34;tg-uika&#34;&gt;58&lt;/td&gt;
    &lt;td class=&#34;tg-uika&#34;&gt;31&lt;/td&gt;
  &lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;style&gt;
.container{
  display: grid;
  text-align: center;
  grid-auto-flow: column;
}
.col {
  width: 500px;
  height: 400px;
  border: 3px solid #0094ff;
}
.col2 {
  width: 500px;
  height: 500px;
  border: 3px solid #0094ff;
}
.col3 {
  width: 500px;
  height: 450px;
  border: 3px solid #0094ff;
}

&lt;/style&gt;
&lt;section&gt;
&lt;h1&gt; &lt;code&gt;leem&lt;/code&gt; em ação &lt;/h1&gt;
&lt;hr&gt;
&lt;h2&gt; Importando os dados &lt;/h2&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;# Numero de erros
d1 &amp;lt;- read.table(&amp;quot;https://raw.githubusercontent.com/bendeivide/book-epaec/master/dados/cap02/nerros.txt&amp;quot;, h = TRUE)
(d1 &amp;lt;- d1$erros)

# Temperatura do foguete Challenger
d2 &amp;lt;- read.table(&amp;quot;https://raw.githubusercontent.com/bendeivide/book-epaec/master/dados/cap02/challenger.txt&amp;quot;, h = TRUE)
(d2 &amp;lt;- d2$chal)

&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;pre&gt;&lt;code&gt;##  [1] 3 1 0 1 3 2 4 1 3 1 1 1 2 3 3 2 0 2 0 1
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;##  [1] 84 49 61 40 83 67 45 66 70 69 80 58 68 60 67 72 73 70 57 63 70 78 52 67 53
## [26] 67 75 61 70 81 76 79 75 76 58 31
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h2&gt; Dados em rol &lt;/h2&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;sort(d1)
sort(d2)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;pre&gt;&lt;code&gt;##  [1] 0 0 0 1 1 1 1 1 1 1 2 2 2 2 3 3 3 3 3 4
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;##  [1] 31 40 45 49 52 53 57 58 58 60 61 61 63 66 67 67 67 67 68 69 70 70 70 70 72
## [26] 73 75 75 76 76 78 79 80 81 83 84
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h2&gt; Distribuição de frequências &lt;/h2&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col2&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;## Forma convencional:
aux &amp;lt;- new_leem(d1, 1)
tabd1 &amp;lt;- tabfreq(aux); tabd1
#-----
aux &amp;lt;- new_leem(d2, 2)
tabd2 &amp;lt;- tabfreq(aux); tabd2
## Usando o operador &#39;pipe&#39; nativo
d1 |&amp;gt; new_leem(variable = 1) |&amp;gt; tabfreq()
d2 |&amp;gt; new_leem(variable = 2) |&amp;gt; tabfreq()
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col2&#34;&gt;
&lt;pre&gt;&lt;code&gt;## 
## Tabela de frequência 
## Tipo de variável: discrete
## 
##   Groups Fi   Fr Fac1 Fac2 Fp Fac1p Fac2p
## 1      0  3 0.15    3   20 15    15   100
## 2      1  7 0.35   10   17 35    50    85
## 3      2  4 0.20   14   10 20    70    50
## 4      3  5 0.25   19    6 25    95    30
## 5      4  1 0.05   20    1  5   100     5
## ============================================== 
## Groups: Agrupamento discretizado 
## Fi: Frequência absoluta 
## Fr: Frequência relativa 
## Fac1: Frequência acumulada (abaixo de) 
## Fac2: Frequência acumulada (acima de) 
## Fp: Frequência percentual 
## Fac1p: Frequência acumulada percentual (abaixo de) 
## Fac2p: Frequência acumulada percentual (acima de)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## 
## Tabela de frequência 
## Tipo de variável: continuous
## 
##           Classes Fi   PM   Fr Fac1 Fac2 Fp  Fac1p  Fac2p
## 1 25.7 |---  36.3  1 31.0 0.03    1   36  3   2.78 100.00
## 2 36.3 |---  46.9  2 41.6 0.06    3   35  6   8.33  97.22
## 3 46.9 |---  57.5  4 52.2 0.11    7   33 11  19.44  91.67
## 4 57.5 |---  68.1 12 62.8 0.33   19   29 33  52.78  80.56
## 5 68.1 |---  78.7 12 73.4 0.33   31   17 33  86.11  47.22
## 6 78.7 |---  89.3  5 84.0 0.14   36    5 14 100.00  13.89
## 
##  ============================================== 
## Classes: Agrupamento de classes 
## Fi: Frequência absoluta 
## PM: Ponto médio 
## Fr: Frequência relativa 
## Fac1: Frequência acumulada (abaixo de) 
## Fac2: Frequência acumulada (acima de) 
## Fp: Frequência percentual 
## Fac1p: Frequência acumulada percentual (abaixo de) 
## Fac2p: Frequência acumulada percentual (acima de)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h2&gt; Apresentação gráfica &lt;/h2&gt;
&lt;h3&gt;Gráfico de hastes ou bastão&lt;/h3&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;# Forma convencional:
aux1 &amp;lt;- new_leem(d1, variable = &amp;quot;discrete&amp;quot;)
aux2 &amp;lt;- tabfreq(aux1)
stickchart(aux2,
          lwd=3, # largura da linha
          pcol = &amp;quot;red&amp;quot;, # cor da linha
          bgcol = &amp;quot;lightgray&amp;quot;, # cor do fundo
          panel.first = grid(col = &amp;quot;white&amp;quot;) # inserindo grid e sua cor
         )
# Usando o pipe
d1 |&amp;gt;
  new_leem(variable = &amp;quot;discrete&amp;quot;) |&amp;gt;
  tabfreq() |&amp;gt;
  stickchart(lwd=3, # largura da linha
            pcol = &amp;quot;red&amp;quot;, # cor da linha
            bgcol = &amp;quot;lightgray&amp;quot;, # cor do fundo
            panel.first = grid(col = &amp;quot;white&amp;quot;) # inserindo grid e sua cor
            )
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s01/index_files/figure-html/unnamed-chunk-11-1.png&#34; width=&#34;672&#34; /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h3&gt;Gráfico de barras&lt;/h3&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;# Forma convencional:
aux1 &amp;lt;- new_leem(d1, variable = 1)
aux2 &amp;lt;- tabfreq(aux1)
barplot(aux2, barcol = heat.colors(5))
# Usando o pipe
d1 |&amp;gt;
  new_leem(variable = 1) |&amp;gt;
    tabfreq() |&amp;gt;
      barplot(barcol = heat.colors(5))
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s01/index_files/figure-html/unnamed-chunk-12-1.png&#34; width=&#34;672&#34; /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h3&gt;Histograma de frequências&lt;/h3&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;# Usando o pipe:
d2 |&amp;gt;
  new_leem(variable = 2) |&amp;gt;
    tabfreq() |&amp;gt;
      hist(barcol = heat.colors(6))
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col&#34;&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s01/index_files/figure-html/unnamed-chunk-13-1.png&#34; width=&#34;672&#34; /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h3&gt;Polígono&lt;/h3&gt;
&lt;h4&gt;Dados discretos&lt;/h4&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;# Usando o pipe:
d1 |&amp;gt;
  new_leem(variable = 1) |&amp;gt;
    tabfreq() |&amp;gt;
      polyfreq(barcol = heat.colors(5),
           main = &amp;quot;Polígono de frequências e
Histograma de frequências&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s01/index_files/figure-html/unnamed-chunk-14-1.png&#34; width=&#34;672&#34; /&gt;
&lt;pre&gt;&lt;code&gt;## 
##  Note: The polygon graph has interpretation problems for the discrete quantitative variable
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h3&gt;Polígono&lt;/h3&gt;
&lt;h4&gt;Dados contínuos&lt;/h4&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;# Usando o pipe:
d2 |&amp;gt;
  new_leem(variable = 2) |&amp;gt;
    tabfreq() |&amp;gt;
      polyfreq(barcol = heat.colors(5),
           main = &amp;quot;Polígono de frequências e
Histograma de frequências&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s01/index_files/figure-html/unnamed-chunk-15-1.png&#34; width=&#34;672&#34; /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h3&gt;Polígono&lt;/h3&gt;
&lt;h4&gt;Sem as barras&lt;/h4&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;# Usando o pipe:
d2 |&amp;gt;
  new_leem(variable = 2) |&amp;gt;
    tabfreq() |&amp;gt;
      polyfreq(bars = FALSE)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s01/index_files/figure-html/unnamed-chunk-16-1.png&#34; width=&#34;672&#34; /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h3&gt;Ogivas&lt;/h3&gt;
&lt;h4&gt;Dados discretos (Crescente)&lt;/h4&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;# Usando o pipe:
d1 |&amp;gt;
  new_leem(variable = 1) |&amp;gt;
    tabfreq() |&amp;gt;
      ogive(bars = TRUE, barcol = &amp;quot;red&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s01/index_files/figure-html/unnamed-chunk-17-1.png&#34; width=&#34;672&#34; /&gt;
&lt;pre&gt;&lt;code&gt;## 
##  Note: The ogive graph has interpretation problems for the discrete quantitative variable
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h3&gt;Ogivas&lt;/h3&gt;
&lt;h4&gt;Dados discretos (Decrescente)&lt;/h4&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;d1 |&amp;gt;
  new_leem(variable = 1) |&amp;gt;
   tabfreq() |&amp;gt;
    ogive(decreasing = TRUE,
        bars = TRUE, barcol = &amp;quot;yellow&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s01/index_files/figure-html/unnamed-chunk-18-1.png&#34; width=&#34;672&#34; /&gt;
&lt;pre&gt;&lt;code&gt;## 
##  Note: The ogive graph has interpretation problems for the discrete quantitative variable
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h3&gt;Ogivas&lt;/h3&gt;
&lt;h4&gt;Dados discretos (Ambos)&lt;/h4&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;d1 |&amp;gt;
  new_leem(variable = 1) |&amp;gt;
  tabfreq() |&amp;gt;
  ogive(both = TRUE, # ambas ogivas
        bars = TRUE, # barras
        barcol = c(&amp;quot;red&amp;quot;, &amp;quot;yellow&amp;quot;))
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s01/index_files/figure-html/unnamed-chunk-19-1.png&#34; width=&#34;672&#34; /&gt;
&lt;pre&gt;&lt;code&gt;## 
##  Note: The ogive graph has interpretation problems for the discrete quantitative variable
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h3&gt;Ogivas&lt;/h3&gt;
&lt;h4&gt;Dados contínuos (Crescente)&lt;/h4&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;d2 |&amp;gt;
  new_leem(variable = 2) |&amp;gt;
  tabfreq() |&amp;gt;
  ogive(bars = TRUE, barcol = &amp;quot;red&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s01/index_files/figure-html/unnamed-chunk-20-1.png&#34; width=&#34;672&#34; /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h3&gt;Ogivas&lt;/h3&gt;
&lt;h4&gt;Dados contínuos (Decrescente)&lt;/h4&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;d2 |&amp;gt;
  new_leem(variable = 2) |&amp;gt;
  tabfreq() |&amp;gt;
  ogive(decreasing = TRUE,
        bars = TRUE, barcol = &amp;quot;yellow&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s01/index_files/figure-html/unnamed-chunk-21-1.png&#34; width=&#34;672&#34; /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h3&gt;Ogivas&lt;/h3&gt;
&lt;h4&gt;Dados contínuos (Ambos)&lt;/h4&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;d2 |&amp;gt;
  new_leem(variable = 2) |&amp;gt;
  tabfreq() |&amp;gt;
  ogive(both = TRUE, # ambas ogivas
        bars = TRUE, # barras
        barcol = c(&amp;quot;red&amp;quot;, &amp;quot;yellow&amp;quot;))
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s01/index_files/figure-html/unnamed-chunk-22-1.png&#34; width=&#34;672&#34; /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h3&gt;Ogivas&lt;/h3&gt;
&lt;h4&gt;Dados contínuos (Ambos + Histograma)&lt;/h4&gt;
&lt;div class=&#34;container&#34;&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;pre&gt;&lt;code class=&#34;language-r&#34;&gt;d2 |&amp;gt;
  new_leem(variable = 2) |&amp;gt;
  tabfreq() |&amp;gt;
  ogive(both = TRUE, # ambas ogivas
        bars = TRUE, # barras
        barcol = c(&amp;quot;red&amp;quot;, &amp;quot;yellow&amp;quot;), # cor da barra das duas ogivas
        histogram = TRUE, # incluindo o histograma
        histcol = gray.colors(6), # cor do histograma
        bgcol = &amp;quot;purple&amp;quot;) # cor do fundo
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&#34;col3&#34;&gt;
&lt;img src=&#34;http://bendeivide.github.io/slides/profmat-est/s01/index_files/figure-html/unnamed-chunk-23-1.png&#34; width=&#34;672&#34; /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/section&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;h1 id=&#34;questões&#34;&gt;Questões?&lt;/h1&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Dúvidas e Sugestões&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://bendeivide.github.io/#contact&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Contato&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;

&lt;section data-noprocess data-shortcode-slide
  
      
      data-background-image=&#34;cap02.png&#34;
  &gt;

&lt;!-- https://revealjs.com/transitions/ --&gt;
&lt;section data-transition=&#34;zoom&#34;&gt;
  &lt;h1&gt;Próximas aulas...&lt;/h1&gt;
&lt;/section&gt;
&lt;section data-transition-speed=&#34;fast&#34;&gt;
&lt;a href=&#34;http://bendeivide.github.io/courses/epaec&#34; target=&#34;_blank&#34;&gt;














&lt;figure  &gt;
  &lt;div class=&#34;d-flex justify-content-center&#34;&gt;
    &lt;div class=&#34;w-100&#34; &gt;&lt;img alt=&#34;&#34; srcset=&#34;
               /slides/profmat-est/s01/ben_hu087225affb9399e037f09661c4d0adbd_219224_5c10d459c8ddc0416f506a4ad838a085.webp 400w,
               /slides/profmat-est/s01/ben_hu087225affb9399e037f09661c4d0adbd_219224_29ebba9a3e515b23ea411bffea18d2f1.webp 760w,
               /slides/profmat-est/s01/ben_hu087225affb9399e037f09661c4d0adbd_219224_1200x1200_fit_q75_h2_lanczos_3.webp 1200w&#34;
               src=&#34;http://bendeivide.github.io/slides/profmat-est/s01/ben_hu087225affb9399e037f09661c4d0adbd_219224_5c10d459c8ddc0416f506a4ad838a085.webp&#34;
               width=&#34;630&#34;
               height=&#34;480&#34;
               loading=&#34;lazy&#34; data-zoomable /&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;/figure&gt;
&lt;/a&gt;
&lt;p&gt;&lt;a href=&#34;http://bendeivide.github.io/courses/epaec&#34; target=&#34;_blank&#34;&gt;bendeivide.github.io/courses/epaec&lt;/a&gt;&lt;/p&gt;
&lt;/section&gt;
&lt;!-- &lt;section&gt; --&gt;
&lt;!--   &lt;h2&gt;Some Slide&lt;/h2&gt; --&gt;
&lt;!--   &lt;aside class=&#34;notes&#34;&gt; --&gt;
&lt;!--     Anotações no Visualizador (Clique em S) 📝 --&gt;
&lt;!--   &lt;/aside&gt; --&gt;
&lt;!-- &lt;/section&gt; --&gt;
&lt;!-- ## Animação --&gt;
&lt;!-- &lt;section data-auto-animate&gt; --&gt;
&lt;!--   &lt;h1&gt;Auto-Animate&lt;/h1&gt; --&gt;
&lt;!-- &lt;/section&gt; --&gt;
&lt;!-- &lt;section data-auto-animate&gt; --&gt;
&lt;!--   &lt;h1 style=&#34;margin-top: 100px; color: red;&#34;&gt;Auto-Animate&lt;/h1&gt; --&gt;
&lt;!-- &lt;/section&gt; --&gt;
</description>
    </item>
    
  </channel>
</rss>
