12  HTML, CSS e JavaScript

Um dos pontos fortes do Shiny é nos permitir construir aplicações web sem precisarmos saber programar em HTML, CSS e JavaScript. Com as funções disponíveis no pacote shiny e nos diversos pacotes feitos pela comunidade Shiny, já conseguimos produzir aplicativos complexos e bonitos.

No entanto, conhecer mesmo o básico dessas linguagens nos permite ir além do que existe nos pacotes disponíveis e customizar nossos apps da maneira que quisermos. Também nos permite entender melhor como o Shiny funciona, o que facilita a tarefa de programar os nossos apps.

Neste capítulo, vamos apresentar os conceitos básicos de HTML e CSS mais importantes para o Shiny, criando uma boa base para continuar aprendendo essas linguagens posteriormente. Também mostraremos como inserir códigos JavaScript em nossos apps a partir de alguns exemplos, mas não faremos uma introdução formal dessa linguagem aqui.

12.1 HTML

O HTML é uma linguagem de marcação para construir páginas web. Uma linguagem de marcação é apenas um tipo de documento que contem texto simples (como em um bloco de notas) e um conjunto de instruções para formatar (anotar, marcar) parte específicas do conteúdo. Além do HTML, o LaTeX e o (R) Markdown são outros exemplos comuns de linguagem de marcação.

Nas seções a seguir, apresentamos os conceitos básicos da linguagem. São três os objetivos aqui:

  • entender como um documento HTML é estruturado;

  • ganhar um pouco de vocabulário, isto é, conhecer as principais tags;

  • e conhecer a nomenclatura da linguagem, o que vai facilitar bastante quando for preciso pesquisar por algo na internet.

Tags

A maior parte do esforço em aprender uma linguagem de marcação está em aprender quais são e como utilizar as instruções de formatação, os seus marcadores. Os marcadores no HTML são as tags. Elas podem ser de abertura ou de fechamento e possuem a seguinte sintaxe:

Tag de abertura: <nome_da_tag>

Tag de fechamento: </nome_da_tag>

Elemento HTML

As tags no HTML definem os chamados elementos HTML. Um elemento HTML é composto por uma tag de abertura, algum conteúdo e uma tag de fechamento.

<nome_da_tag> conteúdo </nome_da_tag>

Alguns elementos podem aparecer corretamente sem a tag de fechamento, mas não conte sempre com isso. Resultados inexperados e erros podem acontecer se você esquercar a tag de fechamento.

Documento HTML

Um documento HTML é um arquivo de texto com extensão .html que possui um código HTML válido dentro. Todo HTML precisa começar com uma declaração de tipo

<!DOCTYPE html>

Ela representa o tipo de documento, o que ajuda os navegarores a mostrar as páginas corretamente. Ela deve aparecer apenas uma vez, no topo da página.

O código HTML em si começa com a tag <html> e deve terminar com </html>.

A parte visível do documento fica entre as tags <body> e </body>.

<!DOCTYPE html>

<html>
  <body>
    O conteúdo da página fica aqui.
  </body>
</html>

Importante: só pode haver apenas um <body> em um documento HTML.

A tag <head>

A tag <head> cria uma seção de metadados para a nossa página HTML.

O elemento <title>, por exemplo, pode ser utilizado para definir um título para a página, usado pelo navegador (na aba da página ou na barra de favoritos) e por algoritmos de busca (Google).

<html>
  <head>
    <title>Esse é o título da página</title>
  </head>
  <body>
    O conteúdo da página fica aqui.
  </body>
</html>

Veremos ainda neste capítulo outros metadados que podemos definir na seção <head>.

Cabeçalhos

Você pode construir títulos e subtítulos com as tags <h1> a <h6>

<h1>Título 1</h1>
<h2>Título 2</h2>
<h3>Título 3</h3>
<h4>Título 4</h4>
<h5>Título 5</h5>
<h6>Título 6</h6>

<h1> define o título mais importante, enquanto <h6> o menos importante.

É uma boa prática colocar apenas um <h1> por página HTML.

Parágrafos

Parágrafos são definidos pela tag <p>. Eles sempre iniciam em uma nova linha. Os navegadores automaticamente criam um espaço em branco (margem) antes e depois do parágrafo.

<p>
  Isto é um parágrafo.
</p>
<p>
  E aqui um outro parágrafo.
</p>

