Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
@Manual{,
+ title = {listviewer: 'htmlwidget' for Interactive Views of R Lists},
+ author = {Jos {de Jong} and Mac { Gainer} and Kent Russell},
+ year = {2023},
+ note = {R package version 4.0.0},
+ url = {https://github.com/timelyportfolio/listviewer},
+}
-
+
+
+
-
-
+
diff --git a/docs/bootstrap-toc.css b/docs/bootstrap-toc.css
new file mode 100644
index 0000000..5a85941
--- /dev/null
+++ b/docs/bootstrap-toc.css
@@ -0,0 +1,60 @@
+/*!
+ * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/)
+ * Copyright 2015 Aidan Feldman
+ * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */
+
+/* modified from https://github.com/twbs/bootstrap/blob/94b4076dd2efba9af71f0b18d4ee4b163aa9e0dd/docs/assets/css/src/docs.css#L548-L601 */
+
+/* All levels of nav */
+nav[data-toggle='toc'] .nav > li > a {
+ display: block;
+ padding: 4px 20px;
+ font-size: 13px;
+ font-weight: 500;
+ color: #767676;
+}
+nav[data-toggle='toc'] .nav > li > a:hover,
+nav[data-toggle='toc'] .nav > li > a:focus {
+ padding-left: 19px;
+ color: #563d7c;
+ text-decoration: none;
+ background-color: transparent;
+ border-left: 1px solid #563d7c;
+}
+nav[data-toggle='toc'] .nav > .active > a,
+nav[data-toggle='toc'] .nav > .active:hover > a,
+nav[data-toggle='toc'] .nav > .active:focus > a {
+ padding-left: 18px;
+ font-weight: bold;
+ color: #563d7c;
+ background-color: transparent;
+ border-left: 2px solid #563d7c;
+}
+
+/* Nav: second level (shown on .active) */
+nav[data-toggle='toc'] .nav .nav {
+ display: none; /* Hide by default, but at >768px, show it */
+ padding-bottom: 10px;
+}
+nav[data-toggle='toc'] .nav .nav > li > a {
+ padding-top: 1px;
+ padding-bottom: 1px;
+ padding-left: 30px;
+ font-size: 12px;
+ font-weight: normal;
+}
+nav[data-toggle='toc'] .nav .nav > li > a:hover,
+nav[data-toggle='toc'] .nav .nav > li > a:focus {
+ padding-left: 29px;
+}
+nav[data-toggle='toc'] .nav .nav > .active > a,
+nav[data-toggle='toc'] .nav .nav > .active:hover > a,
+nav[data-toggle='toc'] .nav .nav > .active:focus > a {
+ padding-left: 28px;
+ font-weight: 500;
+}
+
+/* from https://github.com/twbs/bootstrap/blob/e38f066d8c203c3e032da0ff23cd2d6098ee2dd6/docs/assets/css/src/docs.css#L631-L634 */
+nav[data-toggle='toc'] .nav > .active > ul {
+ display: block;
+}
diff --git a/docs/bootstrap-toc.js b/docs/bootstrap-toc.js
new file mode 100644
index 0000000..1cdd573
--- /dev/null
+++ b/docs/bootstrap-toc.js
@@ -0,0 +1,159 @@
+/*!
+ * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/)
+ * Copyright 2015 Aidan Feldman
+ * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */
+(function() {
+ 'use strict';
+
+ window.Toc = {
+ helpers: {
+ // return all matching elements in the set, or their descendants
+ findOrFilter: function($el, selector) {
+ // http://danielnouri.org/notes/2011/03/14/a-jquery-find-that-also-finds-the-root-element/
+ // http://stackoverflow.com/a/12731439/358804
+ var $descendants = $el.find(selector);
+ return $el.filter(selector).add($descendants).filter(':not([data-toc-skip])');
+ },
+
+ generateUniqueIdBase: function(el) {
+ var text = $(el).text();
+ var anchor = text.trim().toLowerCase().replace(/[^A-Za-z0-9]+/g, '-');
+ return anchor || el.tagName.toLowerCase();
+ },
+
+ generateUniqueId: function(el) {
+ var anchorBase = this.generateUniqueIdBase(el);
+ for (var i = 0; ; i++) {
+ var anchor = anchorBase;
+ if (i > 0) {
+ // add suffix
+ anchor += '-' + i;
+ }
+ // check if ID already exists
+ if (!document.getElementById(anchor)) {
+ return anchor;
+ }
+ }
+ },
+
+ generateAnchor: function(el) {
+ if (el.id) {
+ return el.id;
+ } else {
+ var anchor = this.generateUniqueId(el);
+ el.id = anchor;
+ return anchor;
+ }
+ },
+
+ createNavList: function() {
+ return $('
');
+ },
+
+ createChildNavList: function($parent) {
+ var $childList = this.createNavList();
+ $parent.append($childList);
+ return $childList;
+ },
+
+ generateNavEl: function(anchor, text) {
+ var $a = $('');
+ $a.attr('href', '#' + anchor);
+ $a.text(text);
+ var $li = $('');
+ $li.append($a);
+ return $li;
+ },
+
+ generateNavItem: function(headingEl) {
+ var anchor = this.generateAnchor(headingEl);
+ var $heading = $(headingEl);
+ var text = $heading.data('toc-text') || $heading.text();
+ return this.generateNavEl(anchor, text);
+ },
+
+ // Find the first heading level (`
`, then `
`, etc.) that has more than one element. Defaults to 1 (for `
`).
+ getTopLevel: function($scope) {
+ for (var i = 1; i <= 6; i++) {
+ var $headings = this.findOrFilter($scope, 'h' + i);
+ if ($headings.length > 1) {
+ return i;
+ }
+ }
+
+ return 1;
+ },
+
+ // returns the elements for the top level, and the next below it
+ getHeadings: function($scope, topLevel) {
+ var topSelector = 'h' + topLevel;
+
+ var secondaryLevel = topLevel + 1;
+ var secondarySelector = 'h' + secondaryLevel;
+
+ return this.findOrFilter($scope, topSelector + ',' + secondarySelector);
+ },
+
+ getNavLevel: function(el) {
+ return parseInt(el.tagName.charAt(1), 10);
+ },
+
+ populateNav: function($topContext, topLevel, $headings) {
+ var $context = $topContext;
+ var $prevNav;
+
+ var helpers = this;
+ $headings.each(function(i, el) {
+ var $newNav = helpers.generateNavItem(el);
+ var navLevel = helpers.getNavLevel(el);
+
+ // determine the proper $context
+ if (navLevel === topLevel) {
+ // use top level
+ $context = $topContext;
+ } else if ($prevNav && $context === $topContext) {
+ // create a new level of the tree and switch to it
+ $context = helpers.createChildNavList($prevNav);
+ } // else use the current $context
+
+ $context.append($newNav);
+
+ $prevNav = $newNav;
+ });
+ },
+
+ parseOps: function(arg) {
+ var opts;
+ if (arg.jquery) {
+ opts = {
+ $nav: arg
+ };
+ } else {
+ opts = arg;
+ }
+ opts.$scope = opts.$scope || $(document.body);
+ return opts;
+ }
+ },
+
+ // accepts a jQuery object, or an options object
+ init: function(opts) {
+ opts = this.helpers.parseOps(opts);
+
+ // ensure that the data attribute is in place for styling
+ opts.$nav.attr('data-toggle', 'toc');
+
+ var $topContext = this.helpers.createChildNavList(opts.$nav);
+ var topLevel = this.helpers.getTopLevel(opts.$scope);
+ var $headings = this.helpers.getHeadings(opts.$scope, topLevel);
+ this.helpers.populateNav($topContext, topLevel, $headings);
+ }
+ };
+
+ $(function() {
+ $('nav[data-toggle="toc"]').each(function(i, el) {
+ var $nav = $(el);
+ Toc.init($nav);
+ });
+ });
+})();
diff --git a/docs/index.html b/docs/index.html
index 47a66ef..eec1531 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -5,23 +5,26 @@
-'htmlwidget' for Interactive Views of R Lists • listviewer
-
-
-
-
+htmlwidget for Interactive Views of R Lists • listviewer
+
+
+
+
+
+
-
+ lists. The function reactjson() requires a package
+ reactR that can be installed from CRAN or <https://github.com/timelyportfolio/reactR>.">
-
+
+
+
A package of R htmlwidgets to interactively view and maybe modifylists. As of now, listviewer provides an interface to jsoneditor and react-json-view. listviewer is designed to support multiple interfaces.
-
-
-install
+
+
+
listviewer
+
+
A package of R htmlwidgets to interactively view and maybe modifylists. As of now, listviewer provides an interface to jsoneditor and react-json-view. listviewer is designed to support multiple interfaces.
jsoneditor is a really well designed JSON interactive editor by Jos de Jong. Since most R data can be represented in JSON, we can use this great JavaScript library in R.
jsoneditor is a really well designed JSON interactive editor by Jos de Jong. Since most R data can be represented in JSON, we can use this great JavaScript library in R.
+
+# using the data from the jsoneditor simple example
+# in R list form
+
+library(listviewer)
+
+jsonedit(
+list(
+ array =c(1,2,3)
+ ,boolean =TRUE
+ ,null =NULL
+ ,number =123
+ ,object =list( a="b", c="d")
+ ,string ="Hello World"
+)
+)
react-json-view is another very nice JSON interactive editor. We even get copy/paste! All of the above examples should also work with reactjson.
+
+# using the data from the jsoneditor simple example
+# in R list form
+
+library(listviewer)
+
+reactjson(
+list(
+ array =c(1,2,3)
+ ,boolean =TRUE
+ ,null =NULL
+ ,number =123
+ ,object =list( a="b", c="d")
+ ,string ="Hello World"
+)
+)
-
-
-Shiny example
+
+
Shiny example
+
listviewer works with Shiny but the implementation is crude and likely to change for jsonedit while reactjson integration is much better. If you really want to use jsonedit with Shiny, I would recommend debouncing the change callback. Here are examples with each.
+library(shiny)
+library(listviewer)
+
+# put some data in environment so it will show up
+data(mtcars)
+
+ui<-shinyUI(
+fluidPage(
+jsoneditOutput("jsed")
+)
+)
+
+server<-function(input,output){
+output$jsed<-renderJsonedit({
+jsonedit(
+jsonlite::toJSON(mtcars, auto_unbox =TRUE, data.frame ="rows")
+ ,"onChange"=htmlwidgets::JS('function(after, before, patch){
+ console.log( after.json )
+ }')
+)
+
+})
+}
+
+runApp(list( ui =ui, server =server))
API Changes - onEdit, onAdd, onDelete, and onSelect changed to allow disable. See pull 32. The default TRUE now will pass the event to Shiny if in Shiny context.
jsonedit provides a flexible and helpful interactive tree-like view of lists
or really any R dataset that can be represented as JSON.
Eventually, this could become a very nice way to not only view but also modify R data using
Shiny.
list or String data to view. Although designed for lists, listdata can
be any data source that can be rendered into JSON with jsonlite. Alternately,
listdata could be a String of valid JSON. This might be helpful
-when dealing with an API response.
-
-
-
mode
-
string for the initial view from modes. 'tree' is the default.
list of other options for jsoneditor. This is a temporary way
+when dealing with an API response.
+
+
+
mode
+
string for the initial view from modes. 'tree' is the default.
+
+
+
modes
+
stringc('tree', 'text', 'table') will be the default, since
+these are all the modes currently supported by jsoneditor.
+
+
+
...
+
list of other options for jsoneditor. This is a temporary way
of trying other options in jsoneditor. In the future, this will be eliminated
-in favor of specific, more self-documenting and helpful arguments.
-
-
-
width
-
integer in pixels defining the width of the div container.
-
-
-
height
-
integer in pixels defining the height of the div container.
-
-
-
elementId
-
character to specify valid CSS id of the
-htmlwidget for special situations in which you want a non-random
-identifier.
-
-
-
+in favor of specific, more self-documenting and helpful arguments.
+
+
+
width
+
integer in pixels defining the width of the div container.
-
Examples
-
library(listviewer)
-
- # using the data from the jsoneditor simple example
- # in R list form
- jsonedit(
- list(
- array=c(1,2,3)
- ,boolean=TRUE
- ,null=NULL
- ,number=123
- ,object=list( a="b", c="d" )
- ,string="Hello World"
- )
- )
-
- # jsonedit also works with a JSON string
- jsonedit(
- '{"array" : [1,2,3] , "boolean" : true, "null" : null, number = 123}'
- )
-
- # also works with most data.frames
- jsonedit( mtcars )
-
- # helpful interactive view of par
- jsonedit( par() )
integer in pixels defining the height of the div container.
+
+
+
elementId
+
character to specify valid CSS id of the
+htmlwidget for special situations in which you want a non-random
+identifier.
+
+
+
+
+
Examples
+
library(listviewer)
+
+# using the data from the jsoneditor simple example
+# in R list form
+jsonedit(
+list(
+ array =c(1,2,3)
+ ,boolean =TRUE
+ ,null =NULL
+ ,number =123
+ ,object =list( a="b", c="d")
+ ,string ="Hello World"
+)
+)
+
+
+# jsonedit also works with a JSON string
+jsonedit(
+'{"array" : [1,2,3] , "boolean" : true, "null" : null, "number": 123}'
+)
+
+
+# also works with most data.frames
+jsonedit(mtcars)
+
+
+# helpful interactive view of par
+jsonedit(par())
+
+
+