-
Notifications
You must be signed in to change notification settings - Fork 48
/
html-widgets.html
1031 lines (991 loc) · 124 KB
/
html-widgets.html
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
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html lang="" xml:lang="">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Chapter 5 HTML widgets | JavaScript for R</title>
<meta name="description" content="Invite JavaScript into your Data Science workflow." />
<meta name="generator" content="bookdown 0.19 and GitBook 2.6.7" />
<meta property="og:title" content="Chapter 5 HTML widgets | JavaScript for R" />
<meta property="og:type" content="book" />
<meta property="og:description" content="Invite JavaScript into your Data Science workflow." />
<meta name="github-repo" content="yihui/bookdown-crc" />
<meta name="twitter:card" content="summary" />
<meta name="twitter:title" content="Chapter 5 HTML widgets | JavaScript for R" />
<meta name="twitter:description" content="Invite JavaScript into your Data Science workflow." />
<meta name="author" content="John Coene" />
<meta name="date" content="2020-06-04" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<link rel="prev" href="shiny-1.html"/>
<link rel="next" href="references.html"/>
<script src="libs/header-attrs/header-attrs.js"></script>
<script src="libs/jquery/jquery.min.js"></script>
<link href="libs/gitbook/css/style.css" rel="stylesheet" />
<link href="libs/gitbook/css/plugin-table.css" rel="stylesheet" />
<link href="libs/gitbook/css/plugin-bookdown.css" rel="stylesheet" />
<link href="libs/gitbook/css/plugin-highlight.css" rel="stylesheet" />
<link href="libs/gitbook/css/plugin-search.css" rel="stylesheet" />
<link href="libs/gitbook/css/plugin-fontsettings.css" rel="stylesheet" />
<link href="libs/gitbook/css/plugin-clipboard.css" rel="stylesheet" />
<script src="libs/htmlwidgets/htmlwidgets.js"></script>
<script src="libs/plotly-binding/plotly.js"></script>
<script src="libs/typedarray/typedarray.min.js"></script>
<link href="libs/crosstalk/css/crosstalk.css" rel="stylesheet" />
<script src="libs/crosstalk/js/crosstalk.min.js"></script>
<link href="libs/plotly-htmlwidgets-css/plotly-htmlwidgets.css" rel="stylesheet" />
<script src="libs/plotly-main/plotly-latest.min.js"></script>
<script src="libs/core-js/shim.min.js"></script>
<script src="libs/react/react.min.js"></script>
<script src="libs/react/react-dom.min.js"></script>
<script src="libs/reactwidget/react-tools.js"></script>
<script src="libs/reactable-binding/reactable.js"></script>
<script src="libs/r2d3-render/r2d3-render.js"></script>
<script src="libs/webcomponents/webcomponents.js"></script>
<script src="libs/r2d3-binding/r2d3.js"></script>
<script src="libs/d3v5/d3.min.js"></script>
<style type="text/css">
pre > code.sourceCode { white-space: pre; position: relative; }
pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
pre > code.sourceCode > span:empty { height: 1.2em; }
code.sourceCode > span { color: inherit; text-decoration: inherit; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
pre > code.sourceCode { white-space: pre-wrap; }
pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
}
pre.numberSource code
{ counter-reset: source-line 0; }
pre.numberSource code > span
{ position: relative; left: -4em; counter-increment: source-line; }
pre.numberSource code > span > a:first-child::before
{ content: counter(source-line);
position: relative; left: -1em; text-align: right; vertical-align: baseline;
border: none; display: inline-block;
-webkit-touch-callout: none; -webkit-user-select: none;
-khtml-user-select: none; -moz-user-select: none;
-ms-user-select: none; user-select: none;
padding: 0 4px; width: 4em;
color: #aaaaaa;
}
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
div.sourceCode
{ }
@media screen {
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
}
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code span.at { color: #7d9029; } /* Attribute */
code span.bn { color: #40a070; } /* BaseN */
code span.bu { } /* BuiltIn */
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code span.ch { color: #4070a0; } /* Char */
code span.cn { color: #880000; } /* Constant */
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
code span.dt { color: #902000; } /* DataType */
code span.dv { color: #40a070; } /* DecVal */
code span.er { color: #ff0000; font-weight: bold; } /* Error */
code span.ex { } /* Extension */
code span.fl { color: #40a070; } /* Float */
code span.fu { color: #06287e; } /* Function */
code span.im { } /* Import */
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
code span.op { color: #666666; } /* Operator */
code span.ot { color: #007020; } /* Other */
code span.pp { color: #bc7a00; } /* Preprocessor */
code span.sc { color: #4070a0; } /* SpecialChar */
code span.ss { color: #bb6688; } /* SpecialString */
code span.st { color: #4070a0; } /* String */
code span.va { color: #19177c; } /* Variable */
code span.vs { color: #4070a0; } /* VerbatimString */
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
</style>
<link rel="stylesheet" href="css/style.css" type="text/css" />
</head>
<body>
<div class="book without-animation with-summary font-size-2 font-family-1" data-basepath=".">
<div class="book-summary">
<nav role="navigation">
<ul class="summary">
<li><a href="./">R and JavaScript</a></li>
<li class="divider"></li>
<li class="chapter" data-level="" data-path="index.html"><a href="index.html"><i class="fa fa-check"></i>Preface</a>
<ul>
<li class="chapter" data-level="" data-path="index.html"><a href="index.html#disclaimer"><i class="fa fa-check"></i>Disclaimer</a></li>
</ul></li>
<li class="part"><span><b>I Basics & Roadmap</b></span></li>
<li class="chapter" data-level="1" data-path="introduction.html"><a href="introduction.html"><i class="fa fa-check"></i><b>1</b> Introduction</a>
<ul>
<li class="chapter" data-level="" data-path="introduction.html"><a href="introduction.html#rationale"><i class="fa fa-check"></i>Rationale</a></li>
<li class="chapter" data-level="" data-path="introduction.html"><a href="introduction.html#prerequisites"><i class="fa fa-check"></i>Prerequisites</a>
<ul>
<li class="chapter" data-level="" data-path="introduction.html"><a href="introduction.html#package-development"><i class="fa fa-check"></i>Package Development</a></li>
<li class="chapter" data-level="" data-path="introduction.html"><a href="introduction.html#json"><i class="fa fa-check"></i>JSON</a></li>
<li class="chapter" data-level="" data-path="introduction.html"><a href="introduction.html#javascript"><i class="fa fa-check"></i>JavaScript</a></li>
</ul></li>
<li class="chapter" data-level="" data-path="introduction.html"><a href="introduction.html#methods"><i class="fa fa-check"></i>Methods</a>
<ul>
<li class="chapter" data-level="" data-path="introduction.html"><a href="introduction.html#v8"><i class="fa fa-check"></i>V8</a></li>
<li class="chapter" data-level="" data-path="introduction.html"><a href="introduction.html#htmlwidgets"><i class="fa fa-check"></i>htmlwidgets</a></li>
<li class="chapter" data-level="" data-path="introduction.html"><a href="introduction.html#shiny"><i class="fa fa-check"></i>Shiny</a></li>
<li class="chapter" data-level="" data-path="introduction.html"><a href="introduction.html#reactr"><i class="fa fa-check"></i>reactR</a></li>
<li class="chapter" data-level="" data-path="introduction.html"><a href="introduction.html#bubble"><i class="fa fa-check"></i>bubble</a></li>
<li class="chapter" data-level="" data-path="introduction.html"><a href="introduction.html#r2d3"><i class="fa fa-check"></i>r2d3</a></li>
</ul></li>
</ul></li>
<li class="part"><span><b>II JavaScript for Computations</b></span></li>
<li class="chapter" data-level="2" data-path="the-v8-engine.html"><a href="the-v8-engine.html"><i class="fa fa-check"></i><b>2</b> The V8 Engine</a>
<ul>
<li class="chapter" data-level="" data-path="the-v8-engine.html"><a href="the-v8-engine.html#installation"><i class="fa fa-check"></i>Installation</a></li>
<li class="chapter" data-level="" data-path="the-v8-engine.html"><a href="the-v8-engine.html#basics"><i class="fa fa-check"></i>Basics</a></li>
<li class="chapter" data-level="" data-path="the-v8-engine.html"><a href="the-v8-engine.html#external-libraries"><i class="fa fa-check"></i>External Libraries</a></li>
<li class="chapter" data-level="" data-path="the-v8-engine.html"><a href="the-v8-engine.html#with-npm"><i class="fa fa-check"></i>With Npm</a></li>
<li class="chapter" data-level="" data-path="the-v8-engine.html"><a href="the-v8-engine.html#use-in-packages"><i class="fa fa-check"></i>Use in Packages</a></li>
</ul></li>
<li class="chapter" data-level="3" data-path="node.html"><a href="node.html"><i class="fa fa-check"></i><b>3</b> Node.js with Bubble</a>
<ul>
<li class="chapter" data-level="" data-path="node.html"><a href="node.html#basics-1"><i class="fa fa-check"></i>Basics</a></li>
<li class="chapter" data-level="" data-path="node.html"><a href="node.html#r-markdown-engine"><i class="fa fa-check"></i>R Markdown Engine</a></li>
<li class="chapter" data-level="" data-path="node.html"><a href="node.html#npm"><i class="fa fa-check"></i>Npm</a></li>
<li class="chapter" data-level="" data-path="node.html"><a href="node.html#use-in-packages-1"><i class="fa fa-check"></i>Use in Packages</a></li>
</ul></li>
<li class="part"><span><b>III Web Development with Shiny</b></span></li>
<li class="chapter" data-level="4" data-path="shiny-1.html"><a href="shiny-1.html"><i class="fa fa-check"></i><b>4</b> Shiny</a>
<ul>
<li class="chapter" data-level="" data-path="shiny-1.html"><a href="shiny-1.html#static-files"><i class="fa fa-check"></i>Static Files</a></li>
<li class="chapter" data-level="" data-path="shiny-1.html"><a href="shiny-1.html#integration"><i class="fa fa-check"></i>Integration</a></li>
<li class="chapter" data-level="" data-path="shiny-1.html"><a href="shiny-1.html#from-r-to-javascript"><i class="fa fa-check"></i>From R to JavaScript</a></li>
<li class="chapter" data-level="" data-path="shiny-1.html"><a href="shiny-1.html#from-javascript-to-r"><i class="fa fa-check"></i>From JavaScript to R</a></li>
<li class="chapter" data-level="" data-path="shiny-1.html"><a href="shiny-1.html#external-library"><i class="fa fa-check"></i>External Library</a></li>
<li class="chapter" data-level="" data-path="shiny-1.html"><a href="shiny-1.html#serialisation"><i class="fa fa-check"></i>Serialisation</a></li>
<li class="chapter" data-level="" data-path="shiny-1.html"><a href="shiny-1.html#events-callbacks"><i class="fa fa-check"></i>Events & Callbacks</a></li>
<li class="chapter" data-level="" data-path="shiny-1.html"><a href="shiny-1.html#as-a-package"><i class="fa fa-check"></i>As a Package</a>
<ul>
<li class="chapter" data-level="" data-path="shiny-1.html"><a href="shiny-1.html#dependencies"><i class="fa fa-check"></i>Dependencies</a></li>
<li class="chapter" data-level="" data-path="shiny-1.html"><a href="shiny-1.html#r-code"><i class="fa fa-check"></i>R Code</a></li>
<li class="chapter" data-level="" data-path="shiny-1.html"><a href="shiny-1.html#javascript-code"><i class="fa fa-check"></i>JavaScript Code</a></li>
<li class="chapter" data-level="" data-path="shiny-1.html"><a href="shiny-1.html#shortcoming"><i class="fa fa-check"></i>Shortcoming</a></li>
<li class="chapter" data-level="" data-path="shiny-1.html"><a href="shiny-1.html#input"><i class="fa fa-check"></i>Input</a></li>
<li class="chapter" data-level="" data-path="shiny-1.html"><a href="shiny-1.html#wrapping-up"><i class="fa fa-check"></i>Wrapping up</a></li>
</ul></li>
<li class="chapter" data-level="" data-path="shiny-1.html"><a href="shiny-1.html#exercises"><i class="fa fa-check"></i>Exercises</a></li>
</ul></li>
<li class="part"><span><b>IV Data Visualisation</b></span></li>
<li class="chapter" data-level="5" data-path="html-widgets.html"><a href="html-widgets.html"><i class="fa fa-check"></i><b>5</b> HTML widgets</a>
<ul>
<li class="chapter" data-level="" data-path="html-widgets.html"><a href="html-widgets.html#candidate-libraries"><i class="fa fa-check"></i>Candidate Libraries</a>
<ul>
<li class="chapter" data-level="" data-path="html-widgets.html"><a href="html-widgets.html#plotly"><i class="fa fa-check"></i>Plotly</a></li>
<li class="chapter" data-level="" data-path="html-widgets.html"><a href="html-widgets.html#highchart.js"><i class="fa fa-check"></i>Highchart.js</a></li>
<li class="chapter" data-level="" data-path="html-widgets.html"><a href="html-widgets.html#chart.js"><i class="fa fa-check"></i>Chart.js</a></li>
</ul></li>
<li class="chapter" data-level="" data-path="html-widgets.html"><a href="html-widgets.html#how-it-works"><i class="fa fa-check"></i>How it works</a></li>
<li class="chapter" data-level="" data-path="html-widgets.html"><a href="html-widgets.html#the-scaffold"><i class="fa fa-check"></i>The Scaffold</a></li>
<li class="chapter" data-level="" data-path="html-widgets.html"><a href="html-widgets.html#the-output"><i class="fa fa-check"></i>The Output</a></li>
<li class="chapter" data-level="" data-path="html-widgets.html"><a href="html-widgets.html#typed.js"><i class="fa fa-check"></i>Typed.js</a>
<ul>
<li class="chapter" data-level="" data-path="html-widgets.html"><a href="html-widgets.html#dependency"><i class="fa fa-check"></i>Dependency</a></li>
<li class="chapter" data-level="" data-path="html-widgets.html"><a href="html-widgets.html#javascript-1"><i class="fa fa-check"></i>JavaScript</a></li>
<li class="chapter" data-level="" data-path="html-widgets.html"><a href="html-widgets.html#html-element"><i class="fa fa-check"></i>HTML Element</a></li>
<li class="chapter" data-level="" data-path="html-widgets.html"><a href="html-widgets.html#exercises-1"><i class="fa fa-check"></i>Exercises</a></li>
</ul></li>
<li class="chapter" data-level="" data-path="html-widgets.html"><a href="html-widgets.html#gio.js"><i class="fa fa-check"></i>Gio.js</a>
<ul>
<li class="chapter" data-level="" data-path="html-widgets.html"><a href="html-widgets.html#dependencies-1"><i class="fa fa-check"></i>Dependencies</a></li>
<li class="chapter" data-level="" data-path="html-widgets.html"><a href="html-widgets.html#javascript-2"><i class="fa fa-check"></i>JavaScript</a></li>
<li class="chapter" data-level="" data-path="html-widgets.html"><a href="html-widgets.html#working-with-data"><i class="fa fa-check"></i>Working with Data</a></li>
<li class="chapter" data-level="" data-path="html-widgets.html"><a href="html-widgets.html#transforming-data"><i class="fa fa-check"></i>Transforming Data</a></li>
</ul></li>
</ul></li>
<li class="chapter" data-level="" data-path="references.html"><a href="references.html"><i class="fa fa-check"></i>References</a></li>
</ul>
</nav>
</div>
<div class="book-body">
<div class="body-inner">
<div class="book-header" role="navigation">
<h1>
<i class="fa fa-circle-o-notch fa-spin"></i><a href="./">JavaScript for R</a>
</h1>
</div>
<div class="page-wrapper" tabindex="-1" role="main">
<div class="page-inner">
<section class="normal" id="section-">
<div id="html-widgets" class="section level1" number="5">
<h1><span class="header-section-number">Chapter 5</span> HTML widgets</h1>
<p>In this chapter we cover the integration of JavaScript with R using the htmlwidgets package, which focuses on libraries that produce a visual output, it is often used for data visualisation but is not limited to it.</p>
<p>As in previous chapters we mainly learn by example, building multiple widgets of increasing complexity as we progress through the chapter. Before writing the first widget, we explore JavaScript libraries that make great candidates for htmlwidgets and attempt to understand how they work to grasp what is expected from the developer in order to integrate them with R. Finally, we build up on the previous chapter to improve how HTML widgets work with shiny.</p>
<div id="candidate-libraries" class="section level2 unnumbered" number="">
<h2>Candidate Libraries</h2>
<p>Before going down the rabbit hole it is good to take a look at the types of libraries one will work with. As htmlwidgets’ main client are JavaScript visualisation libraries let us take a look at some such popular libraries and briefly look at how they work and what they have in common. This will greatly help conceptualise what one is trying to achieve in this chapter.</p>
<div id="plotly" class="section level3 unnumbered" number="">
<h3>Plotly</h3>
<p><a href="https://plotly.com/javascript/">Plotly.js</a> is probably one of the more popular out there, it provides over 40 fully customiseable chart types, many of which are very sophisticated. This is indeed the JavaScript library used by the R package of the same name: plotly.</p>
<p>Looking at the code presented in the “Get Started” guide reveals just how convenient the library is. One must import plotly, of course, then have a <code><div></code> where to visualisation will be placed, then, using <code>Plotly.newPlot</code>, create the actual visualisation by passing it first the element previously mentioned and a JSON of options.</p>
<div class="sourceCode" id="cb160"><pre class="sourceCode html"><code class="sourceCode html"><span id="cb160-1"><a href="html-widgets.html#cb160-1"></a><span class="dt"><!DOCTYPE </span>html<span class="dt">></span></span>
<span id="cb160-2"><a href="html-widgets.html#cb160-2"></a><span class="kw"><html</span><span class="ot"> xmlns=</span><span class="st">"http://www.w3.org/1999/xhtml"</span><span class="ot"> lang=</span><span class="st">""</span><span class="ot"> xml:lang=</span><span class="st">""</span><span class="kw">></span></span>
<span id="cb160-3"><a href="html-widgets.html#cb160-3"></a></span>
<span id="cb160-4"><a href="html-widgets.html#cb160-4"></a><span class="kw"><head></span></span>
<span id="cb160-5"><a href="html-widgets.html#cb160-5"></a> <span class="co"><!-- Import library --></span></span>
<span id="cb160-6"><a href="html-widgets.html#cb160-6"></a> <span class="kw"><script</span><span class="ot"> src=</span><span class="st">"plotly-latest.min.js"</span><span class="kw">></script></span></span>
<span id="cb160-7"><a href="html-widgets.html#cb160-7"></a><span class="kw"></head></span></span>
<span id="cb160-8"><a href="html-widgets.html#cb160-8"></a></span>
<span id="cb160-9"><a href="html-widgets.html#cb160-9"></a><span class="kw"><body></span></span>
<span id="cb160-10"><a href="html-widgets.html#cb160-10"></a> <span class="co"><!-- div to hold visualisation --></span></span>
<span id="cb160-11"><a href="html-widgets.html#cb160-11"></a> <span class="kw"><div</span><span class="ot"> id=</span><span class="st">"chart"</span><span class="ot"> style=</span><span class="st">"width:600px;height:250px;"</span><span class="kw">></div></span></span>
<span id="cb160-12"><a href="html-widgets.html#cb160-12"></a></span>
<span id="cb160-13"><a href="html-widgets.html#cb160-13"></a> <span class="co"><!-- Script to create visualsiation --></span></span>
<span id="cb160-14"><a href="html-widgets.html#cb160-14"></a> <span class="kw"><script></span></span>
<span id="cb160-15"><a href="html-widgets.html#cb160-15"></a> el <span class="op">=</span> <span class="va">document</span>.<span class="at">getElementById</span>(<span class="st">'chart'</span>)<span class="op">;</span></span>
<span id="cb160-16"><a href="html-widgets.html#cb160-16"></a> <span class="va">Plotly</span>.<span class="at">newPlot</span>(el<span class="op">,</span> [<span class="op">{</span></span>
<span id="cb160-17"><a href="html-widgets.html#cb160-17"></a> <span class="dt">x</span><span class="op">:</span> [<span class="dv">1</span><span class="op">,</span> <span class="dv">2</span><span class="op">,</span> <span class="dv">3</span><span class="op">,</span> <span class="dv">4</span><span class="op">,</span> <span class="dv">5</span>]<span class="op">,</span></span>
<span id="cb160-18"><a href="html-widgets.html#cb160-18"></a> <span class="dt">y</span><span class="op">:</span> [<span class="dv">1</span><span class="op">,</span> <span class="dv">2</span><span class="op">,</span> <span class="dv">4</span><span class="op">,</span> <span class="dv">8</span><span class="op">,</span> <span class="dv">16</span>] <span class="op">}</span>]</span>
<span id="cb160-19"><a href="html-widgets.html#cb160-19"></a> )<span class="op">;</span></span>
<span id="cb160-20"><a href="html-widgets.html#cb160-20"></a> <span class="kw"></script></span></span>
<span id="cb160-21"><a href="html-widgets.html#cb160-21"></a><span class="kw"></body></span></span>
<span id="cb160-22"><a href="html-widgets.html#cb160-22"></a></span>
<span id="cb160-23"><a href="html-widgets.html#cb160-23"></a><span class="kw"></html></span></span></code></pre></div>
<p>Now let’s look at how another popular library does it.</p>
</div>
<div id="highchart.js" class="section level3 unnumbered" number="">
<h3>Highchart.js</h3>
<p><a href="https://www.highcharts.com/">Highcharts</a> is another library which allows creating gorgeous visualisation, maps, and more, it’s also very popular albeit not being entirely open-source.</p>
<div class="sourceCode" id="cb161"><pre class="sourceCode html"><code class="sourceCode html"><span id="cb161-1"><a href="html-widgets.html#cb161-1"></a><span class="dt"><!DOCTYPE </span>html<span class="dt">></span></span>
<span id="cb161-2"><a href="html-widgets.html#cb161-2"></a><span class="kw"><html</span><span class="ot"> xmlns=</span><span class="st">"http://www.w3.org/1999/xhtml"</span><span class="ot"> lang=</span><span class="st">""</span><span class="ot"> xml:lang=</span><span class="st">""</span><span class="kw">></span></span>
<span id="cb161-3"><a href="html-widgets.html#cb161-3"></a></span>
<span id="cb161-4"><a href="html-widgets.html#cb161-4"></a><span class="kw"><head></span></span>
<span id="cb161-5"><a href="html-widgets.html#cb161-5"></a> <span class="co"><!-- Import library --></span></span>
<span id="cb161-6"><a href="html-widgets.html#cb161-6"></a> <span class="kw"><script</span><span class="ot"> src=</span><span class="st">"highcharts.js"</span><span class="kw">></script></span></span>
<span id="cb161-7"><a href="html-widgets.html#cb161-7"></a><span class="kw"></head></span></span>
<span id="cb161-8"><a href="html-widgets.html#cb161-8"></a></span>
<span id="cb161-9"><a href="html-widgets.html#cb161-9"></a><span class="kw"><body></span></span>
<span id="cb161-10"><a href="html-widgets.html#cb161-10"></a> <span class="co"><!-- div to hold visualisation --></span></span>
<span id="cb161-11"><a href="html-widgets.html#cb161-11"></a> <span class="kw"><div</span><span class="ot"> id=</span><span class="st">"chart"</span><span class="ot"> style=</span><span class="st">"width:100%; height:400px;"</span><span class="kw">></div></span></span>
<span id="cb161-12"><a href="html-widgets.html#cb161-12"></a></span>
<span id="cb161-13"><a href="html-widgets.html#cb161-13"></a> <span class="co"><!-- Script to create visualsiation --></span></span>
<span id="cb161-14"><a href="html-widgets.html#cb161-14"></a> <span class="kw"><script></span></span>
<span id="cb161-15"><a href="html-widgets.html#cb161-15"></a> <span class="kw">var</span> myChart <span class="op">=</span> <span class="va">Highcharts</span>.<span class="at">chart</span>(<span class="st">'chart'</span><span class="op">,</span> <span class="op">{</span></span>
<span id="cb161-16"><a href="html-widgets.html#cb161-16"></a> <span class="dt">xAxis</span><span class="op">:</span> <span class="op">{</span></span>
<span id="cb161-17"><a href="html-widgets.html#cb161-17"></a> <span class="dt">categories</span><span class="op">:</span> [<span class="st">'Apples'</span><span class="op">,</span> <span class="st">'Bananas'</span><span class="op">,</span> <span class="st">'Oranges'</span>]</span>
<span id="cb161-18"><a href="html-widgets.html#cb161-18"></a> <span class="op">},</span></span>
<span id="cb161-19"><a href="html-widgets.html#cb161-19"></a> <span class="dt">series</span><span class="op">:</span> [<span class="op">{</span></span>
<span id="cb161-20"><a href="html-widgets.html#cb161-20"></a> <span class="dt">name</span><span class="op">:</span> <span class="st">'Jane'</span><span class="op">,</span></span>
<span id="cb161-21"><a href="html-widgets.html#cb161-21"></a> <span class="dt">data</span><span class="op">:</span> [<span class="dv">1</span><span class="op">,</span> <span class="dv">0</span><span class="op">,</span> <span class="dv">4</span>]</span>
<span id="cb161-22"><a href="html-widgets.html#cb161-22"></a> <span class="op">},</span> <span class="op">{</span></span>
<span id="cb161-23"><a href="html-widgets.html#cb161-23"></a> <span class="dt">name</span><span class="op">:</span> <span class="st">'John'</span><span class="op">,</span></span>
<span id="cb161-24"><a href="html-widgets.html#cb161-24"></a> <span class="dt">data</span><span class="op">:</span> [<span class="dv">5</span><span class="op">,</span> <span class="dv">7</span><span class="op">,</span> <span class="dv">3</span>]</span>
<span id="cb161-25"><a href="html-widgets.html#cb161-25"></a> <span class="op">}</span>]</span>
<span id="cb161-26"><a href="html-widgets.html#cb161-26"></a> <span class="op">}</span>)<span class="op">;</span></span>
<span id="cb161-27"><a href="html-widgets.html#cb161-27"></a> <span class="kw"></script></span></span>
<span id="cb161-28"><a href="html-widgets.html#cb161-28"></a><span class="kw"></body></span></span>
<span id="cb161-29"><a href="html-widgets.html#cb161-29"></a></span>
<span id="cb161-30"><a href="html-widgets.html#cb161-30"></a><span class="kw"></html></span></span></code></pre></div>
<p>The above is very similar to what plotly.js requires: import libraries, create a <code><div></code> where to put the visualisation, and, to create the chart, run a function which also takes the id of the div where to place the chart and a JSON of options defining the actual chart, including the data.</p>
</div>
<div id="chart.js" class="section level3 unnumbered" number="">
<h3>Chart.js</h3>
<p><a href="https://www.chartjs.org/">Chart.js</a> is yet another library which to draw standard charts popular for its permissive license and convenient API.</p>
<div class="sourceCode" id="cb162"><pre class="sourceCode html"><code class="sourceCode html"><span id="cb162-1"><a href="html-widgets.html#cb162-1"></a><span class="dt"><!DOCTYPE </span>html<span class="dt">></span></span>
<span id="cb162-2"><a href="html-widgets.html#cb162-2"></a><span class="kw"><html</span><span class="ot"> xmlns=</span><span class="st">"http://www.w3.org/1999/xhtml"</span><span class="ot"> lang=</span><span class="st">""</span><span class="ot"> xml:lang=</span><span class="st">""</span><span class="kw">></span></span>
<span id="cb162-3"><a href="html-widgets.html#cb162-3"></a></span>
<span id="cb162-4"><a href="html-widgets.html#cb162-4"></a><span class="kw"><head></span></span>
<span id="cb162-5"><a href="html-widgets.html#cb162-5"></a> <span class="co"><!-- Import library --></span></span>
<span id="cb162-6"><a href="html-widgets.html#cb162-6"></a> <span class="kw"><script</span><span class="ot"> src=</span><span class="st">"Chart.min.js"</span><span class="kw">></script></span></span>
<span id="cb162-7"><a href="html-widgets.html#cb162-7"></a><span class="kw"></head></span></span>
<span id="cb162-8"><a href="html-widgets.html#cb162-8"></a></span>
<span id="cb162-9"><a href="html-widgets.html#cb162-9"></a><span class="kw"><body></span></span>
<span id="cb162-10"><a href="html-widgets.html#cb162-10"></a> <span class="co"><!-- canvas to hold visualisation --></span></span>
<span id="cb162-11"><a href="html-widgets.html#cb162-11"></a> <span class="kw"><canvas</span><span class="ot"> id=</span><span class="st">"chart"</span><span class="ot"> width=</span><span class="st">"400"</span><span class="ot"> height=</span><span class="st">"400"</span><span class="kw">></canvas></span></span>
<span id="cb162-12"><a href="html-widgets.html#cb162-12"></a></span>
<span id="cb162-13"><a href="html-widgets.html#cb162-13"></a> <span class="co"><!-- Script to create visualsiation --></span></span>
<span id="cb162-14"><a href="html-widgets.html#cb162-14"></a> <span class="kw"><script></span></span>
<span id="cb162-15"><a href="html-widgets.html#cb162-15"></a> <span class="kw">var</span> el <span class="op">=</span> <span class="va">document</span>.<span class="at">getElementById</span>(<span class="st">'chart'</span>).<span class="at">getContext</span>(<span class="st">'2d'</span>)<span class="op">;</span> </span>
<span id="cb162-16"><a href="html-widgets.html#cb162-16"></a> <span class="kw">var</span> myChart <span class="op">=</span> <span class="kw">new</span> <span class="at">Chart</span>(el<span class="op">,</span> <span class="op">{</span></span>
<span id="cb162-17"><a href="html-widgets.html#cb162-17"></a> <span class="dt">type</span><span class="op">:</span> <span class="st">'bar'</span><span class="op">,</span></span>
<span id="cb162-18"><a href="html-widgets.html#cb162-18"></a> <span class="dt">data</span><span class="op">:</span> <span class="op">{</span></span>
<span id="cb162-19"><a href="html-widgets.html#cb162-19"></a> <span class="dt">labels</span><span class="op">:</span> [<span class="st">'Red'</span><span class="op">,</span> <span class="st">'Blue'</span><span class="op">,</span> <span class="st">'Yellow'</span><span class="op">,</span> <span class="st">'Green'</span><span class="op">,</span> <span class="st">'Purple'</span><span class="op">,</span> <span class="st">'Orange'</span>]<span class="op">,</span></span>
<span id="cb162-20"><a href="html-widgets.html#cb162-20"></a> <span class="dt">datasets</span><span class="op">:</span> [<span class="op">{</span></span>
<span id="cb162-21"><a href="html-widgets.html#cb162-21"></a> <span class="dt">label</span><span class="op">:</span> <span class="st">'# of Votes'</span><span class="op">,</span></span>
<span id="cb162-22"><a href="html-widgets.html#cb162-22"></a> <span class="dt">data</span><span class="op">:</span> [<span class="dv">12</span><span class="op">,</span> <span class="dv">19</span><span class="op">,</span> <span class="dv">3</span><span class="op">,</span> <span class="dv">5</span><span class="op">,</span> <span class="dv">2</span><span class="op">,</span> <span class="dv">3</span>]</span>
<span id="cb162-23"><a href="html-widgets.html#cb162-23"></a> <span class="op">}</span>]</span>
<span id="cb162-24"><a href="html-widgets.html#cb162-24"></a> <span class="op">}</span></span>
<span id="cb162-25"><a href="html-widgets.html#cb162-25"></a> <span class="op">}</span>)<span class="op">;</span></span>
<span id="cb162-26"><a href="html-widgets.html#cb162-26"></a> <span class="kw"></script></span></span>
<span id="cb162-27"><a href="html-widgets.html#cb162-27"></a><span class="kw"></body></span></span>
<span id="cb162-28"><a href="html-widgets.html#cb162-28"></a></span>
<span id="cb162-29"><a href="html-widgets.html#cb162-29"></a><span class="kw"></html></span></span></code></pre></div>
<p>We again observe a very similar structure as with previous libraries. The library is imported, instead of a <code>div</code> chart.js uses a <code>canvas</code>, and the visualisation is also created from a single function which takes the canvas as first argument and a JSON of options as second.</p>
<p>Hopefully this reveals the repeating structure such libraries tend to follow and also hints at should be reproduced, to some extent at least, using R.</p>
</div>
</div>
<div id="how-it-works" class="section level2 unnumbered" number="">
<h2>How it works</h2>
<p>Imagine there is no such package as HTML widgets to help create interactive visualisations from R: how would one attempt to go about it?</p>
<p>An interactive visualisation using JavaScript will will be contained within an HTML document, therefore it would probably have to be created first. Secondly, the visualisation that is yet to be created likely relies on external libraries, these would need to be imported in the document. The document should also include an HTML element (e.g.: <code><div></code>) to host said visualisation. Then data would have to be serialised in R and embedded into the document where it should be read by JavaScript code that uses it to create the visualisation. Finally all should be managed to work seamlessly across R markdown, shiny, and other settings.</p>
<p>Thankfully the htmlwidgets package is there to handle most of this. Nonetheless, it is important to understand that these operations are undertaken (to some degree) by htmlwidgets as it greatly helps use the package.</p>
<p>Must remember when building HTML widgets:</p>
<ul>
<li>Import dependencies</li>
<li>Create an html element to hold visualisation</li>
<li>Serialise R data to JSON</li>
<li>Handle JSON data to produce visualisation</li>
</ul>
</div>
<div id="the-scaffold" class="section level2 unnumbered" number="">
<h2>The Scaffold</h2>
<p>With some vague understanding of how such widgets work internally one is ready to “scaffold” one with the aim of rummaging through its components to grasp a greater understanding of how such interactive outputs are actually produced. The way one sets up such a package is stunningly simple. Below we create a package named “playground” which will be used to mess around and explore. Though one could probably create widgets outside of an R package, it would only make things more complicated.</p>
<div class="sourceCode" id="cb163"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb163-1"><a href="html-widgets.html#cb163-1"></a><span class="kw">create_package</span>(<span class="st">"playground"</span>)</span></code></pre></div>
<p>Then, from the root of the package created, we scaffold a widget which we call “play”.</p>
<div class="sourceCode" id="cb164"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb164-1"><a href="html-widgets.html#cb164-1"></a>htmlwidgets<span class="op">::</span><span class="kw">scaffoldWidget</span>(<span class="st">"play"</span>)</span></code></pre></div>
<p>This function puts together the minimalistic structure necessary to implement an HTML widget and opens <code>play.R</code>, <code>play.js</code> and <code>play.yaml</code> in the RStudio IDE or the default text editor. These files are named after the widget and will form the core of the package. The R file contains core functions of the R API, namely the <code>play</code> function which creates the widget itself, and the <code>render*</code> and <code>*output</code> functions that handle the widget in the shiny server and UI respectively. The <code>.js</code> file contains JavaScript functions that actually generate the visual output.</p>
<div class="sourceCode" id="cb165"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb165-1"><a href="html-widgets.html#cb165-1"></a>devtools<span class="op">::</span><span class="kw">document</span>()</span>
<span id="cb165-2"><a href="html-widgets.html#cb165-2"></a>devtools<span class="op">::</span><span class="kw">load_all</span>()</span></code></pre></div>
<p>It might be hard to believe, but at this stage one already has a fully functioning widget ready to use after documenting, and building the package. Indeed, the <code>play.R</code> file that that was created contains a function named “play” ẁhich takes, amongst other arguments, a message.</p>
<div class="sourceCode" id="cb166"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb166-1"><a href="html-widgets.html#cb166-1"></a><span class="kw">play</span>(<span class="dt">message =</span> <span class="st">"This is a widget!"</span>)</span></code></pre></div>
<div class="figure">
<img src="images/playground-1.png" alt="" />
<p class="caption">First HTML widget</p>
</div>
<p>This displays the message in the RStudio “Viewer,” or the your default browser which indicates that the function does indeed create an HTML output. One can use the the <img src="images/open-in-browser.png" /> button located in the top right of the RStudio “Viewer” to open the message in web browser which can prove very useful to look under the hood of the widgets for debugging.</p>
</div>
<div id="the-output" class="section level2 unnumbered" number="">
<h2>The Output</h2>
<p>With an out-of-the-box HTML widget package one can start exploring the internals to understand how it works. Let’s start by retracing the path taken by the message written in R to its seemingly magical appearance in HTML. The <code>play</code> function previously used, takes the <code>message</code> wraps it into a list which is then used in <code>htmlwidgets::createWidget</code>.</p>
<div class="sourceCode" id="cb167"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb167-1"><a href="html-widgets.html#cb167-1"></a><span class="co"># forward options using x</span></span>
<span id="cb167-2"><a href="html-widgets.html#cb167-2"></a>x =<span class="st"> </span><span class="kw">list</span>(</span>
<span id="cb167-3"><a href="html-widgets.html#cb167-3"></a> <span class="dt">message =</span> message</span>
<span id="cb167-4"><a href="html-widgets.html#cb167-4"></a>)</span></code></pre></div>
<p>Wrapping a string in a list might seem unnecessary but one will eventually add variables when building a more complex widget, starting with a list makes it easier to add them later on.</p>
<p>To investigate the widget we should look under the hood; the source code of the created (and rendered) output can be accessed in different ways, 1) by right-clicking on the message displayed in the RStudio Viewer and selecting “Inspect element,” or 2) by opening the visualisation in your browser using the <img src="images/open-in-browser.png" /> button located in the top right of the “Viewer,” and in the browser right clicking on the message to select “Inspect.” The latter is advised as web browsers such as Chrome or Firefox provide much friendlier interfaces for such functionalities as well as shortcuts to inspect or view the source code of a page.</p>
<p>Below is a part of the <code><body></code> of the output of <code>play("This is a widget!")</code> obtained with the method described in the previous paragraph.</p>
<div class="sourceCode" id="cb168"><pre class="sourceCode html"><code class="sourceCode html"><span id="cb168-1"><a href="html-widgets.html#cb168-1"></a><span class="kw"><div</span><span class="ot"> id=</span><span class="st">"htmlwidget_container"</span><span class="kw">></span></span>
<span id="cb168-2"><a href="html-widgets.html#cb168-2"></a> <span class="kw"><div</span><span class="ot"> id=</span><span class="st">"htmlwidget-c21cca0e76e520b46fc7"</span><span class="ot"> style=</span><span class="st">"width:960px;height:500px;"</span><span class="ot"> class=</span><span class="st">"play html-widget"</span><span class="kw">></span>This is a widget!<span class="kw"></div></span></span>
<span id="cb168-3"><a href="html-widgets.html#cb168-3"></a><span class="kw"></div></span></span>
<span id="cb168-4"><a href="html-widgets.html#cb168-4"></a><span class="kw"><script</span><span class="ot"> type=</span><span class="st">"application/json"</span><span class="ot"> data-for=</span><span class="st">"htmlwidget-c21cca0e76e520b46fc7"</span><span class="kw">></span><span class="op">{</span><span class="st">"x"</span><span class="op">:{</span><span class="st">"message"</span><span class="op">:</span><span class="st">"This is a widget!"</span><span class="op">},</span><span class="st">"evals"</span><span class="op">:</span>[]<span class="op">,</span><span class="st">"jsHooks"</span><span class="op">:</span>[]<span class="op">}</span><span class="kw"></script></span></span></code></pre></div>
<p>One thing the source code of the rendered output reveals is the element (<code>div</code>) created by the htmlwidgets package to hold the message (the class name is identical to that of the widget, <code>play</code>), as well as, below it, in the <code><script></code> tag, the JSON object which includes the <code>x</code> variable used in the <code>play</code> function. The <code>div</code> created bears a randomly generated <code>id</code> which one can define when creating the widget using the <code>elementId</code> argument.</p>
<div class="sourceCode" id="cb169"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb169-1"><a href="html-widgets.html#cb169-1"></a><span class="co"># specify the id</span></span>
<span id="cb169-2"><a href="html-widgets.html#cb169-2"></a><span class="kw">play</span>(<span class="st">"This is another widget"</span>, <span class="dt">elementId =</span> <span class="st">"myViz"</span>)</span></code></pre></div>
<div class="sourceCode" id="cb170"><pre class="sourceCode html"><code class="sourceCode html"><span id="cb170-1"><a href="html-widgets.html#cb170-1"></a><span class="co"><!-- div bears id specified in R --></span></span>
<span id="cb170-2"><a href="html-widgets.html#cb170-2"></a><span class="kw"><div</span><span class="ot"> id=</span><span class="st">"myViz"</span><span class="ot"> style=</span><span class="st">"width:960px;height:500px;"</span><span class="ot"> class=</span><span class="st">"play html-widget"</span><span class="kw">></span>This is another widget<span class="kw"></div></span></span></code></pre></div>
<p>You will also notice that this affects the <code>script</code> tag below it, the <code>data-for</code> attribute of which is also set to “myViz,” this indicates that it is used to tie the JSON data to a <code>div</code>, essential for htmlwidgets to manage multiple visualisation in R markdown or Shiny for instance. Then again, this happens in the background without the developer (you) having to worry about it.</p>
<div class="sourceCode" id="cb171"><pre class="sourceCode html"><code class="sourceCode html"><span id="cb171-1"><a href="html-widgets.html#cb171-1"></a><span class="kw"><script</span><span class="ot"> type=</span><span class="st">"application/json"</span><span class="ot"> data-for=</span><span class="st">"myViz"</span><span class="kw">></span><span class="op">{</span><span class="st">"x"</span><span class="op">:{</span><span class="st">"message"</span><span class="op">:</span><span class="st">"This is a widget!"</span><span class="op">},</span><span class="st">"evals"</span><span class="op">:</span>[]<span class="op">,</span><span class="st">"jsHooks"</span><span class="op">:</span>[]<span class="op">}</span><span class="kw"></script></span></span></code></pre></div>
<p>Inspecting the output also shows the dependencies imported, these are placed within the <code>head</code> HTML tags at the top of the page.</p>
<div class="sourceCode" id="cb172"><pre class="sourceCode html"><code class="sourceCode html"><span id="cb172-1"><a href="html-widgets.html#cb172-1"></a><span class="kw"><script</span><span class="ot"> src=</span><span class="st">"lib/htmlwidgets-1.5.1/htmlwidgets.js"</span><span class="kw">></script></span></span>
<span id="cb172-2"><a href="html-widgets.html#cb172-2"></a><span class="kw"><script</span><span class="ot"> src=</span><span class="st">"lib/play-binding-0.0.0.9000/play.js"</span><span class="kw">></script></span></span></code></pre></div>
<p>This effectively imports the <code>htmlwidgets.js</code> library as well as the <code>play.js</code> file, and were the visualisation depending on external libraries they would appear alongside those. Peaking inside the <code>play.js</code> file located at <code>inst/htmlwidgets/play.js</code> reveals the code below we see:</p>
<div class="sourceCode" id="cb173"><pre class="sourceCode js"><code class="sourceCode javascript"><span id="cb173-1"><a href="html-widgets.html#cb173-1"></a><span class="co">// play.js</span></span>
<span id="cb173-2"><a href="html-widgets.html#cb173-2"></a><span class="va">HTMLWidgets</span>.<span class="at">widget</span>(<span class="op">{</span></span>
<span id="cb173-3"><a href="html-widgets.html#cb173-3"></a></span>
<span id="cb173-4"><a href="html-widgets.html#cb173-4"></a> <span class="dt">name</span><span class="op">:</span> <span class="st">'play'</span><span class="op">,</span></span>
<span id="cb173-5"><a href="html-widgets.html#cb173-5"></a></span>
<span id="cb173-6"><a href="html-widgets.html#cb173-6"></a> <span class="dt">type</span><span class="op">:</span> <span class="st">'output'</span><span class="op">,</span></span>
<span id="cb173-7"><a href="html-widgets.html#cb173-7"></a></span>
<span id="cb173-8"><a href="html-widgets.html#cb173-8"></a> <span class="dt">factory</span><span class="op">:</span> <span class="kw">function</span>(el<span class="op">,</span> width<span class="op">,</span> height) <span class="op">{</span></span>
<span id="cb173-9"><a href="html-widgets.html#cb173-9"></a></span>
<span id="cb173-10"><a href="html-widgets.html#cb173-10"></a> <span class="co">// </span><span class="al">TODO</span><span class="co">: define shared variables for this instance</span></span>
<span id="cb173-11"><a href="html-widgets.html#cb173-11"></a></span>
<span id="cb173-12"><a href="html-widgets.html#cb173-12"></a> <span class="cf">return</span> <span class="op">{</span></span>
<span id="cb173-13"><a href="html-widgets.html#cb173-13"></a></span>
<span id="cb173-14"><a href="html-widgets.html#cb173-14"></a> <span class="dt">renderValue</span><span class="op">:</span> <span class="kw">function</span>(x) <span class="op">{</span></span>
<span id="cb173-15"><a href="html-widgets.html#cb173-15"></a></span>
<span id="cb173-16"><a href="html-widgets.html#cb173-16"></a> <span class="co">// </span><span class="al">TODO</span><span class="co">: code to render the widget, e.g.</span></span>
<span id="cb173-17"><a href="html-widgets.html#cb173-17"></a> <span class="va">el</span>.<span class="at">innerText</span> <span class="op">=</span> <span class="va">x</span>.<span class="at">message</span><span class="op">;</span></span>
<span id="cb173-18"><a href="html-widgets.html#cb173-18"></a></span>
<span id="cb173-19"><a href="html-widgets.html#cb173-19"></a> <span class="op">},</span></span>
<span id="cb173-20"><a href="html-widgets.html#cb173-20"></a></span>
<span id="cb173-21"><a href="html-widgets.html#cb173-21"></a> <span class="dt">resize</span><span class="op">:</span> <span class="kw">function</span>(width<span class="op">,</span> height) <span class="op">{</span></span>
<span id="cb173-22"><a href="html-widgets.html#cb173-22"></a></span>
<span id="cb173-23"><a href="html-widgets.html#cb173-23"></a> <span class="co">// </span><span class="al">TODO</span><span class="co">: code to re-render the widget with a new size</span></span>
<span id="cb173-24"><a href="html-widgets.html#cb173-24"></a></span>
<span id="cb173-25"><a href="html-widgets.html#cb173-25"></a> <span class="op">}</span></span>
<span id="cb173-26"><a href="html-widgets.html#cb173-26"></a></span>
<span id="cb173-27"><a href="html-widgets.html#cb173-27"></a> <span class="op">};</span></span>
<span id="cb173-28"><a href="html-widgets.html#cb173-28"></a> <span class="op">}</span></span>
<span id="cb173-29"><a href="html-widgets.html#cb173-29"></a><span class="op">}</span>)<span class="op">;</span></span></code></pre></div>
<p>However convoluted this may appear at first do not let that intimate you. The <code>factory</code> function returns two functions, one of which, <code>resize</code>, is currently empty, let’s therefore look at the other one first, <code>renderValue</code>: the function that in fact renders the visualisation. It takes an object <code>x</code> from which is accesses the “message” variable that it uses as text for object <code>el</code> (<code>el.innerText</code>). The object <code>x</code> passed to this function is actually the list of the same name that was build in the R function <code>play</code>! While in R one would access the <code>message</code> in list <code>x</code> with <code>x$message</code> in JavaScript to access the <code>message</code> in the JSON <code>x</code> one writes <code>x.message</code>, only changing the dollar sign to a dot. Let’s show this perhaps more clearly by printing the content of <code>x</code>.</p>
<div class="sourceCode" id="cb174"><pre class="sourceCode js"><code class="sourceCode javascript"><span id="cb174-1"><a href="html-widgets.html#cb174-1"></a><span class="va">console</span>.<span class="at">log</span>(x)<span class="op">;</span></span>
<span id="cb174-2"><a href="html-widgets.html#cb174-2"></a><span class="va">el</span>.<span class="at">innerText</span> <span class="op">=</span> <span class="va">x</span>.<span class="at">message</span><span class="op">;</span></span></code></pre></div>
<p>We place <code>console.log</code> to print the content of <code>x</code> in the console, reload the package with <code>devtools::load_all</code> and use the function <code>play</code> again then explore the console from the browser (inspect and go to the “console” tab).</p>
<div class="figure">
<img src="images/playground-console-x.png" alt="" />
<p class="caption">Console tab output</p>
</div>
<p>This displays the JSON object containing the message: it looks eerily similar to the list that was created in R (<code>x = list(message = "This is a widget!")</code>). What one should take away from this is that data that needs to be communicated from R to the JavaScript function should be placed in the R list <code>x</code>. This list is serialised to JSON and placed in the HTML output in a <code>script</code> tag with a <code>data-for</code> attribute. This attribute indicates which widget the data is destined for. This effectively enables htmlwidgets to match the serialised data with the output elements: data in <code><script data-for='viz'></code> is to be used to create a visualisation in <code><div id='viz'></code>.</p>
<p>Before we move on to other things one should also grasp a better understanding of the <code>el</code> object, which can also be logged in the console.</p>
<div class="sourceCode" id="cb175"><pre class="sourceCode js"><code class="sourceCode javascript"><span id="cb175-1"><a href="html-widgets.html#cb175-1"></a><span class="va">console</span>.<span class="at">log</span>(x)<span class="op">;</span></span>
<span id="cb175-2"><a href="html-widgets.html#cb175-2"></a><span class="va">console</span>.<span class="at">log</span>(el)<span class="op">;</span></span>
<span id="cb175-3"><a href="html-widgets.html#cb175-3"></a><span class="va">el</span>.<span class="at">innerText</span> <span class="op">=</span> <span class="va">x</span>.<span class="at">message</span><span class="op">;</span></span></code></pre></div>
<div class="figure">
<img src="images/playground-console-el.png" alt="" />
<p class="caption">Console tab output</p>
</div>
<p>This displays the HTML element created by htmlwidgets that is meant to hold the visualisation, or in this case, the message. If you are familiar with JavaScript, this is the element that would be returned by <code>document.getElementById</code>. This object allows manipulating the element in pretty much any way imaginable, change its position, its colour, its size, or, as done here, to insert some text in its place. What’s more one can access attributes of the object just like a JSON array. Therefore one can log the <code>id</code> of the element.</p>
<div class="sourceCode" id="cb176"><pre class="sourceCode js"><code class="sourceCode javascript"><span id="cb176-1"><a href="html-widgets.html#cb176-1"></a><span class="co">// print the id of the element</span></span>
<span id="cb176-2"><a href="html-widgets.html#cb176-2"></a><span class="va">console</span>.<span class="at">log</span>(<span class="va">el</span>.<span class="at">id</span>)<span class="op">;</span></span>
<span id="cb176-3"><a href="html-widgets.html#cb176-3"></a><span class="va">el</span>.<span class="at">innerText</span> <span class="op">=</span> <span class="va">x</span>.<span class="at">message</span><span class="op">;</span></span></code></pre></div>
<p>Making the modifications above and reloading the package, one can create a widget given a specific id and see it displayed in the console, e.g.: <code>play("hello", elementId = "see-you-in-the-console")</code>.</p>
<p>In an attempt to become more at ease with this setup let us change something and play with the widget. Out-of-the-box htmlwidgets uses <code>innerText</code>, which does very much what it says on the tin, it places text inside an element. JavaScript comes with another function akin to <code>innerText</code>, <code>innerHTML</code>. While the former only allows inserting text the former lets one insert any HTML.</p>
<div class="sourceCode" id="cb177"><pre class="sourceCode js"><code class="sourceCode javascript"><span id="cb177-1"><a href="html-widgets.html#cb177-1"></a><span class="va">el</span>.<span class="at">innerHTML</span> <span class="op">=</span> <span class="va">x</span>.<span class="at">message</span><span class="op">;</span></span></code></pre></div>
<p>After changing the <code>play.js</code> file as above, and re-loading the package, one can use arbitrary HTML as messages.</p>
<div class="sourceCode" id="cb178"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb178-1"><a href="html-widgets.html#cb178-1"></a><span class="kw">play</span>(<span class="st">"<h1>Using HTML!</h1>"</span>)</span></code></pre></div>
<div class="figure">
<img src="images/playground-h1.png" alt="" />
<p class="caption">Widget output</p>
</div>
<p>That makes for a great improvement which opens the door to many possibilities. However, the interface this provides is unintuitive. Albeit similar, R users are more familiar with shiny and htmltools <span class="citation">(RStudio and Inc. <a href="#ref-R-htmltools" role="doc-biblioref">2019</a>)</span> tags than HTML tags, e.g.: <code><h1></h1></code> translates to <code>h1()</code> in R. The package should allow users to use those instead of forcing them to collapse HTML content in a string. Fortunately, there is a very easy way to obtain the HTML from those functions: convert it to a character string.</p>
<div class="sourceCode" id="cb179"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb179-1"><a href="html-widgets.html#cb179-1"></a>html <-<span class="st"> </span>shiny<span class="op">::</span><span class="kw">h1</span>(<span class="st">"HTML tag"</span>)</span>
<span id="cb179-2"><a href="html-widgets.html#cb179-2"></a></span>
<span id="cb179-3"><a href="html-widgets.html#cb179-3"></a><span class="kw">class</span>(html)</span></code></pre></div>
<pre><code>## [1] "shiny.tag"</code></pre>
<div class="sourceCode" id="cb181"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb181-1"><a href="html-widgets.html#cb181-1"></a><span class="co"># returns string</span></span>
<span id="cb181-2"><a href="html-widgets.html#cb181-2"></a><span class="kw">as.character</span>(html)</span></code></pre></div>
<pre><code>## [1] "<h1>HTML tag</h1>"</code></pre>
<p>Implementing this in the <code>play</code> function will look like this.</p>
<div class="sourceCode" id="cb183"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb183-1"><a href="html-widgets.html#cb183-1"></a><span class="co"># forward options using x</span></span>
<span id="cb183-2"><a href="html-widgets.html#cb183-2"></a>x =<span class="st"> </span><span class="kw">list</span>(</span>
<span id="cb183-3"><a href="html-widgets.html#cb183-3"></a> <span class="dt">message =</span> <span class="kw">as.character</span>(message)</span>
<span id="cb183-4"><a href="html-widgets.html#cb183-4"></a>)</span></code></pre></div>
<p>Reloading the package with <code>devtools::load_all</code> lets one use shiny tags as the message.</p>
<div class="sourceCode" id="cb184"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb184-1"><a href="html-widgets.html#cb184-1"></a><span class="kw">play</span>(shiny<span class="op">::</span><span class="kw">h2</span>(<span class="st">"Chocolate is a colour"</span>, <span class="dt">style =</span> <span class="st">"color:chocolate;"</span>))</span></code></pre></div>
<div class="figure">
<img src="images/playground-color.png" alt="" />
<p class="caption">Using shiny tags</p>
</div>
<p>This hopefully provides some understanding of how htmlwidgets work internally and thereby helps building such packages. To recapitulate, an HTML document is created in which div is placed and given a certain id, this id is also used in a script tag that contains JSON data passed from R so that a JavaScript function we define can read that data in and use it to generate a visual output in a div. However, as much as this section covered, the topic of JavaScript dependencies was not touched, this is approached in the following section where we build another, more interesting widget, which uses an external dependency.</p>
</div>
<div id="typed.js" class="section level2 unnumbered" number="">
<h2>Typed.js</h2>
<p>In this section we build a package called <code>typed</code>, which wraps the JavaScript library of the same name, <a href="https://github.com/mattboldt/typed.js/">typed.js</a> that mimics text being typed. This builds upon many things we explored in the playground package.</p>
<div class="sourceCode" id="cb185"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb185-1"><a href="html-widgets.html#cb185-1"></a>usethis<span class="op">::</span><span class="kw">create_package</span>(<span class="st">"typed"</span>)</span>
<span id="cb185-2"><a href="html-widgets.html#cb185-2"></a>htmlwidgets<span class="op">::</span><span class="kw">scaffoldWidget</span>(<span class="st">"typed"</span>)</span></code></pre></div>
<p>As done with candidate libraries, let’s take a look at documentation of <a href="https://github.com/mattboldt/typed.js/">typed.js</a> to see how typed.js works.</p>
<div class="sourceCode" id="cb186"><pre class="sourceCode html"><code class="sourceCode html"><span id="cb186-1"><a href="html-widgets.html#cb186-1"></a><span class="dt"><!DOCTYPE </span>html<span class="dt">></span></span>
<span id="cb186-2"><a href="html-widgets.html#cb186-2"></a><span class="kw"><html</span><span class="ot"> xmlns=</span><span class="st">"http://www.w3.org/1999/xhtml"</span><span class="ot"> lang=</span><span class="st">""</span><span class="ot"> xml:lang=</span><span class="st">""</span><span class="kw">></span></span>
<span id="cb186-3"><a href="html-widgets.html#cb186-3"></a></span>
<span id="cb186-4"><a href="html-widgets.html#cb186-4"></a><span class="kw"><head></span></span>
<span id="cb186-5"><a href="html-widgets.html#cb186-5"></a> <span class="co"><!-- Import library --></span></span>
<span id="cb186-6"><a href="html-widgets.html#cb186-6"></a> <span class="kw"><script</span><span class="ot"> src=</span><span class="st">"typed.js"</span><span class="kw">></script></span></span>
<span id="cb186-7"><a href="html-widgets.html#cb186-7"></a><span class="kw"></head></span></span>
<span id="cb186-8"><a href="html-widgets.html#cb186-8"></a></span>
<span id="cb186-9"><a href="html-widgets.html#cb186-9"></a><span class="kw"><body></span></span>
<span id="cb186-10"><a href="html-widgets.html#cb186-10"></a> <span class="co"><!-- div to hold visualisation --></span></span>
<span id="cb186-11"><a href="html-widgets.html#cb186-11"></a> <span class="kw"><div</span><span class="ot"> class=</span><span class="st">"element"</span><span class="kw">></div></span></span>
<span id="cb186-12"><a href="html-widgets.html#cb186-12"></a></span>
<span id="cb186-13"><a href="html-widgets.html#cb186-13"></a> <span class="co"><!-- Script to create visualsiation --></span></span>
<span id="cb186-14"><a href="html-widgets.html#cb186-14"></a> <span class="kw"><script></span></span>
<span id="cb186-15"><a href="html-widgets.html#cb186-15"></a> <span class="kw">var</span> typed <span class="op">=</span> <span class="kw">new</span> <span class="at">Typed</span>(<span class="st">'.element'</span><span class="op">,</span> <span class="op">{</span></span>
<span id="cb186-16"><a href="html-widgets.html#cb186-16"></a> <span class="dt">strings</span><span class="op">:</span> [<span class="st">'First sentence.'</span><span class="op">,</span> <span class="st">'And a second sentence.'</span>]</span>
<span id="cb186-17"><a href="html-widgets.html#cb186-17"></a> <span class="op">}</span>)<span class="op">;</span></span>
<span id="cb186-18"><a href="html-widgets.html#cb186-18"></a> <span class="kw"></script></span></span>
<span id="cb186-19"><a href="html-widgets.html#cb186-19"></a><span class="kw"></body></span></span>
<span id="cb186-20"><a href="html-widgets.html#cb186-20"></a></span>
<span id="cb186-21"><a href="html-widgets.html#cb186-21"></a><span class="kw"></html></span></span></code></pre></div>
<p>The code above is not very different from what was observed in other libraries: the library is imported, there is a <code><div></code> where the output will be generated, and a script which also takes a selector and a JSON of options.</p>
<div id="dependency" class="section level3 unnumbered" number="">
<h3>Dependency</h3>
<p>Once the package created and the widget scaffold laid down we need to add the JavaScript dependency without which nothing can move forward. The <a href="https://github.com/mattboldt/typed.js">documentation in the README of typed.js</a> states that it can be imported like so.</p>
<div class="sourceCode" id="cb187"><pre class="sourceCode html"><code class="sourceCode html"><span id="cb187-1"><a href="html-widgets.html#cb187-1"></a><span class="kw"><script</span><span class="ot"> src=</span><span class="st">"https://cdn.jsdelivr.net/npm/[email protected]"</span><span class="kw">></script></span></span></code></pre></div>
<p>First, we will download the dependency, which consists of a single JavaScript file, instead of using the CDN as this ultimately makes the package more robust (more easily reproducible outputs and no requirement for internet connection). Below we place the dependency in a “typed” directory within the “htmlwidgets” folder.</p>
<div class="sourceCode" id="cb188"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb188-1"><a href="html-widgets.html#cb188-1"></a><span class="kw">dir.create</span>(<span class="st">"./inst/htmlwidgets/typed"</span>)</span>
<span id="cb188-2"><a href="html-widgets.html#cb188-2"></a>cdn <-<span class="st"> "https://cdn.jsdelivr.net/npm/[email protected]"</span></span>
<span id="cb188-3"><a href="html-widgets.html#cb188-3"></a><span class="kw">download.file</span>(cdn, <span class="st">"./inst/htmlwidgets/typed/typed.min.js"</span>)</span></code></pre></div>
<p>This produces a directory that looks like this:</p>
<pre><code>.
├── DESCRIPTION
├── NAMESPACE
├── R
│ └── typed.R
└── inst
└── htmlwidgets
├── typed
│ └── typed.min.js
├── typed.js
└── typed.yaml</code></pre>
<p>In htmlwidgets packages dependencies are specified in the <code>.yml</code> file located at <code>inst/htmlwidgets</code> which at first contains a commented template.</p>
<div class="sourceCode" id="cb190"><pre class="sourceCode yml"><code class="sourceCode yaml"><span id="cb190-1"><a href="html-widgets.html#cb190-1"></a><span class="co"># (uncomment to add a dependency)</span></span>
<span id="cb190-2"><a href="html-widgets.html#cb190-2"></a><span class="co"># dependencies:</span></span>
<span id="cb190-3"><a href="html-widgets.html#cb190-3"></a><span class="co"># - name:</span></span>
<span id="cb190-4"><a href="html-widgets.html#cb190-4"></a><span class="co"># version:</span></span>
<span id="cb190-5"><a href="html-widgets.html#cb190-5"></a><span class="co"># src:</span></span>
<span id="cb190-6"><a href="html-widgets.html#cb190-6"></a><span class="co"># script:</span></span>
<span id="cb190-7"><a href="html-widgets.html#cb190-7"></a><span class="co"># stylesheet:</span></span></code></pre></div>
<p>Let’s uncomment those lines as instructed at the top of the file and fill it in.</p>
<div class="sourceCode" id="cb191"><pre class="sourceCode yml"><code class="sourceCode yaml"><span id="cb191-1"><a href="html-widgets.html#cb191-1"></a><span class="fu">dependencies</span><span class="kw">:</span></span>
<span id="cb191-2"><a href="html-widgets.html#cb191-2"></a><span class="at"> </span><span class="kw">-</span><span class="at"> </span><span class="fu">name</span><span class="kw">:</span><span class="at"> typed.js</span></span>
<span id="cb191-3"><a href="html-widgets.html#cb191-3"></a><span class="at"> </span><span class="fu">version</span><span class="kw">:</span><span class="at"> </span><span class="fl">2.0.11</span></span>
<span id="cb191-4"><a href="html-widgets.html#cb191-4"></a><span class="at"> </span><span class="fu">src</span><span class="kw">:</span><span class="at"> htmlwidgets/typed</span></span>
<span id="cb191-5"><a href="html-widgets.html#cb191-5"></a><span class="at"> </span><span class="fu">script</span><span class="kw">:</span><span class="at"> typed.min.js</span></span></code></pre></div>
<p>We remove the <code>stylesheet</code> entry as this package does not require any CSS files. The <code>src</code> specifies the path to the directory containing the scripts and stylesheets. This is akin to using the <code>system.file</code> function to return the full path to a file or directory within the package.</p>
<div class="sourceCode" id="cb192"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb192-1"><a href="html-widgets.html#cb192-1"></a>devtools<span class="op">::</span><span class="kw">load_all</span>()</span>
<span id="cb192-2"><a href="html-widgets.html#cb192-2"></a><span class="kw">system.file</span>(<span class="st">"htmlwidgets/typed"</span>, <span class="dt">package =</span> <span class="st">"typed"</span>) </span>
<span id="cb192-3"><a href="html-widgets.html#cb192-3"></a><span class="co">#> "/home/me/packages/typed/inst/htmlwidgets/typed"</span></span></code></pre></div>
<p>We should verify that this is correct by using the one R function the package features and check the source code of the output to verify that the typed.js is indeed imported. We thus run <code>typed("test")</code>, open the output in the browser (<img src="images/open-in-browser.png" />) and look at the source code of the page (right click and select “View page source”). At the top of the page one should see <code>typed.min.js</code> imported, click the link to ensure it correctly points to the dependency.</p>
<div class="sourceCode" id="cb193"><pre class="sourceCode html"><code class="sourceCode html"><span id="cb193-1"><a href="html-widgets.html#cb193-1"></a><span class="dt"><!DOCTYPE </span>html<span class="dt">></span></span>
<span id="cb193-2"><a href="html-widgets.html#cb193-2"></a><span class="kw"><html></span></span>
<span id="cb193-3"><a href="html-widgets.html#cb193-3"></a><span class="kw"><head></span></span>
<span id="cb193-4"><a href="html-widgets.html#cb193-4"></a><span class="kw"><meta</span><span class="ot"> charset=</span><span class="st">"utf-8"</span><span class="kw">/></span></span>
<span id="cb193-5"><a href="html-widgets.html#cb193-5"></a><span class="kw"><style></span>body{<span class="kw">background-color</span>:<span class="cn">white</span><span class="op">;</span>}<span class="kw"></style></span></span>
<span id="cb193-6"><a href="html-widgets.html#cb193-6"></a><span class="kw"><script</span><span class="ot"> src=</span><span class="st">"lib/htmlwidgets-1.5.1/htmlwidgets.js"</span><span class="kw">></script></span></span>
<span id="cb193-7"><a href="html-widgets.html#cb193-7"></a><span class="kw"><script</span><span class="ot"> src=</span><span class="st">"lib/typed.js-2.0.11/typed.min.js"</span><span class="kw">></script></span></span>
<span id="cb193-8"><a href="html-widgets.html#cb193-8"></a><span class="kw"><script</span><span class="ot"> src=</span><span class="st">"lib/typed-binding-0.0.0.9000/typed.js"</span><span class="kw">></script></span></span>
<span id="cb193-9"><a href="html-widgets.html#cb193-9"></a>...</span></code></pre></div>
</div>
<div id="javascript-1" class="section level3 unnumbered" number="">
<h3>JavaScript</h3>
<p>On its <a href="https://mattboldt.com/demos/typed-js/">official website</a>, typed.js gives the following example. The JavaScript function <code>Typed</code> takes two arguments, first the selector, the element to hold the output, second a JSON of options to specify what is being typed and a myriad of other things.</p>
<div class="sourceCode" id="cb194"><pre class="sourceCode js"><code class="sourceCode javascript"><span id="cb194-1"><a href="html-widgets.html#cb194-1"></a><span class="kw">var</span> typed <span class="op">=</span> <span class="kw">new</span> <span class="at">Typed</span>(<span class="st">'.element'</span><span class="op">,</span> <span class="op">{</span></span>
<span id="cb194-2"><a href="html-widgets.html#cb194-2"></a> <span class="dt">strings</span><span class="op">:</span> [<span class="st">"First sentence."</span><span class="op">,</span> <span class="st">"Second sentence."</span>]<span class="op">,</span></span>
<span id="cb194-3"><a href="html-widgets.html#cb194-3"></a> <span class="dt">typeSpeed</span><span class="op">:</span> <span class="dv">30</span></span>
<span id="cb194-4"><a href="html-widgets.html#cb194-4"></a><span class="op">}</span>)<span class="op">;</span></span></code></pre></div>
<p>Let’s place it in the package by replacing the content of the <code>renderValue</code> in <code>typed.js</code> with the above.</p>
<div class="sourceCode" id="cb195"><pre class="sourceCode js"><code class="sourceCode javascript"><span id="cb195-1"><a href="html-widgets.html#cb195-1"></a>...</span>
<span id="cb195-2"><a href="html-widgets.html#cb195-2"></a>renderValue<span class="op">:</span> <span class="kw">function</span>(x) <span class="op">{</span></span>
<span id="cb195-3"><a href="html-widgets.html#cb195-3"></a></span>
<span id="cb195-4"><a href="html-widgets.html#cb195-4"></a> <span class="kw">var</span> typed <span class="op">=</span> <span class="kw">new</span> <span class="at">Typed</span>(<span class="st">'.element'</span><span class="op">,</span> <span class="op">{</span></span>
<span id="cb195-5"><a href="html-widgets.html#cb195-5"></a> <span class="dt">strings</span><span class="op">:</span> [<span class="st">"First sentence."</span><span class="op">,</span> <span class="st">"Second sentence."</span>]<span class="op">,</span></span>
<span id="cb195-6"><a href="html-widgets.html#cb195-6"></a> <span class="dt">typeSpeed</span><span class="op">:</span> <span class="dv">30</span></span>
<span id="cb195-7"><a href="html-widgets.html#cb195-7"></a> <span class="op">}</span>)<span class="op">;</span></span>
<span id="cb195-8"><a href="html-widgets.html#cb195-8"></a></span>
<span id="cb195-9"><a href="html-widgets.html#cb195-9"></a><span class="op">}</span></span>
<span id="cb195-10"><a href="html-widgets.html#cb195-10"></a>...</span></code></pre></div>
<p>One could be tempted to run <code>devtools::load_all</code> but this will not work, namely because the function uses a selector that is will not return any object; it needs to be applied to the div created by the widget not <code>.element</code>. As hinted at in the playground, the selector of the element created is accessible from the <code>el</code> object. As a matter of fact, we did log in the browser console the id of the created div taken from <code>el.id</code>. Therefore concatenating the pound sign and the element id produces the select to said element. (<code>.class</code>, <code>#id</code>)</p>
<div class="sourceCode" id="cb196"><pre class="sourceCode js"><code class="sourceCode javascript"><span id="cb196-1"><a href="html-widgets.html#cb196-1"></a><span class="co">// typed.js</span></span>
<span id="cb196-2"><a href="html-widgets.html#cb196-2"></a>...</span>
<span id="cb196-3"><a href="html-widgets.html#cb196-3"></a>renderValue<span class="op">:</span> <span class="kw">function</span>(x) <span class="op">{</span></span>
<span id="cb196-4"><a href="html-widgets.html#cb196-4"></a></span>
<span id="cb196-5"><a href="html-widgets.html#cb196-5"></a> <span class="kw">var</span> typed <span class="op">=</span> <span class="kw">new</span> <span class="at">Typed</span>(<span class="st">'#'</span> <span class="op">+</span> <span class="va">el</span>.<span class="at">id</span><span class="op">,</span> <span class="op">{</span></span>
<span id="cb196-6"><a href="html-widgets.html#cb196-6"></a> <span class="dt">strings</span><span class="op">:</span> [<span class="st">"First sentence."</span><span class="op">,</span> <span class="st">"Second sentence."</span>]<span class="op">,</span></span>
<span id="cb196-7"><a href="html-widgets.html#cb196-7"></a> <span class="dt">typeSpeed</span><span class="op">:</span> <span class="dv">30</span></span>
<span id="cb196-8"><a href="html-widgets.html#cb196-8"></a> <span class="op">}</span>)<span class="op">;</span></span>
<span id="cb196-9"><a href="html-widgets.html#cb196-9"></a></span>
<span id="cb196-10"><a href="html-widgets.html#cb196-10"></a><span class="op">}</span></span>
<span id="cb196-11"><a href="html-widgets.html#cb196-11"></a>...</span></code></pre></div>
<p>This should now work, run <code>devtools::load_all</code> followed by <code>typed("whatever")</code> and the JavaScript animated text will appear! It’s not of any use just yet as the options, included the text being typed is predefined: the package is currently not making any use the of the inputs passed from R. Below change the default strings to <code>x.message</code>.</p>
<div class="sourceCode" id="cb197"><pre class="sourceCode js"><code class="sourceCode javascript"><span id="cb197-1"><a href="html-widgets.html#cb197-1"></a><span class="co">// typed.js</span></span>
<span id="cb197-2"><a href="html-widgets.html#cb197-2"></a>...</span>
<span id="cb197-3"><a href="html-widgets.html#cb197-3"></a>renderValue<span class="op">:</span> <span class="kw">function</span>(x) <span class="op">{</span></span>
<span id="cb197-4"><a href="html-widgets.html#cb197-4"></a></span>
<span id="cb197-5"><a href="html-widgets.html#cb197-5"></a> <span class="kw">var</span> typed <span class="op">=</span> <span class="kw">new</span> <span class="at">Typed</span>(<span class="st">'#'</span> <span class="op">+</span> <span class="va">el</span>.<span class="at">id</span><span class="op">,</span> <span class="op">{</span></span>
<span id="cb197-6"><a href="html-widgets.html#cb197-6"></a> <span class="dt">strings</span><span class="op">:</span> <span class="va">x</span>.<span class="at">message</span><span class="op">,</span></span>
<span id="cb197-7"><a href="html-widgets.html#cb197-7"></a> <span class="dt">typeSpeed</span><span class="op">:</span> <span class="dv">30</span></span>
<span id="cb197-8"><a href="html-widgets.html#cb197-8"></a> <span class="op">}</span>)<span class="op">;</span></span>
<span id="cb197-9"><a href="html-widgets.html#cb197-9"></a></span>
<span id="cb197-10"><a href="html-widgets.html#cb197-10"></a><span class="op">}</span></span>
<span id="cb197-11"><a href="html-widgets.html#cb197-11"></a>...</span></code></pre></div>
<p>This, however, will cause issues as the <code>strings</code> options expects and array (vector) and not a single string. This is something often forgotten when working with R, there is no scalar values, in R a scalar is vector of length 1.</p>
<div class="sourceCode" id="cb198"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb198-1"><a href="html-widgets.html#cb198-1"></a><span class="kw">typed</span>(<span class="st">"does not work"</span>) <span class="co"># length = 1</span></span>
<span id="cb198-2"><a href="html-widgets.html#cb198-2"></a><span class="kw">typed</span>(<span class="kw">c</span>(<span class="st">"This"</span>, <span class="st">"will"</span>, <span class="st">"work"</span>)) <span class="co"># length > 1</span></span></code></pre></div>
<p>One solution is to force the input into a list.</p>
<div class="sourceCode" id="cb199"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb199-1"><a href="html-widgets.html#cb199-1"></a><span class="co"># typed.R</span></span>
<span id="cb199-2"><a href="html-widgets.html#cb199-2"></a>x =<span class="st"> </span><span class="kw">list</span>(</span>
<span id="cb199-3"><a href="html-widgets.html#cb199-3"></a> <span class="dt">message =</span> <span class="kw">as.list</span>(message)</span>
<span id="cb199-4"><a href="html-widgets.html#cb199-4"></a>)</span></code></pre></div>
<p>At this juncture the package works but there is a salient issue with the way it handles options. Why build a list in R to reconstruct it in JavaScript manually. Since the options are serialised in R to JSON and that typed.js expects a JSON of options it is actually cleaner and more convenient to construct an R list that mirrors the JSON array so one can use is as-is in JavaScript.</p>
<p>In fact, renaming the <code>message</code> to <code>strings</code> effectively does this.</p>
<div class="sourceCode" id="cb200"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb200-1"><a href="html-widgets.html#cb200-1"></a><span class="co"># typed.R</span></span>
<span id="cb200-2"><a href="html-widgets.html#cb200-2"></a>x =<span class="st"> </span><span class="kw">list</span>(</span>
<span id="cb200-3"><a href="html-widgets.html#cb200-3"></a> <span class="dt">strings =</span> <span class="kw">as.list</span>(message)</span>
<span id="cb200-4"><a href="html-widgets.html#cb200-4"></a>)</span></code></pre></div>
<p>This allows greatly simplifying the code JavaScript side, making it much easier to add other options down the line, maintain, debug, and read.</p>
<div class="sourceCode" id="cb201"><pre class="sourceCode js"><code class="sourceCode javascript"><span id="cb201-1"><a href="html-widgets.html#cb201-1"></a><span class="co">// typed.js</span></span>
<span id="cb201-2"><a href="html-widgets.html#cb201-2"></a>...</span>
<span id="cb201-3"><a href="html-widgets.html#cb201-3"></a>renderValue<span class="op">:</span> <span class="kw">function</span>(x) <span class="op">{</span></span>
<span id="cb201-4"><a href="html-widgets.html#cb201-4"></a></span>
<span id="cb201-5"><a href="html-widgets.html#cb201-5"></a> <span class="kw">var</span> typed <span class="op">=</span> <span class="kw">new</span> <span class="at">Typed</span>(<span class="st">'#'</span> <span class="op">+</span> <span class="va">el</span>.<span class="at">id</span><span class="op">,</span> x)<span class="op">;</span></span>
<span id="cb201-6"><a href="html-widgets.html#cb201-6"></a></span>
<span id="cb201-7"><a href="html-widgets.html#cb201-7"></a><span class="op">}</span></span>
<span id="cb201-8"><a href="html-widgets.html#cb201-8"></a>...</span></code></pre></div>
<p>One can now add more options from the R code without having to alter any of the JavaScript. Let us demonstrate with the <code>loop</code> option.</p>
<div class="sourceCode" id="cb202"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb202-1"><a href="html-widgets.html#cb202-1"></a>typed <-<span class="st"> </span><span class="cf">function</span>(message, <span class="dt">loop =</span> <span class="ot">FALSE</span>, <span class="dt">width =</span> <span class="ot">NULL</span>, <span class="dt">height =</span> <span class="ot">NULL</span>, <span class="dt">elementId =</span> <span class="ot">NULL</span>) {</span>
<span id="cb202-2"><a href="html-widgets.html#cb202-2"></a></span>
<span id="cb202-3"><a href="html-widgets.html#cb202-3"></a> <span class="co"># forward options using x</span></span>
<span id="cb202-4"><a href="html-widgets.html#cb202-4"></a> x =<span class="st"> </span><span class="kw">list</span>(</span>
<span id="cb202-5"><a href="html-widgets.html#cb202-5"></a> <span class="dt">loop =</span> loop,</span>
<span id="cb202-6"><a href="html-widgets.html#cb202-6"></a> <span class="dt">strings =</span> <span class="kw">as.list</span>(message)</span>
<span id="cb202-7"><a href="html-widgets.html#cb202-7"></a> )</span>
<span id="cb202-8"><a href="html-widgets.html#cb202-8"></a></span>
<span id="cb202-9"><a href="html-widgets.html#cb202-9"></a> <span class="co"># create widget</span></span>
<span id="cb202-10"><a href="html-widgets.html#cb202-10"></a> htmlwidgets<span class="op">::</span><span class="kw">createWidget</span>(</span>
<span id="cb202-11"><a href="html-widgets.html#cb202-11"></a> <span class="dt">name =</span> <span class="st">'typed'</span>,</span>
<span id="cb202-12"><a href="html-widgets.html#cb202-12"></a> x,</span>
<span id="cb202-13"><a href="html-widgets.html#cb202-13"></a> <span class="dt">width =</span> width,</span>
<span id="cb202-14"><a href="html-widgets.html#cb202-14"></a> <span class="dt">height =</span> height,</span>
<span id="cb202-15"><a href="html-widgets.html#cb202-15"></a> <span class="dt">package =</span> <span class="st">'typed'</span>,</span>
<span id="cb202-16"><a href="html-widgets.html#cb202-16"></a> <span class="dt">elementId =</span> elementId</span>
<span id="cb202-17"><a href="html-widgets.html#cb202-17"></a> )</span>
<span id="cb202-18"><a href="html-widgets.html#cb202-18"></a>}</span></code></pre></div>
</div>
<div id="html-element" class="section level3 unnumbered" number="">
<h3>HTML Element</h3>
<p>As pointed out multiple times, the widget is generated in a <code><div></code>, which is works fine for most visualisation libraries. But we saw that chart.js requires placing it in a <code><canvas></code>, so one needs the ability to change that. It could be interesting to apply this to typed.js too as within a <code><div></code> it cannot be placed inline, using a <code><span></code>, however, this would work.</p>
<p>This can be changed by placing a function named <code>nameOfWidget_html</code> which looked up by htmlwidgets and used if found. This function takes the three-dot construct <code>...</code> and uses them in an htmltools tag. The three-dots are necessary because internally htmlwidgets needs be able to pass arguments, such as the all too critical <code>id</code>.</p>
<div class="sourceCode" id="cb203"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb203-1"><a href="html-widgets.html#cb203-1"></a>typed_html <-<span class="st"> </span><span class="cf">function</span>(...){</span>
<span id="cb203-2"><a href="html-widgets.html#cb203-2"></a> htmltools<span class="op">::</span>tags<span class="op">$</span><span class="kw">span</span>(...)</span>
<span id="cb203-3"><a href="html-widgets.html#cb203-3"></a>}</span></code></pre></div>
</div>
<div id="exercises-1" class="section level3 unnumbered" number="">
<h3>Exercises</h3>
<p>The full list of which is available in the <a href="https://github.com/mattboldt/typed.js/#customization">documentation of typed.js</a>. There are multiple ways to complete this package with regard to the options that are made available R-side and the API one wants to provide users of the package.</p>
<ol style="list-style-type: decimal">
<li>Keep adding arguments as done with <code>loop</code></li>
<li>Use the three-dot construct (<code>...</code>) instead of adding arguments individually.</li>
<li>Provide other functions for additional options.</li>
</ol>
<p>It might be unclear how to implement the last point, this is something we’ll explore in the following section.</p>
</div>
</div>
<div id="gio.js" class="section level2 unnumbered" number="">
<h2>Gio.js</h2>
<p>With a first widget built one can jump onto another one: <a href="https://giojs.org/">gio.js</a>, a library to draw arcs between countries on a 3 dimensional globe. This will include many more functionalities such packages can comprise.</p>
<div class="figure">
<img src="images/gio-example.png" alt="" />
<p class="caption">Example of Gio.js visualisation</p>
</div>
<p>Then again, the first order of business when looking to integrate a library is to look at the documentation to understand what is should be reproduced in R.</p>
<div class="sourceCode" id="cb204"><pre class="sourceCode html"><code class="sourceCode html"><span id="cb204-1"><a href="html-widgets.html#cb204-1"></a><span class="dt"><!DOCTYPE </span>html<span class="dt">></span></span>
<span id="cb204-2"><a href="html-widgets.html#cb204-2"></a><span class="kw"><html</span><span class="ot"> xmlns=</span><span class="st">"http://www.w3.org/1999/xhtml"</span><span class="ot"> lang=</span><span class="st">""</span><span class="ot"> xml:lang=</span><span class="st">""</span><span class="kw">></span></span>
<span id="cb204-3"><a href="html-widgets.html#cb204-3"></a></span>
<span id="cb204-4"><a href="html-widgets.html#cb204-4"></a><span class="kw"><head></span></span>
<span id="cb204-5"><a href="html-widgets.html#cb204-5"></a> <span class="co"><!-- Import libraries --></span></span>
<span id="cb204-6"><a href="html-widgets.html#cb204-6"></a> <span class="kw"><script</span><span class="ot"> src=</span><span class="st">"three.min.js"</span><span class="kw">></script></span></span>
<span id="cb204-7"><a href="html-widgets.html#cb204-7"></a> <span class="kw"><script</span><span class="ot"> src=</span><span class="st">"gio.min.js"</span><span class="kw">></script></span></span>
<span id="cb204-8"><a href="html-widgets.html#cb204-8"></a><span class="kw"></head></span></span>
<span id="cb204-9"><a href="html-widgets.html#cb204-9"></a></span>
<span id="cb204-10"><a href="html-widgets.html#cb204-10"></a><span class="kw"><body></span></span>
<span id="cb204-11"><a href="html-widgets.html#cb204-11"></a> <span class="co"><!-- div to hold visualisation --></span></span>
<span id="cb204-12"><a href="html-widgets.html#cb204-12"></a> <span class="kw"><div</span><span class="ot"> id=</span><span class="st">"globe"</span><span class="ot"> style=</span><span class="st">"width: 200px; height: 200px"</span><span class="kw">></div></span></span>
<span id="cb204-13"><a href="html-widgets.html#cb204-13"></a></span>
<span id="cb204-14"><a href="html-widgets.html#cb204-14"></a> <span class="co"><!-- Script to create visualsiation --></span></span>
<span id="cb204-15"><a href="html-widgets.html#cb204-15"></a> <span class="kw"><script></span></span>
<span id="cb204-16"><a href="html-widgets.html#cb204-16"></a> <span class="kw">var</span> container <span class="op">=</span> <span class="va">document</span>.<span class="at">getElementById</span>(<span class="st">"globe"</span>)<span class="op">;</span></span>
<span id="cb204-17"><a href="html-widgets.html#cb204-17"></a> <span class="kw">var</span> controller <span class="op">=</span> <span class="kw">new</span> <span class="va">GIO</span>.<span class="at">Controller</span>(container)<span class="op">;</span></span>
<span id="cb204-18"><a href="html-widgets.html#cb204-18"></a> <span class="va">controller</span>.<span class="at">addData</span>(data)<span class="op">;</span></span>
<span id="cb204-19"><a href="html-widgets.html#cb204-19"></a> <span class="va">controller</span>.<span class="at">init</span>()<span class="op">;</span></span>
<span id="cb204-20"><a href="html-widgets.html#cb204-20"></a> <span class="kw"></script></span></span>
<span id="cb204-21"><a href="html-widgets.html#cb204-21"></a><span class="kw"></body></span></span>
<span id="cb204-22"><a href="html-widgets.html#cb204-22"></a></span>
<span id="cb204-23"><a href="html-widgets.html#cb204-23"></a><span class="kw"></html></span></span></code></pre></div>
<p>Gio.js has itself a dependency, <a href="https://threejs.org/">three.js</a>, which needs to be imported before gio.js, other than that not much differs from libraries previously explored in this chapter.</p>
<div class="sourceCode" id="cb205"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb205-1"><a href="html-widgets.html#cb205-1"></a>usethis<span class="op">::</span><span class="kw">create_package</span>(<span class="st">"gio"</span>)</span>
<span id="cb205-2"><a href="html-widgets.html#cb205-2"></a>htmlwidgets<span class="op">::</span><span class="kw">scaffoldWidget</span>(<span class="st">"gio"</span>)</span></code></pre></div>
<div id="dependencies-1" class="section level3 unnumbered" number="">
<h3>Dependencies</h3>
<p>Handling the dependencies does differ much, we only need to download two libraries instead of one.</p>
<div class="sourceCode" id="cb206"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb206-1"><a href="html-widgets.html#cb206-1"></a><span class="co"># create directories for JS dependencies</span></span>
<span id="cb206-2"><a href="html-widgets.html#cb206-2"></a><span class="kw">dir.create</span>(<span class="st">"./inst/htmlwidgets/three"</span>, <span class="dt">recursive =</span> <span class="ot">TRUE</span>)</span>
<span id="cb206-3"><a href="html-widgets.html#cb206-3"></a><span class="kw">dir.create</span>(<span class="st">"./inst/htmlwidgets/gio"</span>, <span class="dt">recursive =</span> <span class="ot">TRUE</span>)</span>
<span id="cb206-4"><a href="html-widgets.html#cb206-4"></a></span>
<span id="cb206-5"><a href="html-widgets.html#cb206-5"></a><span class="co"># download JS dependencies</span></span>
<span id="cb206-6"><a href="html-widgets.html#cb206-6"></a>three <-<span class="st"> "https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.min.js"</span></span>
<span id="cb206-7"><a href="html-widgets.html#cb206-7"></a>gio <-<span class="st"> "https://raw.githubusercontent.com/syt123450/giojs/master/build/gio.min.js"</span></span>
<span id="cb206-8"><a href="html-widgets.html#cb206-8"></a></span>
<span id="cb206-9"><a href="html-widgets.html#cb206-9"></a><span class="kw">download.file</span>(three, <span class="st">"./inst/htmlwidgets/three/three.min.js"</span>)</span>
<span id="cb206-10"><a href="html-widgets.html#cb206-10"></a><span class="kw">download.file</span>(gio, <span class="st">"./inst/htmlwidgets/gio/gio.min.js"</span>)</span></code></pre></div>
<p>This should produce the following working directory.</p>
<pre><code>.
├── DESCRIPTION
├── NAMESPACE
├── R
│ └── gio.R
└── inst
└── htmlwidgets
├── gio
│ └── gio.min.js
├── gio.js
├── gio.yaml
└── three
└── three.min.js</code></pre>
<p>The libraries have been downloaded but the <code>gio.yml</code> file is yet to be edited. The order in which the libraries are listed matters; just as in HTML three.js needs to precede gio.js as the former depends on the latter and not vice versa.</p>
<div class="sourceCode" id="cb208"><pre class="sourceCode yml"><code class="sourceCode yaml"><span id="cb208-1"><a href="html-widgets.html#cb208-1"></a><span class="fu">dependencies</span><span class="kw">:</span></span>
<span id="cb208-2"><a href="html-widgets.html#cb208-2"></a><span class="at"> </span><span class="kw">-</span><span class="at"> </span><span class="fu">name</span><span class="kw">:</span><span class="at"> three</span></span>
<span id="cb208-3"><a href="html-widgets.html#cb208-3"></a><span class="at"> </span><span class="fu">version</span><span class="kw">:</span><span class="at"> </span><span class="dv">110</span></span>
<span id="cb208-4"><a href="html-widgets.html#cb208-4"></a><span class="at"> </span><span class="fu">src</span><span class="kw">:</span><span class="at"> htmlwidgets/three</span></span>
<span id="cb208-5"><a href="html-widgets.html#cb208-5"></a><span class="at"> </span><span class="fu">script</span><span class="kw">:</span><span class="at"> three.min.js</span></span>
<span id="cb208-6"><a href="html-widgets.html#cb208-6"></a><span class="at"> </span><span class="kw">-</span><span class="at"> </span><span class="fu">name</span><span class="kw">:</span><span class="at"> gio</span></span>
<span id="cb208-7"><a href="html-widgets.html#cb208-7"></a><span class="at"> </span><span class="fu">version</span><span class="kw">:</span><span class="at"> </span><span class="fl">2.0</span></span>
<span id="cb208-8"><a href="html-widgets.html#cb208-8"></a><span class="at"> </span><span class="fu">src</span><span class="kw">:</span><span class="at"> htmlwidgets/gio</span></span>
<span id="cb208-9"><a href="html-widgets.html#cb208-9"></a><span class="at"> </span><span class="fu">script</span><span class="kw">:</span><span class="at"> gio.min.js</span></span></code></pre></div>
</div>
<div id="javascript-2" class="section level3 unnumbered" number="">
<h3>JavaScript</h3>
<p>Let’s copy the JavaScript code from the <a href="https://giojs.org/index.html">Get Started section of gio.js</a> in the <code>gio.js</code> file’s <code>renderValue</code> function. At this point the data format is not known so we comment the line which adds data to the visualisation.</p>
<div class="sourceCode" id="cb209"><pre class="sourceCode js"><code class="sourceCode javascript"><span id="cb209-1"><a href="html-widgets.html#cb209-1"></a>...</span>
<span id="cb209-2"><a href="html-widgets.html#cb209-2"></a>renderValue<span class="op">:</span> <span class="kw">function</span>(x) <span class="op">{</span></span>
<span id="cb209-3"><a href="html-widgets.html#cb209-3"></a></span>
<span id="cb209-4"><a href="html-widgets.html#cb209-4"></a> <span class="kw">var</span> container <span class="op">=</span> <span class="va">document</span>.<span class="at">getElementById</span>(<span class="st">"globe"</span>)<span class="op">;</span></span>
<span id="cb209-5"><a href="html-widgets.html#cb209-5"></a> <span class="kw">var</span> controller <span class="op">=</span> <span class="kw">new</span> <span class="va">GIO</span>.<span class="at">Controller</span>(container)<span class="op">;</span></span>
<span id="cb209-6"><a href="html-widgets.html#cb209-6"></a> <span class="co">//controller.addData(data);</span></span>
<span id="cb209-7"><a href="html-widgets.html#cb209-7"></a> <span class="va">controller</span>.<span class="at">init</span>()<span class="op">;</span></span>
<span id="cb209-8"><a href="html-widgets.html#cb209-8"></a></span>
<span id="cb209-9"><a href="html-widgets.html#cb209-9"></a><span class="op">}</span></span>
<span id="cb209-10"><a href="html-widgets.html#cb209-10"></a>...</span></code></pre></div>
<p>One can document and load the package build it likely will not work as the code above attempts to place the visualisation in a <code>div</code> with <code>id = "globe"</code>. As for the previously written widget, this needs to be changed to <code>el.id</code> so the visualisation can correctly render in the HTML element generated by the widget.</p>
<div class="sourceCode" id="cb210"><pre class="sourceCode js"><code class="sourceCode javascript"><span id="cb210-1"><a href="html-widgets.html#cb210-1"></a>...</span>
<span id="cb210-2"><a href="html-widgets.html#cb210-2"></a>renderValue<span class="op">:</span> <span class="kw">function</span>(x) <span class="op">{</span></span>
<span id="cb210-3"><a href="html-widgets.html#cb210-3"></a></span>
<span id="cb210-4"><a href="html-widgets.html#cb210-4"></a> <span class="kw">var</span> container <span class="op">=</span> <span class="va">document</span>.<span class="at">getElementById</span>(<span class="va">el</span>.<span class="at">id</span>)<span class="op">;</span></span>
<span id="cb210-5"><a href="html-widgets.html#cb210-5"></a> <span class="kw">var</span> controller <span class="op">=</span> <span class="kw">new</span> <span class="va">GIO</span>.<span class="at">Controller</span>(container)<span class="op">;</span></span>
<span id="cb210-6"><a href="html-widgets.html#cb210-6"></a> <span class="co">//controller.addData(data);</span></span>
<span id="cb210-7"><a href="html-widgets.html#cb210-7"></a> <span class="va">controller</span>.<span class="at">init</span>()<span class="op">;</span></span>
<span id="cb210-8"><a href="html-widgets.html#cb210-8"></a></span>
<span id="cb210-9"><a href="html-widgets.html#cb210-9"></a><span class="op">}</span></span>
<span id="cb210-10"><a href="html-widgets.html#cb210-10"></a>...</span></code></pre></div>
<p>At this stage the widget should generate a visualisation.</p>
<div class="sourceCode" id="cb211"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb211-1"><a href="html-widgets.html#cb211-1"></a>devtools<span class="op">::</span><span class="kw">document</span>()</span>
<span id="cb211-2"><a href="html-widgets.html#cb211-2"></a>devtools<span class="op">::</span><span class="kw">load_all</span>()</span>
<span id="cb211-3"><a href="html-widgets.html#cb211-3"></a><span class="kw">gio</span>(<span class="dt">message =</span> <span class="st">"This required but not used"</span>)</span></code></pre></div>
<div class="figure">
<img src="images/gio-init.png" alt="" />
<p class="caption">Output without data</p>
</div>
<p>Not too shabby!</p>
</div>
<div id="working-with-data" class="section level3 unnumbered" number="">
<h3>Working with Data</h3>
<p>An interesting start, now onto adding data. Let’s take a look at the <a href="https://giojs.org/html/docs/dataAdd.html">documentation</a> to see what data the library expects.</p>
<div class="sourceCode" id="cb212"><pre class="sourceCode json"><code class="sourceCode json"><span id="cb212-1"><a href="html-widgets.html#cb212-1"></a><span class="ot">[</span></span>
<span id="cb212-2"><a href="html-widgets.html#cb212-2"></a> <span class="fu">{</span></span>
<span id="cb212-3"><a href="html-widgets.html#cb212-3"></a> <span class="dt">"e"</span><span class="fu">:</span> <span class="st">"CN"</span><span class="fu">,</span></span>
<span id="cb212-4"><a href="html-widgets.html#cb212-4"></a> <span class="dt">"i"</span><span class="fu">:</span> <span class="st">"US"</span><span class="fu">,</span></span>
<span id="cb212-5"><a href="html-widgets.html#cb212-5"></a> <span class="dt">"v"</span><span class="fu">:</span> <span class="dv">3300000</span></span>
<span id="cb212-6"><a href="html-widgets.html#cb212-6"></a> <span class="fu">}</span><span class="ot">,</span></span>
<span id="cb212-7"><a href="html-widgets.html#cb212-7"></a> <span class="fu">{</span></span>
<span id="cb212-8"><a href="html-widgets.html#cb212-8"></a> <span class="dt">"e"</span><span class="fu">:</span> <span class="st">"CN"</span><span class="fu">,</span></span>
<span id="cb212-9"><a href="html-widgets.html#cb212-9"></a> <span class="dt">"i"</span><span class="fu">:</span> <span class="st">"RU"</span><span class="fu">,</span></span>
<span id="cb212-10"><a href="html-widgets.html#cb212-10"></a> <span class="dt">"v"</span><span class="fu">:</span> <span class="dv">10000</span></span>
<span id="cb212-11"><a href="html-widgets.html#cb212-11"></a> <span class="fu">}</span></span>
<span id="cb212-12"><a href="html-widgets.html#cb212-12"></a><span class="ot">]</span></span></code></pre></div>
<p>The JSON data should constitutes of arrays that denote arcs to draw on the globe where each arc is defined by an exporting country (<code>e</code>), an importing country (<code>i</code>), and is given a value (<code>v</code>). The importing and exporting country, the source and target of the arc, are indicated by ISO alpha-2 country codes. We can read this JSON into R.</p>
<div class="sourceCode" id="cb213"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb213-1"><a href="html-widgets.html#cb213-1"></a><span class="co"># data.frame to test</span></span>
<span id="cb213-2"><a href="html-widgets.html#cb213-2"></a>arcs <-<span class="st"> </span>jsonlite<span class="op">::</span><span class="kw">fromJSON</span>(</span>
<span id="cb213-3"><a href="html-widgets.html#cb213-3"></a> <span class="st">'[</span></span>
<span id="cb213-4"><a href="html-widgets.html#cb213-4"></a><span class="st"> {</span></span>
<span id="cb213-5"><a href="html-widgets.html#cb213-5"></a><span class="st"> "e": "CN",</span></span>
<span id="cb213-6"><a href="html-widgets.html#cb213-6"></a><span class="st"> "i": "US",</span></span>
<span id="cb213-7"><a href="html-widgets.html#cb213-7"></a><span class="st"> "v": 3300000</span></span>
<span id="cb213-8"><a href="html-widgets.html#cb213-8"></a><span class="st"> },</span></span>
<span id="cb213-9"><a href="html-widgets.html#cb213-9"></a><span class="st"> {</span></span>
<span id="cb213-10"><a href="html-widgets.html#cb213-10"></a><span class="st"> "e": "CN",</span></span>
<span id="cb213-11"><a href="html-widgets.html#cb213-11"></a><span class="st"> "i": "RU",</span></span>
<span id="cb213-12"><a href="html-widgets.html#cb213-12"></a><span class="st"> "v": 10000</span></span>
<span id="cb213-13"><a href="html-widgets.html#cb213-13"></a><span class="st"> }</span></span>
<span id="cb213-14"><a href="html-widgets.html#cb213-14"></a><span class="st"> ]'</span></span>
<span id="cb213-15"><a href="html-widgets.html#cb213-15"></a>)</span>
<span id="cb213-16"><a href="html-widgets.html#cb213-16"></a></span>
<span id="cb213-17"><a href="html-widgets.html#cb213-17"></a><span class="kw">print</span>(arcs)</span></code></pre></div>
<pre><code>## e i v
## 1 CN US 3300000
## 2 CN RU 10000</code></pre>
<p>Jsonlite automagically converts the JSON into a data frame where each row is an arc, which is great as R users tend to prefer rectangular data over lists: this probably what the package should use as input too. Let us make some changes to the <code>gio</code> function so it takes data as input.</p>
<div class="sourceCode" id="cb215"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb215-1"><a href="html-widgets.html#cb215-1"></a>gio <-<span class="st"> </span><span class="cf">function</span>(data, <span class="dt">width =</span> <span class="ot">NULL</span>, <span class="dt">height =</span> <span class="ot">NULL</span>, <span class="dt">elementId =</span> <span class="ot">NULL</span>) {</span>
<span id="cb215-2"><a href="html-widgets.html#cb215-2"></a></span>
<span id="cb215-3"><a href="html-widgets.html#cb215-3"></a> <span class="co"># forward options using x</span></span>
<span id="cb215-4"><a href="html-widgets.html#cb215-4"></a> x =<span class="st"> </span><span class="kw">list</span>(</span>
<span id="cb215-5"><a href="html-widgets.html#cb215-5"></a> <span class="dt">data =</span> data</span>
<span id="cb215-6"><a href="html-widgets.html#cb215-6"></a> )</span>
<span id="cb215-7"><a href="html-widgets.html#cb215-7"></a></span>
<span id="cb215-8"><a href="html-widgets.html#cb215-8"></a> <span class="co"># create widget</span></span>
<span id="cb215-9"><a href="html-widgets.html#cb215-9"></a> htmlwidgets<span class="op">::</span><span class="kw">createWidget</span>(</span>
<span id="cb215-10"><a href="html-widgets.html#cb215-10"></a> <span class="dt">name =</span> <span class="st">'gio'</span>,</span>
<span id="cb215-11"><a href="html-widgets.html#cb215-11"></a> x,</span>
<span id="cb215-12"><a href="html-widgets.html#cb215-12"></a> <span class="dt">width =</span> width,</span>
<span id="cb215-13"><a href="html-widgets.html#cb215-13"></a> <span class="dt">height =</span> height,</span>
<span id="cb215-14"><a href="html-widgets.html#cb215-14"></a> <span class="dt">package =</span> <span class="st">'gio'</span>,</span>
<span id="cb215-15"><a href="html-widgets.html#cb215-15"></a> <span class="dt">elementId =</span> elementId</span>
<span id="cb215-16"><a href="html-widgets.html#cb215-16"></a> )</span>
<span id="cb215-17"><a href="html-widgets.html#cb215-17"></a>}</span></code></pre></div>
<p>Then tiny changes to <code>play.js</code> where we uncomment the line that line previously commented and use <code>x.data</code> passed from R.</p>
<div class="sourceCode" id="cb216"><pre class="sourceCode js"><code class="sourceCode javascript"><span id="cb216-1"><a href="html-widgets.html#cb216-1"></a>...</span>
<span id="cb216-2"><a href="html-widgets.html#cb216-2"></a>renderValue<span class="op">:</span> <span class="kw">function</span>(x) <span class="op">{</span></span>
<span id="cb216-3"><a href="html-widgets.html#cb216-3"></a></span>
<span id="cb216-4"><a href="html-widgets.html#cb216-4"></a> <span class="kw">var</span> container <span class="op">=</span> <span class="va">document</span>.<span class="at">getElementById</span>(<span class="va">el</span>.<span class="at">id</span>)<span class="op">;</span></span>
<span id="cb216-5"><a href="html-widgets.html#cb216-5"></a> <span class="kw">var</span> controller <span class="op">=</span> <span class="kw">new</span> <span class="va">GIO</span>.<span class="at">Controller</span>(container)<span class="op">;</span></span>
<span id="cb216-6"><a href="html-widgets.html#cb216-6"></a> <span class="va">controller</span>.<span class="at">addData</span>(<span class="va">x</span>.<span class="at">data</span>)<span class="op">;</span> <span class="co">// uncomment & use x.data</span></span>
<span id="cb216-7"><a href="html-widgets.html#cb216-7"></a> <span class="va">controller</span>.<span class="at">init</span>()<span class="op">;</span></span>
<span id="cb216-8"><a href="html-widgets.html#cb216-8"></a></span>
<span id="cb216-9"><a href="html-widgets.html#cb216-9"></a><span class="op">}</span></span>
<span id="cb216-10"><a href="html-widgets.html#cb216-10"></a>...</span></code></pre></div>
<p>We can now use the function with the data to plot arcs!</p>
<div class="sourceCode" id="cb217"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb217-1"><a href="html-widgets.html#cb217-1"></a>devtools<span class="op">::</span><span class="kw">document</span>()</span>
<span id="cb217-2"><a href="html-widgets.html#cb217-2"></a>devtools<span class="op">::</span><span class="kw">load_all</span>()</span>
<span id="cb217-3"><a href="html-widgets.html#cb217-3"></a><span class="kw">gio</span>(arcs)</span></code></pre></div>
<p>Unfortunately, this breaks everything and we are presented with a blank screen. Using <code>console.log</code> or looking at the source code the rendered widget reveals the problem: the data isn’t actually in the correct format!</p>
<div class="sourceCode" id="cb218"><pre class="sourceCode json"><code class="sourceCode json"><span id="cb218-1"><a href="html-widgets.html#cb218-1"></a><span class="fu">{</span><span class="dt">"x"</span><span class="fu">:{</span><span class="dt">"data"</span><span class="fu">:{</span><span class="dt">"e"</span><span class="fu">:</span><span class="ot">[</span><span class="st">"CN"</span><span class="ot">,</span><span class="st">"CN"</span><span class="ot">]</span><span class="fu">,</span><span class="dt">"i"</span><span class="fu">:</span><span class="ot">[</span><span class="st">"US"</span><span class="ot">,</span><span class="st">"RU"</span><span class="ot">]</span><span class="fu">,</span><span class="dt">"v"</span><span class="fu">:</span><span class="ot">[</span><span class="dv">3300000</span><span class="ot">,</span><span class="dv">10000</span><span class="ot">]</span><span class="fu">}},</span><span class="dt">"evals"</span><span class="fu">:</span><span class="ot">[]</span><span class="fu">,</span><span class="dt">"jsHooks"</span><span class="fu">:</span><span class="ot">[]</span><span class="fu">}</span></span></code></pre></div>
<p>Htmlwidgets actually serialised the data frame column-wise (long) and not row-wise (wide).</p>
</div>
<div id="transforming-data" class="section level3 unnumbered" number="">
<h3>Transforming Data</h3>
<p>There are multiple ways to fix the issue at hand.</p>
<div id="in-javascript" class="section level4 unnumbered" number="">
<h4>In JavaScript</h4>
<p>One can use JavaScript to transform the data, leaving everything as-is R side to further handle the data JavaScript side. The HTMLwidget JavaScript library (already imported by default) exports an object which provides a method, <code>dataframeToD3</code>, to transform the data from long to wide.</p>
<div class="sourceCode" id="cb219"><pre class="sourceCode js"><code class="sourceCode javascript"><span id="cb219-1"><a href="html-widgets.html#cb219-1"></a>...</span>
<span id="cb219-2"><a href="html-widgets.html#cb219-2"></a>renderValue<span class="op">:</span> <span class="kw">function</span>(x) <span class="op">{</span></span>
<span id="cb219-3"><a href="html-widgets.html#cb219-3"></a></span>
<span id="cb219-4"><a href="html-widgets.html#cb219-4"></a> <span class="co">// long to wide</span></span>
<span id="cb219-5"><a href="html-widgets.html#cb219-5"></a> <span class="va">x</span>.<span class="at">data</span> <span class="op">=</span> <span class="va">HTMLWidgets</span>.<span class="at">dataframeToD3</span>(<span class="va">x</span>.<span class="at">data</span>)<span class="op">;</span></span>
<span id="cb219-6"><a href="html-widgets.html#cb219-6"></a></span>
<span id="cb219-7"><a href="html-widgets.html#cb219-7"></a> <span class="kw">var</span> container <span class="op">=</span> <span class="va">document</span>.<span class="at">getElementById</span>(<span class="va">el</span>.<span class="at">id</span>)<span class="op">;</span></span>
<span id="cb219-8"><a href="html-widgets.html#cb219-8"></a> <span class="kw">var</span> controller <span class="op">=</span> <span class="kw">new</span> <span class="va">GIO</span>.<span class="at">Controller</span>(container)<span class="op">;</span></span>
<span id="cb219-9"><a href="html-widgets.html#cb219-9"></a> <span class="va">controller</span>.<span class="at">addData</span>(<span class="va">x</span>.<span class="at">data</span>)<span class="op">;</span> </span>
<span id="cb219-10"><a href="html-widgets.html#cb219-10"></a> <span class="va">controller</span>.<span class="at">init</span>()<span class="op">;</span></span>
<span id="cb219-11"><a href="html-widgets.html#cb219-11"></a></span>
<span id="cb219-12"><a href="html-widgets.html#cb219-12"></a><span class="op">}</span></span>
<span id="cb219-13"><a href="html-widgets.html#cb219-13"></a>...</span></code></pre></div>
</div>
<div id="in-r" class="section level4 unnumbered" number="">
<h4>In R</h4>
<p>Instead of serialising the data a certain way then correct in JavaScript as demonstrated previously, one can also modify, or even replace, htmlwidgets’ default serialiser. Speaking of which, below is the default serializer.</p>
<div class="sourceCode" id="cb220"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb220-1"><a href="html-widgets.html#cb220-1"></a><span class="cf">function</span> (x, ..., <span class="dt">dataframe =</span> <span class="st">"columns"</span>, <span class="dt">null =</span> <span class="st">"null"</span>, <span class="dt">na =</span> <span class="st">"null"</span>, </span>
<span id="cb220-2"><a href="html-widgets.html#cb220-2"></a> <span class="dt">auto_unbox =</span> <span class="ot">TRUE</span>, <span class="dt">digits =</span> <span class="kw">getOption</span>(<span class="st">"shiny.json.digits"</span>, </span>
<span id="cb220-3"><a href="html-widgets.html#cb220-3"></a> <span class="dv">16</span>), <span class="dt">use_signif =</span> <span class="ot">TRUE</span>, <span class="dt">force =</span> <span class="ot">TRUE</span>, <span class="dt">POSIXt =</span> <span class="st">"ISO8601"</span>, </span>
<span id="cb220-4"><a href="html-widgets.html#cb220-4"></a> <span class="dt">UTC =</span> <span class="ot">TRUE</span>, <span class="dt">rownames =</span> <span class="ot">FALSE</span>, <span class="dt">keep_vec_names =</span> <span class="ot">TRUE</span>, <span class="dt">strict_atomic =</span> <span class="ot">TRUE</span>) </span>
<span id="cb220-5"><a href="html-widgets.html#cb220-5"></a>{</span>
<span id="cb220-6"><a href="html-widgets.html#cb220-6"></a> <span class="cf">if</span> (strict_atomic) </span>
<span id="cb220-7"><a href="html-widgets.html#cb220-7"></a> x <-<span class="st"> </span><span class="kw">I</span>(x)</span>
<span id="cb220-8"><a href="html-widgets.html#cb220-8"></a> jsonlite<span class="op">::</span><span class="kw">toJSON</span>(x, <span class="dt">dataframe =</span> dataframe, <span class="dt">null =</span> null, <span class="dt">na =</span> na, </span>
<span id="cb220-9"><a href="html-widgets.html#cb220-9"></a> <span class="dt">auto_unbox =</span> auto_unbox, <span class="dt">digits =</span> digits, <span class="dt">use_signif =</span> use_signif, </span>
<span id="cb220-10"><a href="html-widgets.html#cb220-10"></a> <span class="dt">force =</span> force, <span class="dt">POSIXt =</span> POSIXt, <span class="dt">UTC =</span> UTC, <span class="dt">rownames =</span> rownames, </span>
<span id="cb220-11"><a href="html-widgets.html#cb220-11"></a> <span class="dt">keep_vec_names =</span> keep_vec_names, <span class="dt">json_verbatim =</span> <span class="ot">TRUE</span>, </span>
<span id="cb220-12"><a href="html-widgets.html#cb220-12"></a> ...)</span>
<span id="cb220-13"><a href="html-widgets.html#cb220-13"></a>}</span></code></pre></div>
<p>The problem we face is caused by the <code>dataframe</code> argument which is set to <code>columns</code> whereas we need it set to <code>rows</code>. This can be done by passing the arguments to the serialiser is a list as <code>TOJSON_ARGS</code> attribute of the object <code>x</code> that is serialised. We could thus change the <code>gio</code> function to reflect the aforementioned change.</p>
<div class="sourceCode" id="cb221"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb221-1"><a href="html-widgets.html#cb221-1"></a>gio <-<span class="st"> </span><span class="cf">function</span>(data, <span class="dt">width =</span> <span class="ot">NULL</span>, <span class="dt">height =</span> <span class="ot">NULL</span>, <span class="dt">elementId =</span> <span class="ot">NULL</span>) {</span>
<span id="cb221-2"><a href="html-widgets.html#cb221-2"></a></span>
<span id="cb221-3"><a href="html-widgets.html#cb221-3"></a> <span class="co"># forward options using x</span></span>
<span id="cb221-4"><a href="html-widgets.html#cb221-4"></a> x =<span class="st"> </span><span class="kw">list</span>(</span>
<span id="cb221-5"><a href="html-widgets.html#cb221-5"></a> <span class="dt">data =</span> data</span>
<span id="cb221-6"><a href="html-widgets.html#cb221-6"></a> )</span>
<span id="cb221-7"><a href="html-widgets.html#cb221-7"></a></span>
<span id="cb221-8"><a href="html-widgets.html#cb221-8"></a> <span class="co"># serialise data.frames to wide (not long as default)</span></span>
<span id="cb221-9"><a href="html-widgets.html#cb221-9"></a> <span class="kw">attr</span>(x, <span class="st">'TOJSON_ARGS'</span>) <-<span class="st"> </span><span class="kw">list</span>(<span class="dt">dataframe =</span> <span class="st">"rows"</span>)</span>
<span id="cb221-10"><a href="html-widgets.html#cb221-10"></a></span>
<span id="cb221-11"><a href="html-widgets.html#cb221-11"></a> <span class="co"># create widget</span></span>
<span id="cb221-12"><a href="html-widgets.html#cb221-12"></a> htmlwidgets<span class="op">::</span><span class="kw">createWidget</span>(</span>
<span id="cb221-13"><a href="html-widgets.html#cb221-13"></a> <span class="dt">name =</span> <span class="st">'gio'</span>,</span>
<span id="cb221-14"><a href="html-widgets.html#cb221-14"></a> x,</span>
<span id="cb221-15"><a href="html-widgets.html#cb221-15"></a> <span class="dt">width =</span> width,</span>
<span id="cb221-16"><a href="html-widgets.html#cb221-16"></a> <span class="dt">height =</span> height,</span>
<span id="cb221-17"><a href="html-widgets.html#cb221-17"></a> <span class="dt">package =</span> <span class="st">'gio'</span>,</span>
<span id="cb221-18"><a href="html-widgets.html#cb221-18"></a> <span class="dt">elementId =</span> elementId</span>
<span id="cb221-19"><a href="html-widgets.html#cb221-19"></a> )</span>
<span id="cb221-20"><a href="html-widgets.html#cb221-20"></a>}</span></code></pre></div>
<p>The above may seem confusing at first as one rarely encounters the <code>attr</code> replacement function.</p>
<div class="sourceCode" id="cb222"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb222-1"><a href="html-widgets.html#cb222-1"></a><span class="kw">attr</span>(cars, <span class="st">"hello"</span>) <-<span class="st"> "attributes"</span> <span class="co"># set </span></span>
<span id="cb222-2"><a href="html-widgets.html#cb222-2"></a><span class="kw">attr</span>(cars, <span class="st">"hello"</span>) <span class="co"># get </span></span></code></pre></div>
<pre><code>## [1] "attributes"</code></pre>
<p>Otherwise one can completely override the serializer, also by setting an attribute, <code>TOJSON_FUNC</code>, to the function which should be used to serialise the data. Below the serialiser is changed to using jsonify <span class="citation">(Cooley <a href="#ref-R-jsonify" role="doc-biblioref">2020</a>)</span> which by default serialises data frames to wide, unlike htmlwidgets’ serialiser, thereby also fixing the issue.</p>
<div class="sourceCode" id="cb224"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb224-1"><a href="html-widgets.html#cb224-1"></a>gio <-<span class="st"> </span><span class="cf">function</span>(data, <span class="dt">width =</span> <span class="ot">NULL</span>, <span class="dt">height =</span> <span class="ot">NULL</span>, <span class="dt">elementId =</span> <span class="ot">NULL</span>) {</span>
<span id="cb224-2"><a href="html-widgets.html#cb224-2"></a></span>
<span id="cb224-3"><a href="html-widgets.html#cb224-3"></a> <span class="co"># forward options using x</span></span>
<span id="cb224-4"><a href="html-widgets.html#cb224-4"></a> x =<span class="st"> </span><span class="kw">list</span>(</span>
<span id="cb224-5"><a href="html-widgets.html#cb224-5"></a> <span class="dt">data =</span> data</span>
<span id="cb224-6"><a href="html-widgets.html#cb224-6"></a> )</span>
<span id="cb224-7"><a href="html-widgets.html#cb224-7"></a></span>
<span id="cb224-8"><a href="html-widgets.html#cb224-8"></a> <span class="co"># replace serialiser</span></span>
<span id="cb224-9"><a href="html-widgets.html#cb224-9"></a> <span class="kw">attr</span>(x, <span class="st">'TOJSON_FUNC'</span>) <-<span class="st"> </span>gio_serialiser</span>
<span id="cb224-10"><a href="html-widgets.html#cb224-10"></a></span>
<span id="cb224-11"><a href="html-widgets.html#cb224-11"></a> <span class="co"># create widget</span></span>
<span id="cb224-12"><a href="html-widgets.html#cb224-12"></a> htmlwidgets<span class="op">::</span><span class="kw">createWidget</span>(</span>
<span id="cb224-13"><a href="html-widgets.html#cb224-13"></a> <span class="dt">name =</span> <span class="st">'gio'</span>,</span>
<span id="cb224-14"><a href="html-widgets.html#cb224-14"></a> x,</span>
<span id="cb224-15"><a href="html-widgets.html#cb224-15"></a> <span class="dt">width =</span> width,</span>
<span id="cb224-16"><a href="html-widgets.html#cb224-16"></a> <span class="dt">height =</span> height,</span>
<span id="cb224-17"><a href="html-widgets.html#cb224-17"></a> <span class="dt">package =</span> <span class="st">'gio'</span>,</span>
<span id="cb224-18"><a href="html-widgets.html#cb224-18"></a> <span class="dt">elementId =</span> elementId</span>
<span id="cb224-19"><a href="html-widgets.html#cb224-19"></a> )</span>
<span id="cb224-20"><a href="html-widgets.html#cb224-20"></a>}</span>
<span id="cb224-21"><a href="html-widgets.html#cb224-21"></a></span>
<span id="cb224-22"><a href="html-widgets.html#cb224-22"></a>gio_serialiser <-<span class="st"> </span><span class="cf">function</span>(x){</span>
<span id="cb224-23"><a href="html-widgets.html#cb224-23"></a> jsonify<span class="op">::</span><span class="kw">to_json</span>(x, <span class="dt">unbox =</span> <span class="ot">TRUE</span>)</span>
<span id="cb224-24"><a href="html-widgets.html#cb224-24"></a>}</span></code></pre></div>
<p>Alternatively, one can also leave all serialisers unchanged and instead format the data in R prior to the serialisation, changing the dataframe to a row-wise list.</p>
<div class="sourceCode" id="cb225"><pre class="sourceCode r"><code class="sourceCode r"><span id="cb225-1"><a href="html-widgets.html#cb225-1"></a><span class="co"># forward options using x</span></span>
<span id="cb225-2"><a href="html-widgets.html#cb225-2"></a>x =<span class="st"> </span><span class="kw">list</span>(</span>
<span id="cb225-3"><a href="html-widgets.html#cb225-3"></a> <span class="dt">data =</span> <span class="kw">apply</span>(data, <span class="dv">1</span>, as.list)</span>
<span id="cb225-4"><a href="html-widgets.html#cb225-4"></a>)</span></code></pre></div>
</div>
<div id="pros-cons" class="section level4 unnumbered" number="">
<h4>Pros & Cons</h4>
<p>There are pros and cons to each methods. The preferable method is probably to change the arguments that cause issue, this is the method used in the remaining of the book. Replacing the serialiser in its entirety should not be necessary, only do this once you are very familiar with serialisation and truly see a need for it. Transforming the data in JavaScript has one drawback, <code>HTMLWidgets.dataframeToD3</code> cannot be applied to the entire <code>x</code> object but the subsets that hold the data frame which tends to lead to clunky code as one uses said function in various places and has to add if statements to make sure data is present, etc. This will become more evident as we progress.</p>
<div class="figure">
<img src="images/gio-data.png" alt="" />
<p class="caption">Gio output with correct serialisation</p>
</div>
</div>
</div>
</div>
</div>
<h3>References</h3>
<div id="refs" class="references">
<div id="ref-R-jsonify">
<p>Cooley, David. 2020. <em>Jsonify: Convert Between ’R’ Objects and Javascript Object Notation (Json)</em>.</p>
</div>
<div id="ref-R-htmltools">
<p>RStudio, and Inc. 2019. <em>Htmltools: Tools for Html</em>. <a href="https://CRAN.R-project.org/package=htmltools">https://CRAN.R-project.org/package=htmltools</a>.</p>
</div>
</div>
</section>
</div>
</div>
</div>
<a href="shiny-1.html" class="navigation navigation-prev " aria-label="Previous page"><i class="fa fa-angle-left"></i></a>
<a href="references.html" class="navigation navigation-next " aria-label="Next page"><i class="fa fa-angle-right"></i></a>
</div>
</div>
<script src="libs/gitbook/js/app.min.js"></script>
<script src="libs/gitbook/js/lunr.js"></script>
<script src="libs/gitbook/js/clipboard.min.js"></script>
<script src="libs/gitbook/js/plugin-search.js"></script>
<script src="libs/gitbook/js/plugin-sharing.js"></script>
<script src="libs/gitbook/js/plugin-fontsettings.js"></script>
<script src="libs/gitbook/js/plugin-bookdown.js"></script>
<script src="libs/gitbook/js/jquery.highlight.js"></script>
<script src="libs/gitbook/js/plugin-clipboard.js"></script>
<script>
gitbook.require(["gitbook"], function(gitbook) {
gitbook.start({
"sharing": {
"github": true,
"facebook": false,
"twitter": false,
"linkedin": false,
"weibo": false,
"instapaper": false,