O HTML não é sensível à caixa das palavras, isto é, <P> e <p> são equivalentes. No entanto, é uma boa prática utilizar sempre a caixa baixa.

Elementos aninhados

Elementos HTML se organizam de maneira hierárquica, isto é, os elementos são aninhados dentro de outros.

<!DOCTYPE html>
<html>
  <body>

    <h1>Título da página</h1>
    <p>Este é o primeiro <b>parágrafo</b> desta página HTML.</p>

  </body>
</html>

No código acima

  • o elemento <body> reside dentro do elemento html;
  • os elementos <h1> e <p> residem dentro do elemento body;
  • e o elemento <b>, que deixa o texto em negrito, reside dentro do elemento p.

Atributos

Todos os elementos HTML podem ter atributos, que provêm informação adicional sobre os elementos.

Atributos são sempre especificados na tag de abertura. Eles geralmente possuem a seguinte sintaxe nome="valor". Dois argumentos diferentes são separados por um espaço vazio.

<!DOCTYPE html>
  <html lang="pt-BR">
    <body>
      "Conteúdo da página"
    </body>
</html>

O atributo lang no elemento <html>, por exemplo, declara qual será o idioma utilizado na página1.

Comentários

Podemos adicionar comentários ao nosso código HTML a partir da seguinte sintaxe:

  • use <!-- para iniciar o comentário;

  • use --> para encerrar o comentário.

<p>Isto é um parágrafo</p>
<!-- Isto é um comentário e vai ser ignorado pelo navegador. -->
<p>Isto é um outro parágrafo</p>

Elementos vazios

Alguns elementos HTML não possuem conteúdo e, portanto, não precisam de uma tag de fechamento. Esses elementos são chamados de elementos vazios.

A tag <br>, que gera uma quebra de linha na página, é um exemplo de elemento vazio.

<p>Parágrafo 1</p>
<br>
<p>Parágrafo 2</p>

Veja que não precisamos fechar a tag <br> com uma tag </br>

Imagens

Imagens podem ser inseridas em uma página HTML a partir da tag <img>.

<img src = "caminho_ou_url_da_imagem" width = "100px" height = "100px" alt = "Essa é uma boa descrição da imagem">

No elemento acima:

  • o argumento src é utilizado para especificar o caminho ou URL da imagem

  • os argumentos width e height são utilizados para especificar o comprimento e altura da imagem;

  • especificar o comprimento e altura é importante pois o navegador reserva o espaço da imagem na tela, mantendo o layout da página, caso ela demore para ser carregada;

  • podemos usar o argumento alt para atribuir uma descrição à imagem, o que é utilizado por leitores de tela para descrever a imagem para pessoas com deficiência visual.

Elementos em bloco e em linha

Os elementos HTML podem ser divididos em dois tipos: elementos em bloco e elementos em linha.

Elementos em bloco sempre começam em uma nova linha e ocupam todo o comprimento da tela ou todo o comprimento que tiverem a disposão. Os navegadores automaticamente adicionam algum espaço (margem) antes e depois desses elementos.

Elementos em linha não iniciam uma nova linha. Esses elementos só ocupam o comprimento necessário para apresentar seu conteúdo na tela.

A tag <div>

A tag <div> é um elemento em bloco normalmente utilizada como um container para outros elementos HTML. Se você não atribuir nenhum atributo a ela, como comprimento ou altura, ela não gera nenhum efeito na página.

Normalmente aplicamos a ela atributos que vão definir o estilo de parte ou de todos os elementos que a <div> contém.

<div>
  <p>Um parágrafo</p>
  <a href="https://curso-r.com">Um link</a>
</div>

A tag <span>

A tag <span> é um elemento em linha utilizada como um container para outros elementos HTML. Se você não atribuir nenhum atributo a ela, como comprimento ou altura, ela não gera nenhum efeito na página.

Normalmente aplicamos a ela atributos que vão definir o estilo de parte ou de todos os elementos que a <div> contém.

<p>
  Como formatar uma única <span>palavra</span>?
</p>

12.2 CSS

CSS (Cascading Style Sheets) é uma linguagem de folha de estilo utilizada para formatar páginas Web. Com CSS, podemos controlar a cor, fonte, tamanho do texto, espaçamento entre elementos, cores e imagens de fundo, a maneira como os elementos são mostrados na página a depender dos diferentes tamanhos de tela e muito mais!

O objetivo de uma linguagens de folha de estilo é separar a formatação e a estrutura de um documento, permitindo que sejam construídos isoladamente, mas os unindo a partir de algum tipo de ligação. Veremos adiante como isso se dá no HTML.

A palavra Cascading (cascata) significa que um estilo aplicado a um elemento pai também é aplicado a todos os elementos filhos, o que é uma característica importante devido à hierarquia de elementos do HTML.

A seguir, apresentaremos os conceitos básicos para aplicar CSS a um documento HTML.

Regras CSS

Para aplicar estilo a um elemento HTML usando CSS, devemos escrever uma regra. A seguir, temos uma regra CSS que define a cor dos parágrafos (o conteúdo dos elementos <p>) como azul e o tamanho da fonte como 12px.

p {
  color: blue;
  font-size: 12px
}

No código:

  • p é chamado de seletor e define quais elementos receberão a regra CSS;

  • color: blue; e font-size: 12px são chamadas de declarações e definem o estilo a ser aplicado;

  • color e font-size dentro de cada declaração são chamados de propriedades, isto é, a característica de cada elemento que será alterada;

  • blue e 12px são os valores atribuídos a cada propriedade.

Para aplicar essa regra, podemos inserir esse código em um documento HTML de 3 maneiras:

  • em linha (inline), dentro do elemento HTML, usando o atributo style;

  • interno (internal), dentro do documento HTML, mas fora dos elementos, usando a tag <style> dentro da seção <head>;

  • externo (external), em um arquivo externo, usando a tag <link> na seção <head> para apontar para um arquivo CSS.

O jeito mais comum de adicionar CSS ao HTML é utilizando um arquivo CSS externo, mas veremos aqui como utilizar as três formas.

CSS inline

O CSS inline é utilizado para aplicar estilo a um único elemento HTML. Fazemos isso usando o atributo style dentro da tag de abertura do elemento.

<p style = "color: blue;"> Esse texto terá a cor azul. </p>

Veja que nesse caso não precisamos declarar um seletor.

CSS interno

Um CSS interno é utilizado para definir estilo para os elementos de uma única página HTML. Ele é definido na seção <head>, dentro de uma tag <style>.

<html>
  <head>
    <style>
        h1 {
          color: red;
        }
        p {
          color: blue;
        }
    </style>
  </head>
  <body>
    <h1> Esse título terá a cor vermelha </h1>
    <p> Esse texto terá a cor azul </p>
  </body>
</html>

CSS externo

Um arquivo CSS externo é utilizado para definir o estilo de várias páginas HTML. Para associar um arquivo CSS a uma página HTML, usamos a tag <link> na seção <head>.

A tag <link> é utilizada para estabelecer uma relação entre o arquivo HTML e um arquivo externo. O atributo href recebe o caminho para o arquivo externo (nosso arquivo CSS) e o atributo rel estabele qual o tipo de relação entre os arquivos. No caso de um arquivo CSS, rel deve receber o valor stylesheet.

<!--Arquivo CSS-->
h1 {
  color: red;
}

<!--Arquivo HTML-->>
<html>
  <head>
    <link rel="stylesheet" href="custom.css">
  </head>
</html>

Cores

Para alterar cores, utilizamos as propriedades color e background-color. Você pode passar como valor tanto o nome da cor em inglês quanto um código hexadecimal.

p {
  color: white;
}

h1, h2 {
  color: #1222bb;
}

body {
  background-color: black;
}

Repare que você pode selecionar um grupo de elementos separando cada seletor por uma vírgula (h1, h2).

Tamanho da fonte

Para alterar o tamanho da fonte, utilizamos a propriedade font-size.

p {
  font-size: 10px;
}

h1 {
  font-size: 12pt;
}

Fontes

Para alterar a fonte do texto, utilizamos a propriedade font-family.

p {
  font-family: "Times New Roman", Times, serif;
}

p {
  font-family: Arial, Helvetica, sans-serif;
}

Você pode especificar mais de uma fonte em uma declaração, o que é útil para garantir que pelo menos uma das fontes especificadas esteja instalada no navegador de quem acessar a página HTML. A preferência é da esquerda para a direita. Na primeira regra do exemplo acima, o navegador tentará aplicar a fonte “Times New Roman” preferencialmente. Se ela não estiver disponível, ela vai aplicar qualquer versão da fonte “Times” e, caso ainda não seja possível, será utilizada qualquer fonte serifada que o navegador usar como padrão. Leia as seções sobre fonte do W3Schools para saber mais.

