-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathhtml-css-js.qmd
941 lines (643 loc) · 31.1 KB
/
html-css-js.qmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
```{r, echo = FALSE}
knitr::opts_chunk$set(
fig.align = "center"
)
```
# HTML, CSS e JavaScript {#sec-html-css-js}
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.
## HTML
O HTML é uma [linguagem de marcação](https://pt.wikipedia.org/wiki/Linguagem_de_marca%C3%A7%C3%A3o) 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 inesperados e erros podem acontecer se você esquecer 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.
```{html}
<!DOCTYPE html>
```
Ela representa o tipo de documento, o que ajuda os navegadores 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>`.
```{html}
<!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}
<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>`.
```{html}
<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.
```{html}
<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.
```{html}
<!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.
```{html}
<!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ágina^[É uma boa prática declarar o idioma da página, pois isso é utilizado pelos algorítmos de busca e pelos navegadores.].
### Links {-}
Links no HTML são chamados de **hiperlinks** (ou hiperligação). Eles são criados com a tag `<a>`.
```{html}
<a href="https://curso-r.com">
Clique aqui para acessar o site da curso-r
</a>
```
Veja que este elemento possui o atributo `href`, que define o destino do link. O conteúdo deste elemento será o texto visível na tela para ser clicado.
### 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.
```{html}
<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.
```{html}
<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>`.
```{html}
<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 à disposiçã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.
```{html}
<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.
```{html}
<p>
Como formatar uma única <span>palavra</span>?
</p>
```
## CSS {#alemCSS}
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.
```{html}
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;
- já `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.
```{html}
<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}
<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`.
```{html}
<!--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.
```{html}
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`.
```{html}
p {
font-size: 10px;
}
h1 {
font-size: 12pt;
}
```
### Fontes {-}
Para alterar a fonte do texto, utilizamos a propriedade `font-family`.
```{html}
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](https://www.w3schools.com/css/css_font.asp) 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`.
```{html}
<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`.
```{htlm}
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}
<!-- 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}
<!-- 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 de 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.
```{html}
p.azul {
color: blue;
}
```
Já a seguinte regra tem especificidade de 10, pois só possui um elemento, e seria preterida com relação à anterior.
```{html}
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.
```{html}
p {
color: red;
}
p {
color: yellow;
}
```
Saiba mais sobre **especificidade** [neste artigo da W3Schools](https://www.w3schools.com/css/css_specificity.asp) em inglês ou [neste artigo](https://tipscode.com.br/especificidade-css-5-coisas-que-voce-precisa) 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*:
```{r, out.width="84%", echo = FALSE}
knitr::include_graphics("img/box_model.png")
```
### Margem {-}
Margens são utilizadas para criar espaço em branco entre elementos HTML. As duas regras CSS a seguir são equivalentes.
```{html}
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.
```{html}
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.
```{html}
#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](https://developer.mozilla.org/en-US/docs/Web/CSS/position) para saber mais sobre posicionamento.
## 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á apresentado na tela, códigos JavaScript geram comportamentos disparados por ações da pessoa acessando a página.
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.
```{r, fig.cap="Interpretador JavaScript no Google Chrome.", echo = FALSE}
knitr::include_graphics("img/console_js.png")
```
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.
### 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.
```{html}
# 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>
# Importando 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.
```{r, eval = FALSE}
# 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>` utilizar 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.
```{r, eval = FALSE}
# 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)
```
### 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.
```{r, eval = FALSE}
# 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)
```
```{js}
# 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.
```{r, eval = FALSE}
# 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)
```
```{js}
// 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:
- [Comunicando-se com o Shiny via JS](https://shiny.rstudio.com/articles/communicating-with-js.html)
- [Eventos JS no Shiny](https://shiny.rstudio.com/articles/js-events.html)
## 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:
```{html}
<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?
```{html}
<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](https://curso-r.github.io/main-dashboards-2/exercicios/04-html-css/harry_potter/index.html). 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)`?