Files
shiny/inst/www/reactive-graph.html
2013-07-02 13:21:39 -07:00

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>
-->