Para importar uma fonte do Google fontes, basta utilizar o elemento <link rel = "stylesheet"> passando o link da fonte no atributo href.

<head>
  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Sofia">
  <style>
  body {
    font-family: "Sofia", sans-serif;
  }
  </style>
</head>

Link para a fonte Sofia: https://fonts.google.com/specimen/Sofia?query=sofia

Bordas

Para definir uma borda a um elemento, utilizamos a propriedade border.

h1 {
  border: 1px solid black;
}
  • O valor 1px se refere à espessura da borda.

  • O valor solid se refere ao estilo da borda.

  • O valor black se refere à cor da borda.

Você pode definir uma borda para quase todos os elementos HTML.

Classes

Elementos HTML possuem um atributo class que pode ser utilizado como seletor em declarações CSS.

<!-- HTML -->
<p class = "azul">Este parágrafo ficará azul</p>
<p>Este parágrafo não ficará azul</p>

<!-- CSS -->
.azul {
  color: blue;
}

Repare que para usar uma classe como seletor, colocamos um . antes do nome da classe.

Elementos HTML podem ter mais de uma classe. Múltiplas classes são separadas por um espaço. Uma mesma classe pode ser utilizada em mais de um elemento HTML.

Ids

Elementos HTML possuem um atributo id que pode ser utilizado como seletor em declarações CSS. Ao contrário das classes, o id deve ser único dentro do documento HTML, isto é, dois elementos HTML não devem ter o mesmo id.

<!-- HTML -->
<p id = "paragrafoAzul">Este parágrafo ficará azul</p>
<p>Este parágrafo não ficará azul</p>

<!-- CSS -->
#paragrafoAzul {
  color: blue;
}

Repare que para usar um id como seletor, colocamos um # antes do nome do id.

Especificidade

Quando mais de uma declaração afeta uma mesma propriedade um elemento HTML, o navegador precisa decidir qual delas será aplicada. Para isso, ele vai se basear nos seguintes valores:

  1. Se o estilo é inline: +1000
  2. Se o seletor é um id: +100
  3. Se o seletor é uma classe: +10
  4. Se o seletor é um elemento: +1

A soma desses valores para uma regra é chamada de especificidade. A regra com maior especificidade será aplicada. Se duas declarações possuirem a mesma especificidade, a última declaração definida no CSS será priorizada.

A regra a seguir, que seleciona todos os elementos p com classe azul tem especificidade 11, pois o seletor possui uma classe e um elemento.

p.azul {
  color: blue;
}

Já a seguinte regra tem especificidade de 10, pois só possui um elemento, e seria preterida com relação à anterior.

p {
  color: blue;
}

Abaixo, temos duas declarações com a mesma especificidade. Nesse caso, a declaração color: yellow; será aplicada por ter sido definido por último.

p {
  color: red;
}

p {
  color: yellow;
}

Saiba mais sobre especificidade neste artigo da W3Schools em inglês ou neste artigo em português.

Box model

O box model do CSS é essencialmente uma caixa que envolve todos os elementos HTML. Ele consiste de uma margem, uma borda, padding e o próprio conteúdo do elemento.

A imagem abaixo ilustra o box model:

Margem

Margens são utilizadas para criar espaço em branco entre elementos HTML. As duas regras CSS a seguir são equivalentes.

p {
  margin: 1px 2px 4px 3px;
}

p {
  margin-top: 1px;
  margin-right: 2px;
  margin-bottom: 4px;
  margin-left: 3px;
}

Padding

A propriedade padding é utilizada para criar espaço ao redor do conteúdo de um elemento, dentro de qualquer borda definida. As duas regras CSS a seguir são equivalentes.

p {
  padding: 1px 2px 4px 3px;
}

p {
  padding-top: 1px;
  padding-right: 2px;
  padding-bottom: 4px;
  padding-left: 3px;
}

Display

A propriedade display especifica se e como um elemento HTML é exibido na tela.

Todo elemento HTML tem um valor padrão para essa propriedade. O valor padrão do display para a maioria dos elementos é block (em bloco) ou inline (em linha). Utilizando essa propriedade, podemos fazer uma <div> em linha ou um <img> em bloco.

