Initial Commit
This commit is contained in:
commit
bbb0a2f580
126 changed files with 14189 additions and 0 deletions
167
static/js/cayley_main.js
Normal file
167
static/js/cayley_main.js
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
// Copyright 2014 The Cayley Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
$(function() {
|
||||
s = null;
|
||||
group = null;
|
||||
Snap.load("/static/cayley.svg", function(d, err) {
|
||||
//Snap(105,65).append(d);
|
||||
s = Snap("#logo").append(d);
|
||||
svg = Snap("svg");
|
||||
var c = svg.selectAll("*")
|
||||
group = svg.group()
|
||||
group.add(c)
|
||||
scale = new Snap.Matrix();
|
||||
scale.scale(0.5);
|
||||
group.transform(scale)
|
||||
})
|
||||
|
||||
neutralColor = "#999999"
|
||||
green = "#0F9D58"
|
||||
|
||||
stopAndReset = function () {
|
||||
for (var i = 0; i < 19; i++) {
|
||||
group[i].stop()
|
||||
}
|
||||
for (var i = 0; i < currentTimeouts.length; i++) {
|
||||
clearTimeout(currentTimeouts[i])
|
||||
}
|
||||
currentTimeouts = []
|
||||
group[17].attr({fill: neutralColor})
|
||||
group[18].attr({fill: neutralColor})
|
||||
for (var i = 1; i < 11; i++) {
|
||||
group[i].attr({stroke: neutralColor})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
currentTimeouts = []
|
||||
|
||||
flash = function(elem, start) {
|
||||
currentTimeouts.push(
|
||||
setTimeout(function() { elem.animate({stroke: green}, 1000)}, start * 1000))
|
||||
currentTimeouts.push(
|
||||
setTimeout(function() { elem.animate({stroke: neutralColor}, 1200)}, (start + 1) * 1000))
|
||||
}
|
||||
|
||||
animate = function() {
|
||||
group[17].animate({fill: green}, 1000)
|
||||
currentTimeouts.push(
|
||||
setTimeout(function() {group[17].animate({fill: neutralColor}, 1200)}, 1000))
|
||||
flash(group[1], 0.5)
|
||||
flash(group[8], 1.0)
|
||||
flash(group[4], 1.5)
|
||||
flash(group[10], 1.0)
|
||||
flash(group[6], 1.5)
|
||||
flash(group[2], 2.0)
|
||||
currentTimeouts.push(
|
||||
setTimeout(function() {group[18].animate({fill: green}, 1000)}, 2500))
|
||||
currentTimeouts.push(
|
||||
setTimeout(function() {group[18].animate({fill: neutralColor}, 1200)}, 3500))
|
||||
currentTimeouts.push(
|
||||
setTimeout(function() {group[17].animate({fill: green}, 1000)}, 3500))
|
||||
currentTimeouts.push(
|
||||
setTimeout(function() {group[17].animate({fill: neutralColor}, 1200)}, 4500))
|
||||
flash(group[1], 4.0)
|
||||
flash(group[7], 4.5)
|
||||
flash(group[5], 5.0)
|
||||
flash(group[9], 4.5)
|
||||
flash(group[3], 5.0)
|
||||
flash(group[2], 5.5)
|
||||
currentTimeouts.push(
|
||||
setTimeout(function() {group[18].animate({fill: green}, 1000)}, 6000))
|
||||
currentTimeouts.push(
|
||||
setTimeout(function() {group[18].animate({fill: neutralColor}, 1200, function() {
|
||||
stopAndReset();
|
||||
animate();
|
||||
})}, 7000))
|
||||
}
|
||||
|
||||
if ($("#code").length != 0) {
|
||||
editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
||||
lineNumbers: true,
|
||||
matchBrackets: true,
|
||||
continueComments: "Enter",
|
||||
// extraKeys: {"Ctrl-Q": "toggleComment"}
|
||||
});
|
||||
} else{
|
||||
editor = null;
|
||||
}
|
||||
|
||||
var defaultQueryStrings = {
|
||||
"gremlin": "g.Emit('Hello World')",
|
||||
"mql": "[{\n \"id\": \"Hello World\"\n}]"
|
||||
}
|
||||
|
||||
var getLastQueryStringFor = function(type) {
|
||||
if (typeof(Storage) !== "undefined") {
|
||||
return localStorage.getItem("cayleySavedQueries" + type)
|
||||
} else {
|
||||
return defaultQueryStrings[type]
|
||||
}
|
||||
}
|
||||
|
||||
var switchTo = function(type) {
|
||||
if (type === "gremlin") { switchToGremlin()}
|
||||
if (type === "mql") { switchToMQL()}
|
||||
if (typeof(Storage) !== "undefined") {
|
||||
localStorage.setItem("cayleyQueryLang", type);
|
||||
}
|
||||
if (editor) {
|
||||
editor.setValue(getLastQueryStringFor(type))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var switchToGremlin = function () {
|
||||
$("#selected-query-lang").html("Gremlin " + caretSpan)
|
||||
selectedQueryLanguage = "gremlin"
|
||||
}
|
||||
|
||||
var switchToMQL = function() {
|
||||
$("#selected-query-lang").html("MQL" + caretSpan)
|
||||
selectedQueryLanguage = "mql"
|
||||
}
|
||||
|
||||
selectedQueryLanguage = "gremlin"
|
||||
var caretSpan = "   <span class='caret'></span>"
|
||||
|
||||
if (typeof(Storage) !== "undefined") {
|
||||
savedQueries = localStorage.getItem("cayleySavedQueriesmql");
|
||||
if (savedQueries === null) {
|
||||
for (var key in defaultQueryStrings) {
|
||||
localStorage.setItem("cayleySavedQueries" + key, defaultQueryStrings[key])
|
||||
}
|
||||
}
|
||||
lang = localStorage.getItem("cayleyQueryLang");
|
||||
if (lang !== null) {
|
||||
switchTo(lang)
|
||||
} else {
|
||||
switchTo("gremlin")
|
||||
}
|
||||
} else {
|
||||
switchTo("gremlin")
|
||||
}
|
||||
|
||||
|
||||
$("#gremlin-dropdown").click(function() {
|
||||
switchTo("gremlin")
|
||||
})
|
||||
|
||||
$("#mql-dropdown").click(function() {
|
||||
switchTo("mql")
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
41
static/js/cayley_query.js
Normal file
41
static/js/cayley_query.js
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright 2014 The Cayley Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
$(function() {
|
||||
|
||||
$("#sbQuery").addClass("active");
|
||||
|
||||
output_editor = CodeMirror.fromTextArea(document.getElementById("output"), {
|
||||
lineNumbers: true,
|
||||
matchBrackets: true,
|
||||
});
|
||||
|
||||
$("#run_button").click(function() {
|
||||
var data = editor.getValue()
|
||||
$("#output").text(editor.getValue())
|
||||
animate();
|
||||
$.post("/api/v1/query/" + selectedQueryLanguage, data)
|
||||
.done(function(return_data) {
|
||||
if (typeof(Storage) !== "undefined") {
|
||||
localStorage.setItem("cayleySavedQueries" + selectedQueryLanguage, data)
|
||||
}
|
||||
output_editor.setValue(return_data)
|
||||
stopAndReset();
|
||||
})
|
||||
.fail(function(jqxhr, textStatus, errorThrown){
|
||||
output_editor.setValue(jqxhr.responseText)
|
||||
stopAndReset();
|
||||
})
|
||||
})
|
||||
});
|
||||
33
static/js/cayley_shape.js
Normal file
33
static/js/cayley_shape.js
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright 2014 The Cayley Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
$(function() {
|
||||
$("#sbQueryShape").addClass("active");
|
||||
|
||||
$("#run_button").click(function() {
|
||||
var data = editor.getValue()
|
||||
$.post("/api/v1/shape/" + selectedQueryLanguage, data)
|
||||
.done(function(return_data) {
|
||||
if (typeof(Storage) !== "undefined") {
|
||||
localStorage.setItem("cayleySavedQueries" + selectedQueryLanguage, data)
|
||||
}
|
||||
shape = $.parseJSON(return_data)
|
||||
$("#viz").empty()
|
||||
if (shape.hasOwnProperty("nodes")) {
|
||||
var net = Network()
|
||||
net("#viz", shape)
|
||||
}
|
||||
});
|
||||
});
|
||||
})
|
||||
113
static/js/cayley_visualize.js
Normal file
113
static/js/cayley_visualize.js
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
// Copyright 2014 The Cayley Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
$(function() {
|
||||
$("#sbVisualize").addClass("active");
|
||||
|
||||
var createGraphVisualization = function(results) {
|
||||
if (window.sigmaGraph !== undefined) {
|
||||
sigmaGraph.stopForceAtlas2()
|
||||
sigmaGraph.kill()
|
||||
$("#visualize").text("")
|
||||
}
|
||||
var nodeMap = {}
|
||||
var g = {nodes: [], edges: []}
|
||||
for (var i = 0; i < results.length; i++) {
|
||||
result = results[i];
|
||||
source = result["source"]
|
||||
target = result["target"]
|
||||
var source_color
|
||||
var target_color
|
||||
if (result["source_color"] != undefined) {
|
||||
source_color = result["source_color"]
|
||||
} else {
|
||||
//source_color = "#2c3e50"
|
||||
source_color = "#001B8A"
|
||||
}
|
||||
if (result["target_color"] != undefined) {
|
||||
target_color = result["target_color"]
|
||||
} else {
|
||||
target_color = "#F09300"
|
||||
}
|
||||
if (nodeMap[source] !== true) {
|
||||
var data = {
|
||||
id: source,
|
||||
x: Math.random(),
|
||||
y: Math.random(),
|
||||
size: 10,
|
||||
color: source_color
|
||||
|
||||
}
|
||||
if (result["source_label"] != undefined) {
|
||||
data.label = result["source_label"]
|
||||
} else {
|
||||
data.label = source
|
||||
}
|
||||
g.nodes.push(data)
|
||||
nodeMap[source] = true
|
||||
}
|
||||
if (nodeMap[target] !== true) {
|
||||
var data = {
|
||||
id: target,
|
||||
x: Math.random(),
|
||||
y: Math.random(),
|
||||
size: 10,
|
||||
color: target_color
|
||||
}
|
||||
if (result["target_label"] != undefined) {
|
||||
data.label = result["target_label"]
|
||||
} else {
|
||||
data.label = target
|
||||
}
|
||||
g.nodes.push(data)
|
||||
nodeMap[target] = true
|
||||
}
|
||||
g.edges.push({
|
||||
id: "e" + i,
|
||||
source: source,
|
||||
target: target,
|
||||
size: 5,
|
||||
color: '#ccc'
|
||||
})
|
||||
|
||||
}
|
||||
sigmaGraph = new sigma({
|
||||
graph: g,
|
||||
container: 'visualize',
|
||||
settings: {
|
||||
defaultNodeColor: '#ec5148'
|
||||
}
|
||||
|
||||
});
|
||||
sigmaGraph.startForceAtlas2();
|
||||
sigmaGraph.forceatlas2.p.linLogMode = true;
|
||||
}
|
||||
|
||||
$("#run_button").click(function() {
|
||||
var data = editor.getValue()
|
||||
animate();
|
||||
$.post("/api/v1/query/" + selectedQueryLanguage, data)
|
||||
.done(function(return_data) {
|
||||
stopAndReset();
|
||||
if (typeof(Storage) !== "undefined") {
|
||||
localStorage.setItem("cayleySavedQueries" + selectedQueryLanguage, data)
|
||||
}
|
||||
links = $.parseJSON(return_data)
|
||||
createGraphVisualization(links.result)
|
||||
})
|
||||
.fail(function() {
|
||||
stopAndReset();
|
||||
});
|
||||
});
|
||||
})
|
||||
158
static/js/cayley_write.js
Normal file
158
static/js/cayley_write.js
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
// Copyright 2014 The Cayley Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
$(function() {
|
||||
|
||||
|
||||
var alertFail = function(text) {
|
||||
$("#alertBox").text(text)
|
||||
$("#alertBox").addClass("alert-danger").fadeIn(300).delay(2000).fadeOut(300).queue(function(){ $(this).removeClass("alert-danger")});
|
||||
}
|
||||
|
||||
var alertSucceed = function(text) {
|
||||
$("#alertBox").text(text)
|
||||
$("#alertBox").addClass("alert-success").fadeIn(300).delay(2000).fadeOut(300).queue(function(){ $(this).removeClass("alert-success")});
|
||||
}
|
||||
|
||||
var checkTriple = function(t) {
|
||||
if (t.subject == "") {
|
||||
alertFail("Need a subject")
|
||||
return false
|
||||
}
|
||||
if (t.predicate == "") {
|
||||
alertFail("Need a predicate")
|
||||
return false
|
||||
}
|
||||
if (t.object == "") {
|
||||
alertFail("Need an object")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
$("#sbWrite").addClass("active");
|
||||
|
||||
$("#add_triple").click(function() {
|
||||
var triple = {
|
||||
subject: $("#subject").val(),
|
||||
predicate: $("#predicate").val(),
|
||||
object: $("#object").val(),
|
||||
provenance: $("#provenance").val()
|
||||
}
|
||||
if (!checkTriple(triple)) {
|
||||
return
|
||||
}
|
||||
$.post("/api/v1/write", JSON.stringify([triple]))
|
||||
.done(function(return_data){
|
||||
alertSucceed("Wrote a triple!")
|
||||
})
|
||||
.fail(function(jqxhr) {
|
||||
var data = $.parseJSON(jqxhr.responseText)
|
||||
alertFail(data.error)
|
||||
})
|
||||
})
|
||||
|
||||
$("#delete_triple").click(function() {
|
||||
var triple = {
|
||||
subject: $("#rsubject").val(),
|
||||
predicate: $("#rpredicate").val(),
|
||||
object: $("#robject").val(),
|
||||
provenance: $("#rprovenance").val()
|
||||
}
|
||||
if (!checkTriple(triple)) {
|
||||
return
|
||||
}
|
||||
$.post("/api/v1/delete", JSON.stringify([triple]))
|
||||
.done(function(return_data){
|
||||
alertSucceed("Deleted a triple!")
|
||||
})
|
||||
.fail(function(jqxhr) {
|
||||
var data = $.parseJSON(jqxhr.responseText)
|
||||
alertFail(data.error)
|
||||
})
|
||||
})
|
||||
|
||||
var upload = null
|
||||
|
||||
var uploadProgress = function(event) {
|
||||
if (event.lengthComputable) {
|
||||
var percentComplete = Math.round(event.loaded * 100 / event.total);
|
||||
$("#alertBox").text("Uploaded " + percentComplete.toString() + "%")
|
||||
} else {
|
||||
$("#alertBox").text("Uploading...")
|
||||
}
|
||||
}
|
||||
|
||||
var uploadComplete = function(event) {
|
||||
stopAndReset();
|
||||
var data = $.parseJSON(upload.responseText)
|
||||
$("#alertBox").text("Upload complete! " + data.result);
|
||||
$("#alertBox").removeClass("alert-info").addClass("alert-success")
|
||||
.delay(2000).fadeOut(300)
|
||||
.queue(function () {
|
||||
$("#write_file").fadeIn(30);
|
||||
$("#alertBox").removeClass("alert-success");
|
||||
})
|
||||
upload = null
|
||||
}
|
||||
|
||||
var uploadCanceled = function(event) {
|
||||
upload = null
|
||||
stopAndReset();
|
||||
$("#alertBox").text("Upload canceled!")
|
||||
$("#alertBox").removeClass("alert-info").addClass("alert-danger")
|
||||
.delay(2000).fadeOut(300)
|
||||
.queue(function () {
|
||||
$("#write_file").fadeIn(30);
|
||||
$("#alertBox").removeClass("alert-danger");
|
||||
})
|
||||
}
|
||||
|
||||
var uploadFailed = function(event) {
|
||||
upload = null
|
||||
stopAndReset();
|
||||
$("#alertBox").text("Upload failed!")
|
||||
$("#alertBox").removeClass("alert-info").addClass("alert-danger")
|
||||
.delay(2000).fadeOut(300)
|
||||
.queue(function () {
|
||||
$("#write_file").fadeIn(30);
|
||||
$("#alertBox").removeClass("alert-danger");
|
||||
})
|
||||
}
|
||||
|
||||
$("#write_file").click(function() {
|
||||
try {
|
||||
animate();
|
||||
var fd = new FormData()
|
||||
fd.append("NQuadFile", document.getElementById("nquad_file").files[0])
|
||||
var xhr = new XMLHttpRequest()
|
||||
upload = xhr
|
||||
$("#write_file").fadeOut(30);
|
||||
$("#alertBox").addClass("alert-info").fadeIn(300);
|
||||
xhr.upload.addEventListener("progress", uploadProgress, false);
|
||||
xhr.addEventListener("load", uploadComplete, false);
|
||||
xhr.addEventListener("error", uploadFailed, false);
|
||||
xhr.addEventListener("abort", uploadCanceled, false);
|
||||
xhr.open("POST", "/api/v1/write/file/nquad");
|
||||
xhr.send(fd);
|
||||
|
||||
} catch(err) {
|
||||
$("#alertBox").removeClass("alert-info");
|
||||
stopAndReset();
|
||||
alertFail(err)
|
||||
$("#write_file").fadeIn(30);
|
||||
}
|
||||
})
|
||||
|
||||
});
|
||||
351
static/js/query_viz.js
Normal file
351
static/js/query_viz.js
Normal file
|
|
@ -0,0 +1,351 @@
|
|||
// Copyright 2014 The Cayley Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
function Network() {
|
||||
var height = 800;
|
||||
var width = 800;
|
||||
|
||||
// Things in the first force graph.
|
||||
var nodesG = null;
|
||||
var linksG = null;
|
||||
var linkNodesG = null;
|
||||
|
||||
var node = null;
|
||||
var linknode = null;
|
||||
var link = null;
|
||||
|
||||
var curLinksData = null;
|
||||
var curNodesData = null;
|
||||
|
||||
|
||||
// Things in the second force graph
|
||||
var tag_nodesG = null;
|
||||
var tag_linksG = null;
|
||||
|
||||
var tag_node = null;
|
||||
var tag_link = null;
|
||||
|
||||
var curTagLinksData = null;
|
||||
var curTagNodesData = null;
|
||||
|
||||
|
||||
var allData = null;
|
||||
|
||||
var dragstart = function(d) {
|
||||
d3.select(this).classed("fixed", d.fixed = true);
|
||||
}
|
||||
|
||||
//our force directed layout
|
||||
var force = d3.layout.force()
|
||||
var force_drag = force.drag().on("dragstart", dragstart)
|
||||
var tag_force = d3.layout.force()
|
||||
|
||||
//color function used to color nodes
|
||||
var baseNodeColors = d3.scale.category20()
|
||||
var linkNodeColors = function(d) {
|
||||
return d3.rgb("#555").toString()
|
||||
}
|
||||
var strokeFor = function(d) {
|
||||
return d3.rgb("#000").brighter().toString()
|
||||
}
|
||||
|
||||
var rotationTransformForLinkNode = function (d) {
|
||||
var center_x = (d.link.source.x + d.link.target.x) / 2
|
||||
var center_y = (d.link.source.y + d.link.target.y) / 2
|
||||
var dx = d.link.target.x - d.link.source.x
|
||||
var dy = d.link.target.y - d.link.source.y
|
||||
var rotation_radians = Math.atan2(dy,dx)
|
||||
var rotation_degrees = rotation_radians * (180 / Math.PI)
|
||||
return "rotate(" + rotation_degrees + ", " + center_x + ", " + center_y + ")"
|
||||
|
||||
}
|
||||
|
||||
var updateLink = function() {
|
||||
this.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})
|
||||
}
|
||||
|
||||
var forceTick = function(e) {
|
||||
tag_force.start()
|
||||
node
|
||||
.attr("cx", function(d) {return d.x})
|
||||
.attr("cy", function(d) {return d.y})
|
||||
|
||||
linknode.each(function(d) {
|
||||
d.x = (d.link.source.x + d.link.target.x) / 2
|
||||
d.y = (d.link.source.y + d.link.target.y) / 2
|
||||
})
|
||||
|
||||
linknode
|
||||
.attr("cx", function(d) {return d.x })
|
||||
.attr("cy", function(d) {return d.y })
|
||||
.attr("transform", rotationTransformForLinkNode)
|
||||
|
||||
link.call(updateLink);
|
||||
|
||||
tagForceTick(e)
|
||||
}
|
||||
|
||||
var tagForceTick = function(e) {
|
||||
tag_node.each(function(d) {
|
||||
if(d.is_tag === false) {
|
||||
d.x = d.node.x;
|
||||
d.y = d.node.y;
|
||||
} else {
|
||||
var b = this.childNodes[1].getBBox();
|
||||
var diffX = d.x - d.node.x;
|
||||
var diffY = d.y - d.node.y;
|
||||
|
||||
var dist = Math.sqrt(diffX * diffX + diffY * diffY);
|
||||
|
||||
var shiftX = b.width * (diffX - dist) / (dist * 2);
|
||||
shiftX = Math.max(-b.width, Math.min(0, shiftX));
|
||||
var shiftY = 5;
|
||||
this.childNodes[1].setAttribute("transform", "translate(" + shiftX + "," + shiftY + ")");
|
||||
}
|
||||
});
|
||||
tag_node
|
||||
.attr("transform", function(d) {
|
||||
return "translate(" + d.x + "," + d.y + ")";
|
||||
});
|
||||
|
||||
tag_link.call(updateLink);
|
||||
}
|
||||
|
||||
var setupData = function (data) {
|
||||
data.nodes.forEach(function (n) {
|
||||
n.x = randomnumber=Math.floor(Math.random()*width)
|
||||
n.y = randomnumber=Math.floor(Math.random()*height)
|
||||
n.radius = 10
|
||||
});
|
||||
|
||||
var nodesMap = mapNodes(data.nodes)
|
||||
|
||||
data.links.forEach(function (l) {
|
||||
l.source = nodesMap.get(l.source)
|
||||
l.target = nodesMap.get(l.target)
|
||||
nodesMap.get(l.link_node).link = l
|
||||
})
|
||||
|
||||
data.tag_links = []
|
||||
data.tag_nodes = []
|
||||
var tag_id_counter = 0
|
||||
|
||||
data.nodes.forEach(function (n) {
|
||||
if (n.tags !== undefined) {
|
||||
n.tags.forEach( function (tag) {
|
||||
var tag_node = {}
|
||||
tag_node.id = "tag" + tag_id_counter
|
||||
tag_node.tag = tag
|
||||
tag_node.x = n.x
|
||||
tag_node.y = n.y
|
||||
tag_node.is_tag = true
|
||||
tag_node.is_value = false
|
||||
tag_node.node = n
|
||||
tag_node.radius = 0
|
||||
tag_id_counter += 1;
|
||||
var fake_node = {}
|
||||
fake_node.id = "tag" + tag_id_counter
|
||||
fake_node.x = n.x
|
||||
fake_node.y = n.y
|
||||
fake_node.node = n
|
||||
fake_node.radius = 0
|
||||
fake_node.is_tag = false
|
||||
tag_id_counter += 1;
|
||||
var tag_link = {}
|
||||
tag_link.source = fake_node
|
||||
tag_link.target = tag_node
|
||||
data.tag_nodes.push(tag_node)
|
||||
data.tag_nodes.push(fake_node)
|
||||
data.tag_links.push(tag_link)
|
||||
})
|
||||
}
|
||||
if (n.values !== undefined) {
|
||||
n.values.forEach( function (value) {
|
||||
var tag_node = {}
|
||||
tag_node.id = "tag" + tag_id_counter
|
||||
tag_node.tag = value
|
||||
tag_node.x = n.x
|
||||
tag_node.y = n.y
|
||||
tag_node.is_tag = true
|
||||
tag_node.is_value = true
|
||||
tag_node.node = n
|
||||
tag_node.radius = 0
|
||||
tag_id_counter += 1;
|
||||
var fake_node = {}
|
||||
fake_node.id = "tag" + tag_id_counter
|
||||
fake_node.x = n.x
|
||||
fake_node.y = n.y
|
||||
fake_node.node = n
|
||||
fake_node.radius = 0
|
||||
fake_node.is_tag = false
|
||||
tag_id_counter += 1;
|
||||
var tag_link = {}
|
||||
tag_link.source = fake_node
|
||||
tag_link.target = tag_node
|
||||
data.tag_nodes.push(tag_node)
|
||||
data.tag_nodes.push(fake_node)
|
||||
data.tag_links.push(tag_link)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
var mapNodes = function (nodes) {
|
||||
var nodesMap = d3.map()
|
||||
nodes.forEach(function (n) {
|
||||
nodesMap.set(n.id, n)
|
||||
})
|
||||
return nodesMap
|
||||
}
|
||||
|
||||
var network = function (selection, data) {
|
||||
allData = setupData(data)
|
||||
var vis = d3.select(selection).append("svg")
|
||||
.attr("width", width)
|
||||
.attr("height", height)
|
||||
|
||||
vis.append("defs").append("marker")
|
||||
.attr("id", "arrowhead")
|
||||
.attr("refX", 6 + 3) // shift?
|
||||
.attr("refY", 2)
|
||||
.attr("markerWidth", 6)
|
||||
.attr("markerHeight", 4)
|
||||
.attr("orient", "auto")
|
||||
.append("path")
|
||||
.attr("d", "M 0,0 V 4 L6,2 Z");
|
||||
|
||||
linksG = vis.append("g").attr("id", "links")
|
||||
nodesG = vis.append("g").attr("id", "nodes")
|
||||
linkNodesG = vis.append("g").attr("id", "link-nodes")
|
||||
|
||||
tagNodesG = vis.append("g").attr("id", "tag_nodes")
|
||||
tagLinksG = vis.append("g").attr("id", "tag_links")
|
||||
|
||||
force.size([width, height])
|
||||
force.on("tick", forceTick)
|
||||
.charge(-200)
|
||||
.linkDistance(100);
|
||||
|
||||
tag_force
|
||||
.gravity(0)
|
||||
.linkDistance(25)
|
||||
.linkStrength(20)
|
||||
.charge(-100)
|
||||
.size([width, height])
|
||||
|
||||
tag_force.start()
|
||||
|
||||
//perform rendering and start force layout
|
||||
update()
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
var update = function () {
|
||||
allNodes = allData.nodes;
|
||||
curLinksData = allData.links;
|
||||
curNodesData = $.grep(allData.nodes, function(n) { return n.is_link_node === false; })
|
||||
curLinkNodesData = $.grep(allData.nodes, function(n) { return n.is_link_node; })
|
||||
|
||||
curTagLinksData = allData.tag_links
|
||||
curTagNodesData = allData.tag_nodes
|
||||
|
||||
force.nodes(allNodes);
|
||||
node = nodesG.selectAll("circle.node")
|
||||
.data(curNodesData, function(d) {return d.id})
|
||||
|
||||
node.enter().append("circle")
|
||||
.attr("class", "node")
|
||||
.attr("cx", function(d) {return d.x})
|
||||
.attr("cy", function(d) {return d.y})
|
||||
.attr("r", function(d) {return d.radius;})
|
||||
.style("fill", function(d) {return baseNodeColors(d.id);})
|
||||
.style("stroke", function(d) {return strokeFor(d);})
|
||||
.style("stroke-width", 1.0)
|
||||
.call(force_drag)
|
||||
|
||||
node.exit().remove();
|
||||
|
||||
linknode = linkNodesG.selectAll("ellipse.node")
|
||||
.data(curLinkNodesData, function(d) { return d.id })
|
||||
|
||||
linknode.enter().append("ellipse")
|
||||
.attr("class", "node")
|
||||
.attr("cx", function(d) {return d.x})
|
||||
.attr("cy", function(d) {return d.y})
|
||||
.attr("rx", function(d) {return d.radius;})
|
||||
.attr("ry", function(d) {return d.radius / 2;})
|
||||
.style("fill", function(d) {return linkNodeColors(d.id);})
|
||||
.style("stroke", function(d) {return strokeFor(d);})
|
||||
.style("stroke-width", 1.0);
|
||||
|
||||
linknode.exit().remove();
|
||||
|
||||
|
||||
force.links(curLinksData);
|
||||
|
||||
link = linksG.selectAll("line.link")
|
||||
.data(curLinksData, function(d) { return d.source.id + "_" + d.target.id});
|
||||
|
||||
link.enter().append("line")
|
||||
.attr("class", "link")
|
||||
.attr("stroke", "#222")
|
||||
.attr("stroke-opacity", 1.0)
|
||||
.attr("marker-end", "url(#arrowhead)")
|
||||
.style("stroke-width", 2.0)
|
||||
.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});
|
||||
|
||||
link.exit().remove();
|
||||
force.start();
|
||||
|
||||
tag_force.nodes(curTagNodesData);
|
||||
tag_node = nodesG.selectAll("g.tag_node")
|
||||
.data(curTagNodesData, function(d) { return d.id })
|
||||
var tag_g = tag_node.enter().append("g").attr("class", "tag_node")
|
||||
tag_g.append("svg:circle").attr("r", 0).style("fill", "#FFF");
|
||||
tag_g.append("svg:text")
|
||||
.text(function(d) { return d.is_tag ? d.tag : "" })
|
||||
.style("fill", "#555")
|
||||
.style("font-family", function(d) { return d.is_value ? "Courier" : "Arial"})
|
||||
.style("font-size", 12);
|
||||
|
||||
tag_force.links(curTagLinksData);
|
||||
tag_link = linksG.selectAll("line.tag_link")
|
||||
.data(curTagLinksData, function(d) { return d.source.id + "_" + d.target.id});
|
||||
|
||||
tag_link.enter().append("line")
|
||||
.attr("class", "tag_link")
|
||||
.attr("stroke", "#ddd")
|
||||
.attr("stroke-opacity", 0.5)
|
||||
.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});
|
||||
|
||||
tag_link.exit().remove();
|
||||
tag_force.start()
|
||||
}
|
||||
|
||||
return network
|
||||
};
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue