// Generated by CoffeeScript 1.10.0 (function() { // noprotect ; var R, char_window, current_sentence, defs, diameter, distance, editor, find_annotations, height, max_depth, prefixes, svg, vis, width; prefixes = { rdf: 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', owl: 'http://www.w3.org/2002/07/owl#', rdfs: 'http://www.w3.org/2000/01/rdf-schema#', foaf: 'http://xmlns.com/foaf/0.1/', dbo: 'http://dbpedia.org/ontology/', dbr: 'http://dbpedia.org/resource/', wiki: 'http://en.wikipedia.org/wiki/' }; /* Manuscript EDITOR */ width = 960 / 2; height = 500; diameter = width * 1.4; max_depth = 3; distance = 40; char_window = 15; svg = d3.select('svg'); vis = svg.append('g'); defs = svg.append('defs'); R = 18; /* define arrow markers for graph links */ defs.append('marker').attr({ id: 'end-arrow', viewBox: '0 0 10 10', refX: 5 + R, refY: 5, orient: 'auto' }).append('path').attr({ d: 'M0,0 L0,10 L10,5 z' }); CodeMirror.defineSimpleMode('mtss', { start: [ { regex: new RegExp('(\\<)([^\\>]*)(\\>)(\\()([^\\)]*)(\\))'), token: ['span_symbol', 'span_text', 'span_symbol', 'entity_symbol', 'entity_id', 'entity_symbol'] }, { regex: new RegExp('^___$'), token: 'start_directives', next: 'directives' } ], directives: [ { regex: new RegExp('(\\()(.*)(\\))'), token: ['entity_symbol', 'entity_id', 'entity_symbol'] }, { regex: new RegExp('.'), token: 'directive' } ] }); editor = CodeMirror.fromTextArea(document.getElementById('editor'), { mode: 'mtss', lineNumbers: false, lineWrapping: true, gutters: ['error_gutter'] }); /* TEXT TRANSLATION Every time the text is changed new annotations are searched, the diagram is updated */ editor.on('change', function() { return find_annotations(); }); find_annotations = function() { /* DATA CONSTRUCTION */ var PAD_MULTIPLIER, content, d3cola, enter_as, enter_links, enter_nodes, entity_index, graph, i, j, k, l, len, len1, len2, len3, len4, len5, levels, link_labels, links, m, n, nn, nodes, o, q, r, ref, ref1, ref2, ref3, ref4, text, topological_order; text = editor.getValue(); editor.clearGutter('error_gutter'); parser.parse(text); /* GRAPH */ content = { type: 'content' }; nodes = [content]; links = []; graph = { nodes: nodes, links: links }; entity_index = {}; parser.directives.forEach(function(d) { var n; if (!(d.id in entity_index)) { n = { type: 'entity', id: d.id }; nodes.push(n); entity_index[d.id] = n; } else { n = entity_index[d.id]; } return d.popairs.forEach(function(p) { var ext_n; ext_n = { type: 'external', id: p.object }; nodes.push(ext_n); return links.push({ source: n, target: ext_n, type: 'predicate', predicate: p.predicate }); }); }); parser.annotations.forEach(function(a, i) { var n; n = { type: 'span', id: i }; nodes.push(n); links.push({ source: content, target: n, start: a.start, end: a.end, type: 'locus', inverted: true }); return links.push({ source: n, target: entity_index[a.id], type: 'about' }); }); /* VISUALIZATION */ /* store the node index into the node itself */ ref = graph.nodes; for (i = j = 0, len = ref.length; j < len; i = ++j) { n = ref[i]; n.i = i; } /* store neighbor nodes into each node */ ref1 = graph.nodes; for (i = k = 0, len1 = ref1.length; k < len1; i = ++k) { n = ref1[i]; n.in_neighbors = []; n.out_neighbors = []; } ref2 = graph.links; for (m = 0, len2 = ref2.length; m < len2; m++) { l = ref2[m]; l.source.out_neighbors.push(l.target); l.target.in_neighbors.push(l.source); } /* compute longest distances */ topological_order = tsort(graph.links.map(function(l) { return [l.source.i, l.target.i]; })); ref3 = graph.nodes; for (o = 0, len3 = ref3.length; o < len3; o++) { n = ref3[o]; n.longest_dist = -Infinity; } graph.nodes.forEach(function(n) { if (n.in_neighbors.length === 0) { return n.longest_dist = (function() { switch (n.type) { case 'content': return 0; case 'entity': return 2; } })(); } }); for (q = 0, len4 = topological_order.length; q < len4; q++) { i = topological_order[q]; n = graph.nodes[i]; ref4 = n.out_neighbors; for (r = 0, len5 = ref4.length; r < len5; r++) { nn = ref4[r]; if (nn.longest_dist < n.longest_dist + 1) { nn.longest_dist = n.longest_dist + 1; } } } graph.constraints = []; /* create the alignment contraints */ levels = _.uniq(graph.nodes.map(function(n) { return n.longest_dist; })); levels.sort(); levels.forEach(function(depth) { return graph.constraints.push({ type: 'alignment', axis: 'x', offsets: graph.nodes.filter(function(n) { return n.longest_dist === depth; }).map(function(n) { return { node: n.i, offset: 0 }; }) }); }); PAD_MULTIPLIER = 3.5; /* create the position contraints */ levels.forEach(function(depth, i) { var n1, n2; if (i < levels.length - 1) { n1 = _.find(graph.nodes, function(n) { return n.longest_dist === depth; }); n2 = _.find(graph.nodes, function(n) { return n.longest_dist === depth + 1; }); return graph.constraints.push({ axis: 'x', left: n1.i, right: n2.i, gap: depth < 2 ? 5 * R : 8 * R }); } }); /* create nodes and links */ vis.selectAll('.link').remove(); vis.selectAll('.node').remove(); vis.selectAll('.link_label').remove(); links = vis.selectAll('.link').data(graph.links); enter_links = links.enter().append('line').attr({ "class": function(d) { return "link " + d.type; } }); enter_links.append('title').text(function(d) { return 'link'; }); link_labels = vis.selectAll('.link_label').data(graph.links); link_labels.enter().append('text').text(function(d) { if (d.type === 'predicate') { return d.predicate; } else { return d.type; } }).attr({ "class": 'link_label' }); nodes = vis.selectAll('.node').data(graph.nodes); enter_nodes = nodes.enter().append('g').attr({ "class": function(d) { return "node " + d.type; } }); enter_nodes.append('circle').attr({ r: R }); enter_as = enter_nodes.append('a').attr({ target: '_blank' }); enter_as.filter(function(d) { return d.type === 'external'; }).attr({ "class": 'valid', 'xlink:href': function(d) { var splitted; if (d.type !== 'external') { return ''; } splitted = ('' + d.id).split(':'); if (splitted[0] === 'http') { return d.id; } else { return prefixes[splitted[0]] + splitted[1]; } } }); enter_as.append('text').text(function(d) { switch (d.type) { case 'external': return d.id; case 'content': return 'CONTENT'; case 'span': return "< >"; case 'entity': return "(" + d.id + ")"; } }).attr({ "class": 'label', dy: '0.35em' }); /* cola layout */ graph.nodes.forEach(function(v, i) { v.width = PAD_MULTIPLIER * R; v.height = PAD_MULTIPLIER * R; v.x = i; return v.y = i; }); content.x = R + 20; content.y = height / 2; content.fixed = true; d3cola = cola.d3adaptor().size([width, height]).linkDistance(60).constraints(graph.constraints).avoidOverlaps(true).nodes(graph.nodes).links(graph.links).on('tick', function() { /* update nodes and links */ nodes.attr('transform', function(d) { return "translate(" + d.x + "," + d.y + ")"; }); links.filter(function(d) { return !d.inverted; }).attr('x1', function(d) { return d.source.x; }).attr('y1', function(d) { return d.source.y; }).attr('x2', function(d) { return d.target.x; }).attr('y2', function(d) { return d.target.y; }); links.filter(function(d) { return d.inverted; }).attr('x1', function(d) { return d.target.x; }).attr('y1', function(d) { return d.target.y; }).attr('x2', function(d) { return d.source.x; }).attr('y2', function(d) { return d.source.y; }); return link_labels.attr({ transform: function(d) { return "translate(" + ((d.source.x + d.target.x) / 2) + " " + ((d.source.y + d.target.y) / 2) + ") rotate(" + (Math.atan2(d.target.y - d.source.y, d.target.x - d.source.x) / Math.PI / 2 * 360) + ") translate(0,-5)"; } }); }); enter_nodes.call(d3cola.drag); return d3cola.start(100, 30, 30); }; find_annotations(); /* Sentence highlighting */ current_sentence = null; editor.on('cursorActivity', function() { var cursor, from, search_cursor, to; cursor = editor.getCursor(); search_cursor = editor.getSearchCursor('||', cursor); search_cursor.findPrevious(); from = search_cursor.pos.to; search_cursor.findNext(); to = search_cursor.pos.from; if (current_sentence != null) { current_sentence.clear(); } return current_sentence = editor.markText(from, to, { className: 'sentence_highlight' }); }); /* Error reporting */ window.on_code_error = function(message, details) { var error_marker; error_marker = d3.select(document.createElement('a')).text('X').style({ 'text-align': 'center', background: 'red', color: 'white', display: 'inline-block', width: '100%' }).attr({ title: "Unexpected " + details.token + ": " + details.text }); return editor.setGutterMarker(details.line, 'error_gutter', error_marker.node()); }; }).call(this);