#divInline {
  display: inline
}

#imgBlock {
  display: block;
}

Também é possível atribuir o valor none a essa proprieda, fazendo com que o elemento não seja mostrado na tela. Isso é utilizado com JavaScript para mostrar/esconder elementos.

Posicionamento

A propriedade position define que tipo de posicionamento será utilizado para exibir um elemento na página.

Os principais valores dessa propriedade são:

  • static — os elementos são renderizados na ordem que eles aparecem no documento HTML (valor padrão);

  • relative — os elementos são posicionados relativamente a sua posição normal, permitindo o ajuste do elemento a partir de offsets (propriedades top, bottom, left e right);

  • absolute — os elementos são posicionados relativamente ao seu primeiro elemento ancestral com position diferente de static;

  • fixed — os elementos são posicionados relativamente à janela do navegador.

Leia este artigo para saber mais sobre posicionamento.

12.3 JavaScript

O JavaScript (JS) é uma linguagem de programação criada para a Web. Ele foi criado em apenas 10 dias, em 1995, por uma única pessoa, Brendan Eich. Ele foi inicialmente chamado LiveScript, mas como a linguagem Java era popular na época, o nome mudou para JavaScript, embora as duas linguagens não tenham nenhuma relação uma com a outra.

O papel do JavaScript é possibilitar interatividade em páginas Web. Enquanto o HTML e o CSS apenas ditam como esse conteúdo será apresentada na tela, códigos JavaScript geram comportamentos disparados por ações da pessoa acessando a pagina.

O código JS é colocado junto ao HTML e interpretado pelo navegador. Todo navegador moderno possui um interpretador de JavaScript: você pode testar isso acessando as “Ferramentas de desenvolvedor” do seu navegador e clicando na aba “Console”. O terminal apresentado será um interpretador JavaScript.

Interpretador JavaScript no Google Chrome.

Nesta seção, não faremos uma introdução formal ao JavaScript, pois qualquer tentativa seria incompleta ou muito extensa para o escopo desse livro. Além disso, existe bastante conteúdo introdutório e gratuito sobre JavaScript disponível na internet. O que abordaremos aqui será, dado algum conhecimento prévio da linguagem, como utilizar o JavaScript dentro do Shiny. Começaremos mostrando como inserir um código feito em JS no seu Shiny app e, em seguida, como acessar valores dos inputs do app dentro de um código JavaScript.

12.3.1 Inserindo JavaScript em seu app

Para inserir um código JavaScript em um arquivo HTML, utilizamos o elemento <script></script>. Podemos escrever diretamente o código JavaScript dentro desse elemento ou ler o código de um arquivo externo definido pelo atributo src. Os dois exemplos abaixo são equivalentes e mudam para vermelho a cor do primeiro parágrafo quando clicamos no botão.

# Definindo o código diretamente no HTML
<!DOCTYPE html>
<html>
  <body>
    <p id = "alvo">
      Parágrafo 1
    </p>
    <p>
      Parágrafo 2
    </p>
    <button onClick = "deixarVermelho()">
      Deixar vermelho
    </button>
    <script>
      deixarVermelho = function() {
        document.getElementById("alvo").style = "color: red";
      }
    </script>
  </body>
</html>

  
# Importanto o código de um arquivo JS

# HTML
<!DOCTYPE html>
<html>
  <body>
    <p id = "alvo">
      Parágrafo 1
    </p>
    <p>
      Parágrafo 2
    </p>
    <button onClick = "deixarVermelho()">
      Deixar vermelho
    </button>
    <script src = "script.js"></script>
  </body>
</html>

# JS (script.js)
deixarVermelho = function() {
  document.getElementById("alvo").style = "color: red";
}

O código JS nesse exemplo define uma função que muda o atributo style do elemento com id alvo. Essa função é chamada sempre que o botão é clicado. Isso acontece porque associamos a função ao evento onClick do botão.

Em um aplicativo Shiny, o procedimento é equivalente. A grande diferença é que o arquivo script.js deve estar dentro da pasta www/ para ser acessado pelo navegador.

# Definiindo o código JS diretamente na UI
library(shiny)

ui <- fluidPage(
  tags$p("Parágrafo 1", id = "alvo"),
  tags$p("Parágrafo 2"),
  tags$button(onClick = "deixarVermelho()", "Deixar vermelho"),
  tags$script(
    'deixarVermelho = function() {
      document.getElementById("alvo").style = "color: red";
    }'
  )
)

