htmlwidgets in effect are reusable HTML/JS/CSS components (think simple Polymer or WebComponents) I don’t recommend it, but if we wanted to use an htmlwidget with no R, it is fairly straightforward. Even if you decided not to do this, I think it will be helpful in your journey to htmlwidgets mastery.
We’ll use the simple but powerful jsonedit from the listviewer package. Its JavaScript binding is very sparse, so I hope it will be a good subject.
Output from a htmlwidget
Let’s start by seeing what happens when we create our htmlwidget. The R code would look something like this.
library(listviewer)
# give it an empty list() or {} in JavaScript
jsonedit(list())
If we open our developer tools in Chrome, we should see something like this.
screenshot of html from htmlwidget
Each htmlwidget will be different, but the ingredients will usually contain:
- JavaScript and CSS dependencies
htmlwidgets.js- js/css for the source libraries which are provided in the
htmlwidgetyaml - the htmlwidget binding -
jsonedit.js
- HTML tags
- usually a
<div>with anidandclass='..widgetname.. html-widget', but depending on the widget might be a differenttagor set oftags <script type='application/json' data-for='..widgetid..'>
- usually a
copy/paste method
Nearly every step to enlightenment in programming starts with copy/paste, so we’ll copy/paste the bits and pieces to make this. We’ll change to use the CDN for jsoneditor. Also, we’ll change the random element id to mywidget. These aren’t necessary, but they might be considered an improvement.
<!doctype html>
<html>
<head>
<script src="https://cdn.rawgit.com/ramnathv/htmlwidgets/master/inst/www/htmlwidgets.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jsoneditor/5.5.6/jsoneditor.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/jsoneditor/5.5.6/jsoneditor.min.css" rel="stylesheet">
<script src="https://cdn.rawgit.com/timelyportfolio/listviewer/master/inst/htmlwidgets/jsonedit.js"></script>
</head>
<body>
<div id="mywidget" class="jsonedit html-widget" style="height:100%;width:100%;"></div>
<script type="application/json" data-for="mywidget">
{"x":{"data":[],"options":{"mode":"tree","modes":["code","form","text","tree","view"]}},"evals":[],"jsHooks":[]}
</script>
</body>
</html>
To see it working, I’ll embed the iframe below, or go directly to the example.html.
easier way?
The data script with data-for piece can be tricky to populate. Many times, it might be easier to manually render our htmlwidget from JavaScript. We can get rid of the <script ... data-for> and use some more traditional looking JavaScript.
find the widget binding
// use HTMLWidgets.widgets to give us
// a list of available htmlwiget bindings
// in this case we should just have one
var widgets = HTMLWidgets.widgets;
// assume there might be lots, so filter for the one we want
// in this case, we want jsonedit
var jed = widgets.filter(function(widget){
return widget.name === "jsonedit"
})[0];
get/make all the arguments for renderValue
// the binding should have an intialize, renderValue, and resize
// to render we use renderValue with arguments
// el the DOM element in which we want to render
// x the data and options
// instance return value from initialize
// get our htmlwidget DOM element
var el = document.getElementById('mywidget');
// make our x data and options
// this varies by widget
// and if widget built robustly then might be able
// to eliminate much of this
var x = {
"data":[],
"options":{"mode":"tree","modes":["code","form","text","tree","view"]}
};
// get our htmlwidget instance with initialize
var instance = jed.initialize(el);
render our widget
jed.renderValue(
el,
x,
instance
);
To see it working, I’ll embed the iframe below, or go directly to the example.html.
Reusable Components
Resability and portability is quite nice, so if you really like an htmlwidget, but don’t use R, you can still use them. We’d love to have some more JavaScript/HTML/CSS, or heck Python, Go, Elm folks.