mirror of
https://github.com/rstudio/shiny.git
synced 2026-04-29 03:00:45 -04:00
623 lines
12 KiB
HTML
623 lines
12 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
|
|
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
|
|
<style type="text/css">
|
|
svg {
|
|
border: 1px solid silver;
|
|
}
|
|
svg, #viz {
|
|
width: 600px;
|
|
height: 600px;
|
|
}
|
|
.node {
|
|
z-index: 1;
|
|
stroke: white;
|
|
stroke-width: 1px;
|
|
fill: #FEF2A9;
|
|
transition: stroke 0.75s ease;
|
|
}
|
|
.node.observer {
|
|
fill: #9C6E46;
|
|
}
|
|
.node.observable {
|
|
fill: #C7D4E3;
|
|
}
|
|
.node.value {
|
|
fill: #D0D0CD;
|
|
}
|
|
|
|
.node.invalidated {
|
|
stroke: #FF2B3D;
|
|
/*fill: url(#diagonalHatch);*/
|
|
}
|
|
.node.running {
|
|
stroke: #333;
|
|
}
|
|
#triangle {
|
|
fill: #CCC;
|
|
}
|
|
.link {
|
|
fill: none;
|
|
stroke: #CCC;
|
|
stroke-width: 0.5px;
|
|
z-index: 0;
|
|
}
|
|
#description {
|
|
position: fixed;
|
|
width: 300px;
|
|
left: 630px;
|
|
top: 36px;
|
|
height: auto;
|
|
}
|
|
</style>
|
|
<script>
|
|
var log = [
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "names(input)"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "input (all)"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "input$dataset"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "names(input)"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "input (all)"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "input$caption"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "names(input)"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "input (all)"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "input$obs"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "names(clientData)"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "clientData (all)"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "clientData$output_caption_hidden"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "names(clientData)"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "clientData (all)"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "clientData$output_summary_hidden"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "names(clientData)"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "clientData (all)"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "clientData$output_view_hidden"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "names(clientData)"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "clientData (all)"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "clientData$pixelratio"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "names(clientData)"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "clientData (all)"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "clientData$url_protocol"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "names(clientData)"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "clientData (all)"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "clientData$url_hostname"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "names(clientData)"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "clientData (all)"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "clientData$url_port"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "names(clientData)"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "clientData (all)"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "clientData$url_pathname"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "names(clientData)"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "clientData (all)"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "clientData$url_search"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "names(clientData)"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "clientData (all)"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "clientData$url_hash_initial"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "names(clientData)"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "clientData (all)"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "clientData$allowDataUriScheme"
|
|
},
|
|
{
|
|
"action" : "ctx",
|
|
"id" : "1",
|
|
"label" : "output$caption",
|
|
"type" : "observer",
|
|
"prevId" : ""
|
|
},
|
|
{
|
|
"action" : "invalidate",
|
|
"id" : "1"
|
|
},
|
|
{
|
|
"action" : "ctx",
|
|
"id" : "2",
|
|
"label" : "output$summary",
|
|
"type" : "observer",
|
|
"prevId" : ""
|
|
},
|
|
{
|
|
"action" : "invalidate",
|
|
"id" : "2"
|
|
},
|
|
{
|
|
"action" : "ctx",
|
|
"id" : "3",
|
|
"label" : "output$view",
|
|
"type" : "observer",
|
|
"prevId" : ""
|
|
},
|
|
{
|
|
"action" : "invalidate",
|
|
"id" : "3"
|
|
},
|
|
{
|
|
"action" : "ctx",
|
|
"id" : "4",
|
|
"label" : "output$caption",
|
|
"type" : "observer",
|
|
"prevId" : "1"
|
|
},
|
|
{
|
|
"action" : "enter",
|
|
"id" : "4"
|
|
},
|
|
{
|
|
"action" : "dep",
|
|
"id" : "4",
|
|
"dependsOn" : "input$caption"
|
|
},
|
|
{
|
|
"action" : "exit",
|
|
"id" : "4"
|
|
},
|
|
{
|
|
"action" : "ctx",
|
|
"id" : "5",
|
|
"label" : "output$summary",
|
|
"type" : "observer",
|
|
"prevId" : "2"
|
|
},
|
|
{
|
|
"action" : "enter",
|
|
"id" : "5"
|
|
},
|
|
{
|
|
"action" : "ctx",
|
|
"id" : "6",
|
|
"label" : "reactive({\n switch(input$dataset, rock = rock, pressure = pressure, cars = cars)\n})",
|
|
"type" : "observable",
|
|
"prevId" : ""
|
|
},
|
|
{
|
|
"action" : "enter",
|
|
"id" : "6"
|
|
},
|
|
{
|
|
"action" : "dep",
|
|
"id" : "6",
|
|
"dependsOn" : "input$dataset"
|
|
},
|
|
{
|
|
"action" : "exit",
|
|
"id" : "6"
|
|
},
|
|
{
|
|
"action" : "depId",
|
|
"id" : "5",
|
|
"dependsOn" : "6"
|
|
},
|
|
{
|
|
"action" : "exit",
|
|
"id" : "5"
|
|
},
|
|
{
|
|
"action" : "ctx",
|
|
"id" : "7",
|
|
"label" : "output$view",
|
|
"type" : "observer",
|
|
"prevId" : "3"
|
|
},
|
|
{
|
|
"action" : "enter",
|
|
"id" : "7"
|
|
},
|
|
{
|
|
"action" : "depId",
|
|
"id" : "7",
|
|
"dependsOn" : "6"
|
|
},
|
|
{
|
|
"action" : "dep",
|
|
"id" : "7",
|
|
"dependsOn" : "input$obs"
|
|
},
|
|
{
|
|
"action" : "exit",
|
|
"id" : "7"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "names(input)"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "input (all)"
|
|
},
|
|
{
|
|
"action" : "valueChange",
|
|
"id" : "input$dataset"
|
|
},
|
|
{
|
|
"action" : "invalidate",
|
|
"id" : "6"
|
|
},
|
|
{
|
|
"action" : "invalidate",
|
|
"id" : "5"
|
|
},
|
|
{
|
|
"action" : "invalidate",
|
|
"id" : "7"
|
|
},
|
|
{
|
|
"action" : "ctx",
|
|
"id" : "8",
|
|
"label" : "output$summary",
|
|
"type" : "observer",
|
|
"prevId" : "5"
|
|
},
|
|
{
|
|
"action" : "enter",
|
|
"id" : "8"
|
|
},
|
|
{
|
|
"action" : "ctx",
|
|
"id" : "9",
|
|
"label" : "reactive({\n switch(input$dataset, rock = rock, pressure = pressure, cars = cars)\n})",
|
|
"type" : "observable",
|
|
"prevId" : "6"
|
|
},
|
|
{
|
|
"action" : "enter",
|
|
"id" : "9"
|
|
},
|
|
{
|
|
"action" : "dep",
|
|
"id" : "9",
|
|
"dependsOn" : "input$dataset"
|
|
},
|
|
{
|
|
"action" : "exit",
|
|
"id" : "9"
|
|
},
|
|
{
|
|
"action" : "depId",
|
|
"id" : "8",
|
|
"dependsOn" : "9"
|
|
},
|
|
{
|
|
"action" : "exit",
|
|
"id" : "8"
|
|
},
|
|
{
|
|
"action" : "ctx",
|
|
"id" : "10",
|
|
"label" : "output$view",
|
|
"type" : "observer",
|
|
"prevId" : "7"
|
|
},
|
|
{
|
|
"action" : "enter",
|
|
"id" : "10"
|
|
},
|
|
{
|
|
"action" : "depId",
|
|
"id" : "10",
|
|
"dependsOn" : "9"
|
|
},
|
|
{
|
|
"action" : "dep",
|
|
"id" : "10",
|
|
"dependsOn" : "input$obs"
|
|
},
|
|
{
|
|
"action" : "exit",
|
|
"id" : "10"
|
|
}
|
|
];
|
|
try {
|
|
log = __DATA__;
|
|
} catch (e) {}
|
|
|
|
var nodes = {};
|
|
var nodeList = [];
|
|
var nodeSelection = null;
|
|
var links = [];
|
|
var linkSelection = null;
|
|
|
|
var node, link; // d3 selections
|
|
|
|
var force = d3.layout.force()
|
|
.nodes(nodeList)
|
|
.links(links)
|
|
.size([150, 150]);
|
|
force.on('tick', onTick);
|
|
|
|
function update() {
|
|
var layoutDirty = true;
|
|
|
|
node = d3.select('#nodes').selectAll('.node').data(nodeList);
|
|
//layoutDirty = layoutDirty || !node.enter().empty() || !node.exit().empty();
|
|
node.enter().append('circle')
|
|
.attr('class', function(n) {return 'node ' + n.type;})
|
|
.attr('title', function(n) {return n.label;})
|
|
.attr('r', 5)
|
|
.attr('onmouseover', '$("#description").text(this.getAttribute("title"));')
|
|
.attr('onmouseout', '$("#description").html("<br/>");')
|
|
.call(force.drag);
|
|
node.exit().remove();
|
|
node
|
|
.classed('invalidated', function(n) { return n.invalidated; })
|
|
.classed('running', function(n) { return n.running; })
|
|
.attr('fill', function(n) {
|
|
if (n.invalidated)
|
|
return "url(#diagonalHatch)";
|
|
else
|
|
return null;
|
|
});
|
|
|
|
link = d3.select('#links').selectAll('.link').data(links);
|
|
//layoutDirty = layoutDirty || !link.enter().empty() || !link.exit().empty();
|
|
link.enter().append('path')
|
|
.attr('class', 'link')
|
|
.attr('marker-start', 'url(#triangle)');
|
|
link.exit().remove();
|
|
|
|
if (layoutDirty) {
|
|
force.start();
|
|
layoutDirty = false;
|
|
}
|
|
}
|
|
|
|
function onTick() {
|
|
node
|
|
.attr('cx', function(n) { return n.x; })
|
|
.attr('cy', function(n) { return n.y; });
|
|
link
|
|
.attr('d', function(link) {
|
|
return 'M' + link.source.x + ',' + link.source.y +
|
|
' L' + link.target.x + ',' + link.target.y;
|
|
});
|
|
}
|
|
|
|
function createNode(data, type) {
|
|
var node;
|
|
if (!data.prevId) {
|
|
node = {
|
|
label: data.label,
|
|
type: data.type,
|
|
index: nodeList.length
|
|
};
|
|
nodes[data.id] = node;
|
|
nodeList.push(node);
|
|
} else {
|
|
node = nodes[data.prevId];
|
|
delete nodes[data.prevId];
|
|
nodes[data.id] = node;
|
|
node.invalidated = false;
|
|
}
|
|
}
|
|
|
|
var callbacks = {
|
|
ctx: function(data) {
|
|
createNode(data);
|
|
return true;
|
|
},
|
|
dep: function(data) {
|
|
if (!nodes[data.dependsOn])
|
|
createNode({id: data.dependsOn, label: data.dependsOn, type: 'value'});
|
|
links.push({
|
|
source: nodes[data.id],
|
|
target: nodes[data.dependsOn]
|
|
});
|
|
},
|
|
depId: function(data) {
|
|
links.push({
|
|
source: nodes[data.id],
|
|
target: nodes[data.dependsOn]
|
|
});
|
|
},
|
|
invalidate: function(data) {
|
|
var node = nodes[data.id];
|
|
node.invalidated = true;
|
|
links = links.filter(function(link) {
|
|
return link.source !== node;
|
|
});
|
|
},
|
|
valueChange: function(data) {
|
|
return true;
|
|
},
|
|
enter: function(data) {
|
|
var node = nodes[data.id];
|
|
node.running = true;
|
|
},
|
|
exit: function(data) {
|
|
var node = nodes[data.id];
|
|
node.running = false;
|
|
}
|
|
};
|
|
|
|
function processMessage(data) {
|
|
console.log(JSON.stringify(data));
|
|
if (!callbacks.hasOwnProperty(data.action))
|
|
throw new Error('Unknown action ' + data.action);
|
|
var result = callbacks[data.action].call(callbacks, data);
|
|
update();
|
|
return result;
|
|
}
|
|
|
|
function doNext() {
|
|
while (log.length)
|
|
if (!processMessage(log.shift()))
|
|
break;
|
|
if (log.length === 0)
|
|
document.getElementById('processNext').setAttribute('disabled', 'disabled');
|
|
}
|
|
|
|
function zoom() {
|
|
var scale = d3.event.scale;
|
|
var x = d3.event.translate[0];
|
|
var y = d3.event.translate[1];
|
|
d3.select('#viz').attr('transform', 'scale(' + scale + ') translate(' + x/scale + ' ' + y/scale + ')');
|
|
}
|
|
$(function() {
|
|
d3.select('svg').call(d3.behavior.zoom().scale(4).on('zoom', zoom));
|
|
});
|
|
</script>
|
|
<body>
|
|
<button id="processNext" onclick="doNext();">Next</button>
|
|
<br/>
|
|
<div id="container">
|
|
<svg>
|
|
<defs>
|
|
<marker id="triangle"
|
|
viewBox="0 0 10 10"
|
|
refX="-18" refY="5"
|
|
markerWidth="6"
|
|
markerHeight="6"
|
|
orient="auto">
|
|
<path d="M 10 0 L 0 5 L 10 10 z" />
|
|
</marker>
|
|
<pattern id="diagonalHatch" patternUnits="userSpaceOnUse" width="1" height="1">
|
|
<path stroke="black" stroke-width="0.25" fill="none"
|
|
d="M-1,1 l2,-2
|
|
M0,4 l4,-4
|
|
M3,5 l2,-2" />
|
|
</pattern>
|
|
</defs>
|
|
<g id="viz" transform="scale(4)">
|
|
<g id="links"></g>
|
|
<g id="nodes"></g>
|
|
</g>
|
|
</svg>
|
|
</div>
|
|
<pre id="description"><br/></pre>
|
|
</body>
|
|
</html>
|
|
<!--
|
|
<svg style="border: 1px solid silver; width: 400px; height: 400px">
|
|
<g>
|
|
<path stroke="black" stroke-width="4" fill="white" d="m 58,2 c -75,0 -75,100 0,100 l 60,0 l 50,-50 l -50,-50 Z"/>
|
|
</g>
|
|
<g transform="translate(0 110)">
|
|
<path stroke="black" stroke-width="4" fill="white" d="m 58,2 c -75,0 -75,100 0,100 l 100,0 l 0,-100 Z"/>
|
|
</g>
|
|
<g transform="translate(0 220)">
|
|
<path stroke="black" stroke-width="4" fill="white" d="m 2,0 l 0,100 l 100,0 l 50,-50 l -50,-50 Z"/>
|
|
</g>
|
|
</svg>
|
|
--> |