server <- function(input, output, session) {

}

shinyApp(ui, server)


# Definindo o código JS em um arquivo externo (www/script.js)
library(shiny)

ui <- fluidPage(
  tags$p("Parágrafo 1", id = "alvo"),
  tags$p("Parágrafo 2"),
  tags$button(onClick = "deixarVermelho()", "Deixar vermelho"),
  tags$script(src = "script.js")
)

server <- function(input, output, session) {

}

shinyApp(ui, server)

Um ponto de atenção sobre a utilização de códigos JS em documentos HTML é a posição onde eles são definidos dentro do documento. Como o HTML é interpretado pelo navegador na ordem em que o código foi escrito, se um elemento <script> utilziar elementos que ainda não foram criados, o código JS não vai funcionar.

No exemplo anterior, poderíamos definir o código JavaScript em qualquer lugar do script pois ele define uma função que só será usada quando o botão for clicado. No exemplo a seguir, o código JavaScript pinta de vermelho todos os parágrafos com classe vermelho. Para que isso seja possível, o elemento script deve vir após a criação dos elementos p. Se estivesse definido antes dos elementos p, nenhum parágrafo ficaria vermelho.

# Os parágrafos 1, 3 e 5 ficam com cor vermelha
library(shiny)

ui <- fluidPage(
  tags$p("Parágrafo 1", class = "vermelho"),
  tags$p("Parágrafo 2"),
  tags$p("Parágrafo 3", class = "vermelho"),
  tags$p("Parágrafo 4"),
  tags$p("Parágrafo 5", class = "vermelho"),
  tags$script(
    'document.getElementsByClassName("vermelho").forEach(
      function(paragrafo) {
        paragrafo.style = "color: red"
      }
    )'
  )
)

server <- function(input, output, session) {

}

shinyApp(ui, server)


# Nenhum parágrafo fica vermelho pois o código JS
# vem antes da criação do parágrafo
library(shiny)

ui <- fluidPage(
   tags$script(
    'document.getElementsByClassName("vermelho").forEach(
      function(paragrafo) {
        paragrafo.style = "color: red"
      }
    )'
  ),
  tags$p("Parágrafo 1", class = "vermelho"),
  tags$p("Parágrafo 2"),
  tags$p("Parágrafo 3", class = "vermelho"),
  tags$p("Parágrafo 4"),
  tags$p("Parágrafo 5", class = "vermelho")
)

server <- function(input, output, session) {

}

shinyApp(ui, server)

12.3.2 Interagindo com inputs via JavaScript

Nesta seção, vamos discutir como interagir com os inputs do Shiny a partir do JavaScript. Vamos fazer isso de duas maneiras: acessando o valor de inputs criados pela UI e criar novos inputs via JavaScript.

Para acessar o valor de um input criado na UI do Shiny a partir do JavaScript precisamos primeiro saber qual elemento HTML representa esse input. No caso de um selectInput com inputId = seletor, por exemplo, estamos criando no HTML um elemento <select id = "seletor">. Então, se quisermos acessar o valor desse input via JS, basta buscarmos por esse elemento e extrair o seu valor.

No exemplo a seguir, constuimos um app que permite trocar a cor do texto apresentado a partir de um selectInput. Essa troca é feita apenas no navegador, a partir de um código JavaScript. Tente rodar o app para testar testar esse comportamento.

# app.R
library(shiny)

