CofeehousePy/services/corenlp/classes/edu/stanford/nlp/pipeline/demo/corenlp-parseviewer.js

215 lines
6.1 KiB
JavaScript

//'use strict';
//d3 || require('d3');
//var dagreD3 = require('dagre-d3');
//var jquery = require('jquery');
//var $ = jquery;
var ParseViewer = function(params) {
// Container in which the scene template is displayed
this.selector = params.selector;
this.container = $(this.selector);
this.fitToGraph = true;
this.onClickNodeCallback = params.onClickNodeCallback;
this.onHoverNodeCallback = params.onHoverNodeCallback;
this.init();
return this;
};
ParseViewer.MIN_WIDTH = 100;
ParseViewer.MIN_HEIGHT = 100;
ParseViewer.prototype.constructor = ParseViewer;
ParseViewer.prototype.getAutoWidth = function () {
return Math.max(ParseViewer.MIN_WIDTH, this.container.width());
};
ParseViewer.prototype.getAutoHeight = function () {
return Math.max(ParseViewer.MIN_HEIGHT, this.container.height() - 20);
};
ParseViewer.prototype.init = function () {
var canvasWidth = this.getAutoWidth();
var canvasHeight = this.getAutoHeight();
this.parseElem = d3.select(this.selector)
.append('svg')
.attr({'width': canvasWidth, 'height': canvasHeight})
.style({'width': canvasWidth, 'height': canvasHeight});
console.log(this.parseElem);
this.graph = null;
this.graphRendered = false;
this.controls = $('<div class="text"></div>');
this.container.append(this.controls);
};
var GraphBuilder = function(roots) {
// Create the input graph
this.graph = new dagreD3.graphlib.Graph()
.setGraph({})
.setDefaultEdgeLabel(function () {
return {};
});
this.visitIndex = 0;
//console.log('building graph', roots);
for (var i = 0; i < roots.length; i++) {
this.build(roots[i]);
}
};
GraphBuilder.prototype.build = function(node) {
console.log(node);
// Track my visit index
this.visitIndex++;
node.visitIndex = this.visitIndex;
// Add a node
var nodeData = node; // TODO: replace with semantic data
var nodeLabel = node.label;
var nodeIndex = node.visitIndex;
var nodeClass = 'parse-RULE';
this.graph.setNode(nodeIndex, { label: nodeLabel, class: nodeClass, data: nodeData });
if (node.parent) {
this.graph.setEdge(node.parent.visitIndex, nodeIndex, {
class: 'parse-EDGE'
});
}
if (node.isTerminal) {
this.visitIndex++;
nodeIndex = this.visitIndex;
nodeLabel = node.text;
nodeClass = 'parse-TERMINAL';
this.graph.setNode(nodeIndex, { label: nodeLabel, class: nodeClass, data: nodeData });
this.graph.setEdge(node.visitIndex, nodeIndex, {
class: 'parse-EDGE'
});
} else if (node.children) {
for (var i = 0; i < node.children.length; i++) {
this.build(node.children[i]);
}
}
};
ParseViewer.prototype.updateGraphPosition = function (svg, g, minWidth, minHeight) {
if (this.fitToGraph) {
minWidth = g.graph().width;
minHeight = this.getAutoHeight();
}
adjustGraphPositioning(svg, g, minWidth, minHeight);
};
function adjustGraphPositioning(svg, g, minWidth, minHeight) {
// Resize svg
var newWidth = Math.max(minWidth, g.graph().width);
var newHeight = Math.max(minHeight, g.graph().height + 40);
svg.attr({'width': newWidth, 'height': newHeight});
svg.style({'width': newWidth, 'height': newHeight});
// Center the graph
var svgGroup = svg.select('g');
var xCenterOffset = (svg.attr('width') - g.graph().width) / 2;
svgGroup.attr('transform', 'translate(' + xCenterOffset + ', 20)');
svg.attr('height', g.graph().height + 40);
svg.style('height', g.graph().height + 40);
}
ParseViewer.prototype.renderGraph = function (svg, g, parse) {
// Create the renderer
var render = new dagreD3.render();
// Run the renderer. This is what draws the final graph.
var svgGroup = svg.select('g');
render(svgGroup, g);
var scope = this;
var nodes = svgGroup.selectAll('g.node');
nodes.on('click',
function (d) {
var v = d;
var node = g.node(v);
if (scope.onClickNodeCallback) {
scope.onClickNodeCallback(node.data);
}
console.log(g.node(v));
}
);
nodes.on('mouseover',
function (d) {
var v = d;
var node = g.node(v);
if (scope.onHoverNodeCallback) {
scope.onHoverNodeCallback(node.data);
}
}
);
this.updateGraphPosition(svg, g, svg.attr('width'), svg.attr('height'));
this.graphRendered = true;
};
ParseViewer.prototype.showParse = function (root) {
this.showParses([root]);
};
ParseViewer.prototype.showParses = function (roots) {
// Take parse and create a graph
var gb = new GraphBuilder(roots);
var g = gb.graph;
g.nodes().forEach(function (v) {
var node = g.node(v);
// Round the corners of the nodes
node.rx = node.ry = 5;
});
var svg = this.parseElem;
svg.selectAll('*').remove();
var svgGroup = svg.append('g');
this.graph = g;
this.parse = roots;
if (this.container.is(':visible')) {
if (roots.length > 0) {
this.renderGraph(svg, this.graph, this.parse);
}
} else {
this.graphRendered = false;
}
};
ParseViewer.prototype.showAnnotation = function (annotation) {
var parses = [];
for (var i = 0; i < annotation.sentences.length; i++) {
var s = annotation.sentences[i];
if (s && s.parseTree) {
parses.push(s.parseTree);
}
}
this.showParses(parses);
};
ParseViewer.prototype.onResize = function () {
var canvasWidth = this.getAutoWidth();
var canvasHeight = this.getAutoHeight();
var svg = this.parseElem;
// Center the graph
var svgGroup = svg.select('g');
if (svgGroup && this.graph) {
if (!this.graphRendered) {
svg.attr({'width': canvasWidth, 'height': canvasHeight});
svg.style({'width': canvasWidth, 'height': canvasHeight});
this.renderGraph(svg, this.graph, this.parse);
} else {
this.updateGraphPosition(svg, this.graph, canvasWidth, canvasHeight);
}
} else {
svg.attr({'width': canvasWidth, 'height': canvasHeight});
svg.style({'width': canvasWidth, 'height': canvasHeight});
}
};
// Exports
//module.exports = ParseViewer;