Embedding an R htmlwidget into existing webpage - r
I am trying to embed an R htmlwidget into an existing webpage -- a webpage that already has bootstrap and styling applied. For example, consider the following webpage (note where the widget should be placed):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<p>This is a test.</p>
<!-- htmlwidget should go here. -->
<p>A closing paragraph.</p>
</body>
</html>
I can create and save a datatable widget like so:
library(htmlwidgets)
library(datatable)
d1 <- datatable(mtcars, filter = "top")
saveWidget(d1, file = "widget_file.html")
The generated widget_file.html (even for this modest widget) contains a lot of code. Is there an easy way to embed this into an existing webpage/template?
I have been successful using <iframe src="widget_file.html"> but I'm wondering if there is a better way? Moreover, is there a way to separate pieces/dependencies (e.g. json data) from the widget_file.html so they can be placed in other folders?
Note: I created the htmlwidget tag, but I believe there should be a synonymous htmlwidgets tag.
The htmlwidget-Package offers a way to save the pieces for the widget separately as follows:
library(dygraphs)
d1 <- dygraph(nhtemp, main = "New Haven Temperatures") %>%
dyRangeSelector(dateWindow = c("1920-01-01", "1960-01-01"))
saveWidget(d1, file = "widget_file.html", selfcontained = FALSE)
Which results in the following files/dirs:
widget_file.html
widget_file_files
/dygraphs-1.1.1
..
/dygraphs-binding-0.6
..
/htmlwidgets-0.5
..
/jquery-1.11.1
..
/moment-2.8.4
..
/moment-timezone-0.2.5
..
And widget_file.html reads as follows:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<script src="widget_file_files/htmlwidgets-0.5/htmlwidgets.js"></script>
...
<script src="widget_file_files/dygraphs-binding-0.6/dygraphs.js"></script>
</head>
<body style="background-color:white;">
<div id="htmlwidget_container">
<div id="htmlwidget-2956" style="width:960px;height:500px;" class="dygraphs"></div>
</div>
<!-- THE JSON DATA -->
<script type="application/json" data-for="htmlwidget-2956">
{THE JSON DATA YOU WERE LOOKING FOR}
</script>
<!-- THE JSON DATA -->
<script type="application/htmlwidget-sizing" data-for="htmlwidget-2956">{Widget-Styling-Json}
</script>
</body>
</html>
So you can edit your html as follows:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<!-- Begin of scripts to run the widget -->
<script src="widget_file_files/htmlwidgets-0.5/htmlwidgets.js"></script>
<script src="widget_file_files/jquery-1.11.1/jquery.min.js"></script>
<link href="widget_file_files/dygraphs-1.1.1/dygraph.css" rel="stylesheet" />
<script src="widget_file_files/dygraphs-1.1.1/dygraph-combined.js"></script>
<script src="widget_file_files/moment-2.8.4/moment.js"></script>
<script src="widget_file_files/moment-timezone-0.2.5/moment-timezone-with-data.js"></script>
<script src="widget_file_files/dygraphs-binding-0.6/dygraphs.js"></script>
<!-- End of scripts to run the widget -->
<!-- Begin Widget styling -->
<script type="application/htmlwidget-sizing" data-for="htmlwidget-2956">{"viewer":{"width":450,"height":350,"padding":10,"fill":true},"browser":{"width":960,"height":500,"padding":40,"fill":true}}</script>
<!-- End widget Styling -->
<!-- Begin Data for the widget-->
<script type="application/json" data-for="htmlwidget-2956">{"x":{"attrs":{"title":"New Haven Temperatures","labels":["year","V1"],"legend":"auto","retainDateWindow":false,"axes":{"x":{"pixelsPerLabel":60}},"showRangeSelector":true,"dateWindow":["1920-01-01T00:00:00Z","1960-01-01T00:00:00Z"],"rangeSelectorHeight":40,"rangeSelectorPlotFillColor":" #A7B1C4","rangeSelectorPlotStrokeColor":"#808FAB","interactionModel":"Dygraph.Interaction.defaultModel"},"scale":"yearly","annotations":[],"shadings":[],"events":[],"format":"date","data":[["1912-01-01T00:00:00Z","1913-01-01T00:00:00Z","1914-01-01T00:00:00Z","1915-01-01T00:00:00Z","1916-01-01T00:00:00Z","1917-01-01T00:00:00Z","1918-01-01T00:00:00Z","1919-01-01T00:00:00Z","1920-01-01T00:00:00Z","1921-01-01T00:00:00Z","1922-01-01T00:00:00Z","1923-01-01T00:00:00Z","1924-01-01T00:00:00Z","1925-01-01T00:00:00Z","1926-01-01T00:00:00Z","1927-01-01T00:00:00Z","1928-01-01T00:00:00Z","1929-01-01T00:00:00Z","1930-01-01T00:00:00Z","1931-01-01T00:00:00Z","1932-01-01T00:00:00Z","1933-01-01T00:00:00Z","1934-01-01T00:00:00Z","1935-01-01T00:00:00Z","1936-01-01T00:00:00Z","1937-01-01T00:00:00Z","1938-01-01T00:00:00Z","1939-01-01T00:00:00Z","1940-01-01T00:00:00Z","1941-01-01T00:00:00Z","1942-01-01T00:00:00Z","1943-01-01T00:00:00Z","1944-01-01T00:00:00Z","1945-01-01T00:00:00Z","1946-01-01T00:00:00Z","1947-01-01T00:00:00Z","1948-01-01T00:00:00Z","1949-01-01T00:00:00Z","1950-01-01T00:00:00Z","1951-01-01T00:00:00Z","1952-01-01T00:00:00Z","1953-01-01T00:00:00Z","1954-01-01T00:00:00Z","1955-01-01T00:00:00Z","1956-01-01T00:00:00Z","1957-01-01T00:00:00Z","1958-01-01T00:00:00Z","1959-01-01T00:00:00Z","1960-01-01T00:00:00Z","1961-01-01T00:00:00Z","1962-01-01T00:00:00Z","1963-01-01T00:00:00Z","1964-01-01T00:00:00Z","1965-01-01T00:00:00Z","1966-01-01T00:00:00Z","1967-01-01T00:00:00Z","1968-01-01T00:00:00Z","1969-01-01T00:00:00Z","1970-01-01T00:00:00Z","1971-01-01T00:00:00Z"],[49.9,52.3,49.4,51.1,49.4,47.9,49.8,50.9,49.3,51.9,50.8,49.6,49.3,50.6,48.4,50.7,50.9,50.6,51.5,52.8,51.8,51.1,49.8,50.2,50.4,51.6,51.8,50.9,48.8,51.7,51,50.6,51.7,51.5,52.1,51.3,51,54,51.4,52.7,53.1,54.6,52,52,50.9,52.6,50.2,52.6,51.6,51.9,50.5,50.9,51.7,51.4,51.7,50.8,51.9,51.8,51.9,53]]},"evals":["attrs.interactionModel"]}</script>
<!-- End Data for the widget-->
</head>
<body>
<p>This is a test.</p>
<div id="htmlwidget_container">
<div id="htmlwidget-2956" style="width:960px;height:500px;" class="dygraphs"></div>
</div>
<p>A closing paragraph.</p>
</body>
</html>
This will leave you with the json-data hardcoded within the html-document (see my ).
If you want to load the data dynamically you can use e.g.
json_dat <- readLines("widget_file.html")[18]
cat(sub("</script>","",sub('<script type=\"application/json\" data-for=.*\">', "", json_dat)), file = "./widget_file_files/my_data.json")
To save the json-data as ./widget_file_files/my_data.json and then load it within the html. If you are using PHP you can do:
<script type="application/json" data-for="htmlwidget-2956">
<?php include('widget_file_files/my_data.json'); ?>
</script>
If you want to use a pure JS solution maybe have a look at http://api.jquery.com/jquery.getjson/ and the widget_file_files/htmlwidgets-0.5/htmlwidgets.js-File how the json-data is bound at the moment...
P.S.:
As this question got a lot of attention already you could also contact the package developer and ask him to further "un-selfcontain" the "selfcontained" option in htmlwidgets:::saveWidget: Meaning to save the json-data separately and include it e.g. via jquery.getjson
Related
Don't hide items when there are still space
I am trying to use the command bar of ng-office-ui-fabric, here is a code <!DOCTYPE html> <html> <head> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script> <link rel="stylesheet" href="https://static2.sharepointonline.com/files/fabric/office-ui-fabric-core/2.6.3/css/fabric.min.css" /> <link rel="stylesheet" href="https://static2.sharepointonline.com/files/fabric/office-ui-fabric-core/2.6.3/css/fabric.components.min.css" /> <script src="https://cdnjs.cloudflare.com/ajax/libs/ngOfficeUiFabric/0.15.3/ngOfficeUiFabric.min.js"></script> </head> <body ng-app="YourApp"> <div ng-controller="YourController"> <uif-command-bar> <uif-command-bar-main> <uif-command-bar-item> <span>one</span> </uif-command-bar-item> <uif-command-bar-item> <span>two</span> </uif-command-bar-item> <uif-command-bar-item> <span>three</span> </uif-command-bar-item> </uif-command-bar-main> </uif-command-bar> </div> <script type="text/javascript"> angular.module('YourApp', ['officeuifabric.core', 'officeuifabric.components']) .controller('YourController', ['$scope', function ($scope) {}]) </script> </body> </html> If we change the width of the preview, we could see that the items are hidden very easily (we could see a class is-hidden is added), even though there are visually lots of space. Does anyone know how to control this limit width such that the items are not hidden easily? Another option is never hiding the command items, does anyone know how to enable this? Otherwise, is it possible to make a command bar with office-ui-fabric in angularjs without ng-office-ui-fabric?
Alchemy.js simple example not working
I'm trying to implement this example in order to become familiar with Alchemy.js. http://graphalchemist.github.io/Alchemy/#/examples how can I fix this to make it work? <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Alchemy</title> <link rel="stylesheet" href="bower_components/alchemy.min.css"/> </head> <body> <div class="alchemy" id="alchemy"></div> <script src="bower_components/alchemy.min.js"></script> <script type="text/javascript"> alchemy.begin({dataSource: "charlize.json"}); </script> </body> </html>
Probably you are using the wrong library, try with this: (Can you try including the vendor script first and then the alchmey script.) <script src="https://cdnjs.cloudflare.com/ajax/libs/alchemyjs/0.4.2/scripts/vendor.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/alchemyjs/0.4.2/alchemy.min.js"></script>
Trying to ignore unused layout fragment in Thymeleaf Layout Dialect
Does anyone know if it's possible to hide a layout:fragment if it is not specified in the calling page? For example, I have a page layout.html that has something like (where there is a separate fragment.html file with header and footer fragments): <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" th:lang = "en"> <head> <title layout:title-pattern="$CONTENT_TITLE">TITLE</title> </head> <body> <header layout:replace="fragment :: header">HEADER</header> <section layout:fragment="messages">MESSAGES</section> <section layout:fragment="content">CONTENT</section> <footer layout:replace="fragment :: footer">FOOTER</footer> </body> </html> If in a calling page to the layout that I don't want to include the "messages" fragment, is there a way to do it by just not including that code? For example (say, simple.html): <html layout:decorator="layout"> <head> <title th:text=#{PAGETITLE_SIMPLE}>SIMPLE PAGE TITLE</title> </head> <body> <section layout:fragment="content"> <p>Put in some random content for the body of the simple page</p> </section> </body> This will still put into the rendered HTML the text "MESSAGES" inside a <section>-tag. I have been able to put into this simple.html <section layout:fragment="messages" th:remove="all"></section> But this seems somewhat sloppy and was wondering if there was a way to hide that from the users of the layout by putting the logic in the layout to ignore that fragment altogether. Using Spring 4.1.6, Thymleaf 2.1.4, and Layout Dialect 1.3.3. Thanks
I was able to resolve this by applying the methods posted by Serge Ballesta in How to check Thymeleaf fragment is defined to the layout dialect. This is what the rewritten layout.html looks like: <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" th:lang = "en"> <head> <title layout:title-pattern="$CONTENT_TITLE">TITLE</title> </head> <body> <header layout:replace="fragment :: header">HEADER</header> <section layout:replace="this :: messages">MESSAGES</section> <section layout:fragment="content">CONTENT</section> <footer layout:replace="fragment :: footer">FOOTER</footer> </body> </html> This way, if the calling page (simple.html) only has the <section> for content, no HTML will be rendered for the section for messages. But if the page did have the following, it will be included as intended: <section layout:fragment="messages"> <p>Message 1</p> <p>Message 2</p> </section>
Exporting as image from mermaid (Gantt)
I'm having an issue trying to export the Gantt chart as a png or any other image format. The Viewer within RStudio shows me the Gantt is rendered. It also gives me the option to save as an image, but I'm finding the image is very pixelated when you zoom in. Here is what I have tried, but the file comes up empty after running: library(DiagrammeR) m1<-mermaid(" gantt dateFormat MM/DD/YY title Example Gantt section Example Section Process1 :done, task_1, 01/01/01, 01/05/01 Process2 :done, task_2, 02/01/02, 02/05/02 Process3 :done, task_3, 03/01/03, 03/05/03 ") m1$x$config = list(ganttConfig = list( axisFormatter = list(list( "%y" ,htmlwidgets::JS( 'function(d){ return d.getDay() }' ) )) )) png("Example.png") m1 dev.off()
This is the code that executing that m1 object creates when run from an R console. I don't see an image in the SO viewing window, but apologies since I'm not a particularly knowledgeable user of that facility. You can view this in a browser, which is what RSudio is providing and it can be zoomed up to the browser limits and then screenshots will not be pixelated: <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.3.8/d3.min.js"></script> <!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <script src="lib/htmlwidgets-0.5/htmlwidgets.js"></script> <script src="lib/d3-3.3.8/d3.min.js"></script> <script src="lib/dagre-0.4.0/dagre-d3.min.js"></script> <link href="lib/mermaid-0.3.0/dist/mermaid.css" rel="stylesheet" /> <script src="lib/mermaid-0.3.0/dist/mermaid.slim.min.js"></script> <link href="lib/DiagrammeR-styles-0.2/styles.css" rel="stylesheet" /> <script src="lib/chromatography-0.1/chromatography.js"></script> <script src="lib/DiagrammeR-binding-0.8.1/DiagrammeR.js"></script> </head> <body style="background-color:white;"> <div id="htmlwidget_container"> <div id="htmlwidget-2084" style="width:960px;height:500px;" class="DiagrammeR"></div> </div> <script type="application/json" data-for="htmlwidget-2084">{"x":{"diagram":"\n gantt\n dateFormat MM/DD/YY\n title Example Gantt\n\n section Example Section\n Process1 :done, task_1, 01/01/01, 01/05/01\n Process2 :done, task_2, 02/01/02, 02/05/02\n Process3 :done, task_3, 03/01/03, 03/05/03\n ","config":{"ganttConfig":{"axisFormatter":[["%y","function(d){ return d.getDay() }"]]}}},"evals":["config.ganttConfig.axisFormatter.0.1"]}</script> <script type="application/htmlwidget-sizing" data-for="htmlwidget-2084">{"viewer":{"width":450,"height":350,"padding":15,"fill":true},"browser":{"width":960,"height":500,"padding":40,"fill":false}}</script> </body> </html>
unable to load a dicom image using cornerstone
I am trying to load a dicom image using cornerstone library. I get an error - uncaught exception: loadImage: no image loader for imageId. I have my image file named as image-1.dcm. What am I doing wrong? Here is my code: <!DOCTYPE HTML> <html> <head> <!-- twitter bootstrap CSS stylesheet - not required by cornerstone --> <link href="http://netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet"> </head> <body> <div class="container"> <h1> jsminimal/index.html </h1> This is an example of the minimal use of cornerstone driven by javascript <br> <br> In this example, javascript is used to image enable a div. <br> <br> <div id="dicomImage" style="width:512px;height:512px;"> </div> </div> </body> <!-- cornerstone depends on jQuery so it must be loaded first--> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script> <!-- include the cornerstone library --> <script src="cornerstone-master/dist/cornerstone.js"></script> <!-- include special code for these examples which provides images --> <script src="cornerstone-master/example/exampleImageIdLoader.js"></script> <script> $(document).ready(function() { var imageId = 'image-1'; var element = document.getElementById('dicomImage'); cornerstone.enable(element); cornerstone.loadImage(imageId).then(function(image) { cornerstone.displayImage(element, image); }); }); </script> </html>
You need to use the cornerstoneWADOImageLoader to loader DICOM P10: https://github.com/chafey/cornerstoneWADOImageLoader