ui <- fluidPage(
  h1("JavaScript", align = "center"),
  hr(),
  selectInput(
    inputId = "cor_do_texto",
    label = "Selecione a cor do texto",
    choices = c("black", "red", "orange", "purple", "blue", "green")
  ),
  br(),
  p("JavaScript (frequentemente abreviado como JS) é uma linguagem de
    programação interpretada estruturada, de script em alto nível com tipagem
    dinâmica fraca e multiparadigma (protótipos, orientado a objeto,
    imperativo e funcional). Juntamente com HTML e CSS, o JavaScript é
    uma das três principais tecnologias da World Wide Web. JavaScript
    permite páginas da Web interativas e, portanto, é uma parte essencial
    dos aplicativos da web. A grande maioria dos sites usa, e todos os
    principais navegadores têm um mecanismo JavaScript dedicado para
    executá-lo."),
  p("É atualmente a principal linguagem para programação client-side em
    navegadores web. É também bastante utilizada do lado do servidor através
    de ambientes como o node.js."),
  tags$script(src = "script.js")
)

server <- function(input, output, session) {

}

shinyApp(ui, server)
# www/script.js
var select = document.getElementById("cor_do_texto");

select.onchange = function() {
  var paragrafos = document.getElementsByTagName("p");
  for (var i = 0; i < paragrafos.length; i++) {
    paragrafos[i].style = "color: " + select.value + ";";
  }
}

O código JavaScript utilizado busca no HTML o elemento que representa o selectInput a partir do seu Id e atribui a ele uma função que será executada sempre que o valor desse select mudar. A função busca por todas as tags p do HTML e utiliza o valor do select para alterar a cor do texto. Esse valor é acessado via a propriedade value do objeto select.

Como exercício, tente refazer esse exemplo sem usar o JavaScript, usando no lugar um renderUI na função server.

A partir do JavaScript, também podemos criar novos inputs e acessá-los no servidor. Para isso, usamos o método Shiny.setInputValue(idName, value) em nosso código JavaScript. O app abaixo apresenta uma mensagem na tela informando qual navegador está sendo usado para acessá-lo. Veja que o input$browser não é definido na UI, mas sim dentro do código JavaScript.

# app.R
library(shiny)

ui <- fluidPage(
  tags$script(src = "script.js"),
  textOutput("mensagem")
)

server <- function(input, output, session) {

  output$mensagem <- renderText({
    print(input$browser)
    glue::glue("Olá! Você está usando o navegador {input$browser}!")
  })

}

shinyApp(ui, server)
// www/script.js
function getBrowserName() {
  let browserInfo = navigator.userAgent;
  let browser;
  if (browserInfo.includes('Opera') || browserInfo.includes('Opr')) {
    browser = 'Opera';
  } else if (browserInfo.includes('Edg')) {
    browser = 'Edge';
  } else if (browserInfo.includes('Chrome')) {
    browser = 'Chrome';
  } else if (browserInfo.includes('Safari')) {
    browser = 'Safari';
  } else if (browserInfo.includes('Firefox')) {
    browser = 'Firefox';
  } else {
    browser = 'unknown';
  }
    return browser;
}

$(document).on("shiny:sessioninitialized", function() {
  Shiny.setInputValue("browser", getBrowserName());
});

A primeira parte do código JavaScript define uma função chamada getBrowserName(), que identifica qual o navegador está sendo utilizado. A segunda parte define uma função anônima que será executada assim que a sessão do Shiny for inicializada. Essa função cria o input browser com o valor retornado pela função getBrowserName().

O objeto Shiny possui vários outros métodos para interagirmos com a sessão do Shiny via JavaScript. Recomendamos a leitura dos artigos a seguir para mais informações de como utilizá-lo:

12.4 Exercícios

1 - O que são elementos HTML?


2 - Para que serve a seção <head> de um código HTML?


3 - Conserte o erro do código HTML abaixo:

<p> Para acessar a loja, basta clicar <a href = "https://loja.curso-r.com">neste link</p></a>

4 - Qual a diferença entre as tags <div> e <span>?


5 - Ao que se refere o termo cascading da sigla CSS?


6 - Qual a ordem de precedência com relação ao local onde CSS pode ser colocado (inline, interno, externo)?


7 - O que é o box model no CSS?


8 - Segundo o código CSS abaixo, a caixa azul vai aparecer sobre o fundo amarelo ou rosa? E a caixa laranja?

<div style = "position: relative;">
  <div style = "height: 100px; background-color: yellow;"></div>
  <div style = "height: 100px; background-color: pink;">
    <div style = "height: 40px; width: 10%; background-color: blue;">
      Caixa azul
    </div>
    <div style = "height: 40px; width: 10%; background-color: orange; position: absolute; top: 0px;">
      Caixa laranja
    </div>
  </div>
</div>

9 - Reproduza a página HTML contida neste link. Sinta-se livre para deixar o visual da página da sua maneira.


10 - Em um app Shiny, para que serve o método JS Shiny.setInputValue(idName, value)?


  1. É uma boa prática declarar o idioma da página, pois isso é utilizado pelos algorítmos de busca e pelos navegadores.↩︎