Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
W
WebPublic
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
前端开发小组
WebPublic
Commits
6b9d77f6
提交
6b9d77f6
authored
8月 06, 2020
作者:
tb53863844
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
知识图谱组件
上级
acab7121
显示空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
1715 行增加
和
5 行删除
+1715
-5
Neo4jD3Com.jsx
one_stop_public/libs/Neo4jD3Com.jsx
+731
-0
index.jsx
one_stop_public/tableCompon/index.jsx
+16
-5
Neo4jD3.js
one_stop_public/utils/Neo4jD3.js
+968
-0
没有找到文件。
one_stop_public/libs/Neo4jD3Com.jsx
0 → 100644
浏览文件 @
6b9d77f6
import
React
from
'react'
import
Neo4jD3
from
'@/webPublic/one_stop_public/utils/Neo4jD3'
import
UUID
from
'react-native-uuid'
;
export
default
class
Neo4jD3Com
extends
React
.
Component
{
uid
=
UUID
.
v4
()
triggerChange
=
(
changedValue
)
=>
{
// Should provide an event to pass value to Form.
const
onChange
=
this
.
props
.
onChange
;
if
(
onChange
)
{
onChange
(
changedValue
);
}
}
data
componentWillReceiveProps
(
nextProps
)
{
// Should be a controlled component.
if
(
'option'
in
nextProps
&&
nextProps
.
option
&&
nextProps
.
option
.
neo4jData
)
{
if
(
this
.
neo4jd3
==
null
){
this
.
data
=
nextProps
.
option
.
neo4jData
this
.
init
(
nextProps
.
option
.
neo4jData
)
}
else
{
if
(
JSON
.
stringify
(
this
.
data
)
!=
JSON
.
stringify
(
nextProps
.
option
.
neo4jData
)){
this
.
neo4jd3
.
updateWithD3Data
(
nextProps
.
option
.
neo4jData
)
this
.
data
=
nextProps
.
option
.
neo4jData
}
}
}
}
changePos
=
(
obj
)
=>
{
if
(
!
(
'value'
in
this
.
props
))
{
this
.
setState
({...
obj
});
}
this
.
triggerChange
({...
obj
});
}
neo4jd3
init
=
(
neo4jData
)
=>
{
/* const x = [
{
"p": {
"start": {
"identity": 548,
"labels": [
"Actor"
],
"properties": {
"name": "Carrie-Anne Moss",
"personId": "carrieanne"
}
},
"end": {
"identity": 0,
"labels": [
"Movie"
],
"properties": {
"movieId": "tt0133093",
"title": "The Matrix",
"year": 1999
}
},
"segments": [
{
"start": {
"identity": 548,
"labels": [
"Actor"
],
"properties": {
"name": "Carrie-Anne Moss",
"personId": "carrieanne"
}
},
"relationship": {
"identity": 6,
"start": 548,
"end": 0,
"type": "ACTED_IN",
"properties": {
"role": "Trinity"
}
},
"end": {
"identity": 0,
"labels": [
"Movie"
],
"properties": {
"movieId": "tt0133093",
"title": "The Matrix",
"year": 1999
}
}
}
],
"length": 1.0
}
},
{
"p": {
"start": {
"identity": 547,
"labels": [
"Actor"
],
"properties": {
"name": "Laurence Fishburne",
"personId": "laurence"
}
},
"end": {
"identity": 0,
"labels": [
"Movie"
],
"properties": {
"movieId": "tt0133093",
"title": "The Matrix",
"year": 1999
}
},
"segments": [
{
"start": {
"identity": 547,
"labels": [
"Actor"
],
"properties": {
"name": "Laurence Fishburne",
"personId": "laurence"
}
},
"relationship": {
"identity": 3,
"start": 547,
"end": 0,
"type": "ACTED_IN",
"properties": {
"role": "Morpheus"
}
},
"end": {
"identity": 0,
"labels": [
"Movie"
],
"properties": {
"movieId": "tt0133093",
"title": "The Matrix",
"year": 1999
}
}
}
],
"length": 1.0
}
},
{
"p": {
"start": {
"identity": 546,
"labels": [
"Actor"
],
"properties": {
"name": "Keanu Reeves",
"personId": "keanu"
}
},
"end": {
"identity": 0,
"labels": [
"Movie"
],
"properties": {
"movieId": "tt0133093",
"title": "The Matrix",
"year": 1999
}
},
"segments": [
{
"start": {
"identity": 546,
"labels": [
"Actor"
],
"properties": {
"name": "Keanu Reeves",
"personId": "keanu"
}
},
"relationship": {
"identity": 0,
"start": 546,
"end": 0,
"type": "ACTED_IN",
"properties": {
"role": "Neo"
}
},
"end": {
"identity": 0,
"labels": [
"Movie"
],
"properties": {
"movieId": "tt0133093",
"title": "The Matrix",
"year": 1999
}
}
}
],
"length": 1.0
}
},
{
"p": {
"start": {
"identity": 548,
"labels": [
"Actor"
],
"properties": {
"name": "Carrie-Anne Moss",
"personId": "carrieanne"
}
},
"end": {
"identity": 1,
"labels": [
"Movie",
"Sequel"
],
"properties": {
"movieId": "tt0234215",
"title": "The Matrix Reloaded",
"year": 2003
}
},
"segments": [
{
"start": {
"identity": 548,
"labels": [
"Actor"
],
"properties": {
"name": "Carrie-Anne Moss",
"personId": "carrieanne"
}
},
"relationship": {
"identity": 7,
"start": 548,
"end": 1,
"type": "ACTED_IN",
"properties": {
"role": "Trinity"
}
},
"end": {
"identity": 1,
"labels": [
"Movie",
"Sequel"
],
"properties": {
"movieId": "tt0234215",
"title": "The Matrix Reloaded",
"year": 2003
}
}
}
],
"length": 1.0
}
},
{
"p": {
"start": {
"identity": 547,
"labels": [
"Actor"
],
"properties": {
"name": "Laurence Fishburne",
"personId": "laurence"
}
},
"end": {
"identity": 1,
"labels": [
"Movie",
"Sequel"
],
"properties": {
"movieId": "tt0234215",
"title": "The Matrix Reloaded",
"year": 2003
}
},
"segments": [
{
"start": {
"identity": 547,
"labels": [
"Actor"
],
"properties": {
"name": "Laurence Fishburne",
"personId": "laurence"
}
},
"relationship": {
"identity": 4,
"start": 547,
"end": 1,
"type": "ACTED_IN",
"properties": {
"role": "Morpheus"
}
},
"end": {
"identity": 1,
"labels": [
"Movie",
"Sequel"
],
"properties": {
"movieId": "tt0234215",
"title": "The Matrix Reloaded",
"year": 2003
}
}
}
],
"length": 1.0
}
},
{
"p": {
"start": {
"identity": 546,
"labels": [
"Actor"
],
"properties": {
"name": "Keanu Reeves",
"personId": "keanu"
}
},
"end": {
"identity": 1,
"labels": [
"Movie",
"Sequel"
],
"properties": {
"movieId": "tt0234215",
"title": "The Matrix Reloaded",
"year": 2003
}
},
"segments": [
{
"start": {
"identity": 546,
"labels": [
"Actor"
],
"properties": {
"name": "Keanu Reeves",
"personId": "keanu"
}
},
"relationship": {
"identity": 1,
"start": 546,
"end": 1,
"type": "ACTED_IN",
"properties": {
"role": "Neo"
}
},
"end": {
"identity": 1,
"labels": [
"Movie",
"Sequel"
],
"properties": {
"movieId": "tt0234215",
"title": "The Matrix Reloaded",
"year": 2003
}
}
}
],
"length": 1.0
}
},
{
"p": {
"start": {
"identity": 548,
"labels": [
"Actor"
],
"properties": {
"name": "Carrie-Anne Moss",
"personId": "carrieanne"
}
},
"end": {
"identity": 2,
"labels": [
"Movie",
"Sequel"
],
"properties": {
"movieId": "tt0242653",
"title": "The Matrix Revolutions",
"year": 2003
}
},
"segments": [
{
"start": {
"identity": 548,
"labels": [
"Actor"
],
"properties": {
"name": "Carrie-Anne Moss",
"personId": "carrieanne"
}
},
"relationship": {
"identity": 8,
"start": 548,
"end": 2,
"type": "ACTED_IN",
"properties": {
"role": "Trinity"
}
},
"end": {
"identity": 2,
"labels": [
"Movie",
"Sequel"
],
"properties": {
"movieId": "tt0242653",
"title": "The Matrix Revolutions",
"year": 2003
}
}
}
],
"length": 1.0
}
},
{
"p": {
"start": {
"identity": 547,
"labels": [
"Actor"
],
"properties": {
"name": "Laurence Fishburne",
"personId": "laurence"
}
},
"end": {
"identity": 2,
"labels": [
"Movie",
"Sequel"
],
"properties": {
"movieId": "tt0242653",
"title": "The Matrix Revolutions",
"year": 2003
}
},
"segments": [
{
"start": {
"identity": 547,
"labels": [
"Actor"
],
"properties": {
"name": "Laurence Fishburne",
"personId": "laurence"
}
},
"relationship": {
"identity": 5,
"start": 547,
"end": 2,
"type": "ACTED_IN",
"properties": {
"role": "Morpheus"
}
},
"end": {
"identity": 2,
"labels": [
"Movie",
"Sequel"
],
"properties": {
"movieId": "tt0242653",
"title": "The Matrix Revolutions",
"year": 2003
}
}
}
],
"length": 1.0
}
},
{
"p": {
"start": {
"identity": 546,
"labels": [
"Actor"
],
"properties": {
"name": "Keanu Reeves",
"personId": "keanu"
}
},
"end": {
"identity": 2,
"labels": [
"Movie",
"Sequel"
],
"properties": {
"movieId": "tt0242653",
"title": "The Matrix Revolutions",
"year": 2003
}
},
"segments": [
{
"start": {
"identity": 546,
"labels": [
"Actor"
],
"properties": {
"name": "Keanu Reeves",
"personId": "keanu"
}
},
"relationship": {
"identity": 2,
"start": 546,
"end": 2,
"type": "ACTED_IN",
"properties": {
"role": "Neo"
}
},
"end": {
"identity": 2,
"labels": [
"Movie",
"Sequel"
],
"properties": {
"movieId": "tt0242653",
"title": "The Matrix Revolutions",
"year": 2003
}
}
}
],
"length": 1.0
}
}
]
var graph = eval(x);
console.log(JSON.stringify(graph))
let nodes =[];
let links = []; // 存放节点和关系
let nodeSet = []; // 存放去重后nodes的id
for (let item of graph) {
// console.log(item.p.start instanceof Array)
// console.log(item.p)
// 重新更改data格式
if(nodeSet.indexOf(item.p.start.identity) == -1){
nodeSet.push(item.p.start.identity)
nodes.push({
id: item.p.start.identity,
labels: item.p.start.labels,
properties: item.p.start.properties
})
}
if(nodeSet.indexOf(item.p.end.identity) == -1){
nodeSet.push(item.p.end.identity)
nodes.push({
id: item.p.end.identity,
labels: item.p.end.labels,
properties: item.p.end.properties
})
}
links.push({
source: item.p.segments[0].relationship.start,
target: item.p.segments[0].relationship.end,
type: item.p.segments[0].relationship.type,
properties: item.p.segments[0].relationship.properties
})
}
console.log(nodes)
console.log(links) */
this
.
neo4jd3
=
new
Neo4jD3
(
'#id_'
+
this
.
uid
,
{
highlight
:
[
{
class
:
'Project'
,
property
:
'name'
,
value
:
'neo4jd3'
},
{
class
:
'User'
,
property
:
'userId'
,
value
:
'eisman'
}
],
icons
:
{
// 'Address': 'home',
'Api'
:
'gear'
,
// 'BirthDate': 'birthday-cake',
'Cookie'
:
'paw'
,
// 'CreditCard': 'credit-card',
// 'Device': 'laptop',
'Email'
:
'at'
,
'Git'
:
'git'
,
'Github'
:
'github'
,
'Google'
:
'google'
,
// 'icons': 'font-awesome',
'Ip'
:
'map-marker'
,
'Issues'
:
'exclamation-circle'
,
'Language'
:
'language'
,
'Options'
:
'sliders'
,
'Password'
:
'lock'
,
'Phone'
:
'phone'
,
'Project'
:
'folder-open'
,
'SecurityChallengeAnswer'
:
'commenting'
,
'User'
:
'user'
,
'zoomFit'
:
'arrows-alt'
,
'zoomIn'
:
'search-plus'
,
'zoomOut'
:
'search-minus'
},
images
:
{
'Address'
:
'img/twemoji/1f3e0.svg'
,
// 'Api': 'img/twemoji/1f527.svg',
'BirthDate'
:
'img/twemoji/1f382.svg'
,
'Cookie'
:
'img/twemoji/1f36a.svg'
,
'CreditCard'
:
'img/twemoji/1f4b3.svg'
,
'Device'
:
'img/twemoji/1f4bb.svg'
,
'Email'
:
'img/twemoji/2709.svg'
,
'Git'
:
'img/twemoji/1f5c3.svg'
,
'Github'
:
'img/twemoji/1f5c4.svg'
,
'icons'
:
'img/twemoji/1f38f.svg'
,
'Ip'
:
'img/twemoji/1f4cd.svg'
,
'Issues'
:
'img/twemoji/1f4a9.svg'
,
'Language'
:
'img/twemoji/1f1f1-1f1f7.svg'
,
'Options'
:
'img/twemoji/2699.svg'
,
'Password'
:
'img/twemoji/1f511.svg'
,
// 'Phone': 'img/twemoji/1f4de.svg',
'Project'
:
'img/twemoji/2198.svg'
,
'Project|name|neo4jd3'
:
'img/twemoji/2196.svg'
,
// 'SecurityChallengeAnswer': 'img/twemoji/1f4ac.svg',
'User'
:
'img/twemoji/1f600.svg'
// 'zoomFit': 'img/twemoji/2194.svg',
// 'zoomIn': 'img/twemoji/1f50d.svg',
// 'zoomOut': 'img/twemoji/1f50e.svg'
},
minCollision
:
60
,
neo4jData
:
neo4jData
,
nodeRadius
:
25
,
onNodeDoubleClick
:
function
(
node
)
{
switch
(
node
.
id
)
{
case
'25'
:
// Google
window
.
open
(
node
.
properties
.
url
,
'_blank'
);
break
;
default
:
var
maxNodes
=
5
,
data
=
neo4jd3
.
randomD3Data
(
node
,
maxNodes
);
neo4jd3
.
updateWithD3Data
(
data
);
break
;
}
},
onRelationshipDoubleClick
:
function
(
relationship
)
{
console
.
log
(
'double click on relationship: '
+
JSON
.
stringify
(
relationship
));
},
zoomFit
:
true
});
}
render
()
{
return
(
<
div
id=
{
"id_"
+
this
.
uid
}
style=
{
{
height
:
500
}
}
></
div
>
);
}
}
\ No newline at end of file
one_stop_public/tableCompon/index.jsx
浏览文件 @
6b9d77f6
...
...
@@ -52,6 +52,7 @@ import TableSelect from '../libs/TableSelect';
import
LocationCom
from
'../libs/LocationCom'
;
import
MobileDate
from
'../libs/MobileDate'
;
import
ChildForm
from
'../libs/ChildForm'
;
import
Neo4jD3Com
from
'../libs/Neo4jD3Com'
;
import
ImgUploadCom
from
'../libs/ImgUploadCom'
;
import
moment
from
'moment'
;
import
router
from
'umi/router'
;
...
...
@@ -814,7 +815,7 @@ export default class tableCom extends Component {
);
//message.error(`页面${this.props.formKey}第${this.props.i + 1}行,第${this.props.j + 1}列:公式配置有误,回调函数内部错误${e}`, 10)
}
}
else
if
(
json
.
comName
==
'Echart'
||
json
.
comName
==
'QRCode'
)
{
}
else
if
(
json
.
comName
==
'Echart'
||
json
.
comName
==
'QRCode'
||
json
.
comName
==
'Graph'
)
{
try
{
const
x
=
callback
(
data
);
if
(
x
!=
null
)
{
...
...
@@ -888,7 +889,7 @@ export default class tableCom extends Component {
e
,
);
}
}
else
if
(
json
.
comName
==
'Echart'
||
json
.
comName
==
'QRCode'
)
{
}
else
if
(
json
.
comName
==
'Echart'
||
json
.
comName
==
'QRCode'
||
json
.
comName
==
'Graph'
)
{
try
{
const
x
=
callback
(
data
);
if
(
x
!=
null
)
{
...
...
@@ -964,7 +965,7 @@ export default class tableCom extends Component {
e
,
);
}
}
else
if
(
json
.
comName
==
'Echart'
||
json
.
comName
==
'QRCode'
)
{
}
else
if
(
json
.
comName
==
'Echart'
||
json
.
comName
==
'QRCode'
||
json
.
comName
==
'Graph'
)
{
try
{
const
x
=
callback
(
data
);
if
(
x
!=
null
)
{
...
...
@@ -1044,7 +1045,7 @@ export default class tableCom extends Component {
e
,
);
}
}
else
if
(
json
.
comName
==
'Echart'
||
json
.
comName
==
'QRCode'
)
{
}
else
if
(
json
.
comName
==
'Echart'
||
json
.
comName
==
'QRCode'
||
json
.
comName
==
"Graph"
)
{
try
{
const
x
=
callback
(
data
);
if
(
x
!=
null
)
{
...
...
@@ -1177,7 +1178,7 @@ export default class tableCom extends Component {
if
(
callback
)
callback
();
});
}
}
else
if
(
json
.
comName
==
'Echart'
||
json
.
comName
==
'QRCode'
)
{
}
else
if
(
json
.
comName
==
'Echart'
||
json
.
comName
==
'QRCode'
||
json
.
comName
==
'Graph'
)
{
this
.
setState
({
option
:
value
});
}
else
{
try
{
...
...
@@ -1464,6 +1465,16 @@ export default class tableCom extends Component {
/>
);
}
if
(
json
.
comName
==
'Graph'
)
{
return
(
<
Neo4jD3Com
style=
{
{
height
:
json
.
height
||
500
}
}
key=
{
this
.
props
.
uuid
}
option=
{
this
.
state
.
option
||
[]
}
/>
);
}
if
(
json
.
comName
==
'PartForm'
)
{
const
fk
=
this
.
props
.
form
.
getFieldValue
(
this
.
props
.
uuid
)
||
json
.
childFormKey
;
if
(
fk
==
null
)
{
...
...
one_stop_public/utils/Neo4jD3.js
0 → 100644
浏览文件 @
6b9d77f6
'use strict'
;
import
*
as
d3
from
'd3'
;
function
Neo4jD3
(
_selector
,
_options
)
{
var
container
,
graph
,
info
,
node
,
nodes
,
relationship
,
relationshipOutline
,
relationshipOverlay
,
relationshipText
,
relationships
,
selector
,
simulation
,
svg
,
svgNodes
,
svgRelationships
,
svgScale
,
svgTranslate
,
classes2colors
=
{},
justLoaded
=
false
,
numClasses
=
0
,
options
=
{
arrowSize
:
4
,
colors
:
colors
(),
highlight
:
undefined
,
iconMap
:
fontAwesomeIcons
(),
icons
:
undefined
,
imageMap
:
{},
images
:
undefined
,
infoPanel
:
true
,
minCollision
:
undefined
,
neo4jData
:
undefined
,
neo4jDataUrl
:
undefined
,
nodeOutlineFillColor
:
undefined
,
nodeRadius
:
25
,
relationshipColor
:
'#a5abb6'
,
zoomFit
:
false
},
VERSION
=
'0.0.1'
;
function
appendGraph
(
container
)
{
svg
=
container
.
append
(
'svg'
)
.
attr
(
'width'
,
'100%'
)
.
attr
(
'height'
,
'100%'
)
.
attr
(
'class'
,
'neo4jd3-graph'
)
.
call
(
d3
.
zoom
().
on
(
'zoom'
,
function
()
{
var
scale
=
d3
.
event
.
transform
.
k
,
translate
=
[
d3
.
event
.
transform
.
x
,
d3
.
event
.
transform
.
y
];
if
(
svgTranslate
)
{
translate
[
0
]
+=
svgTranslate
[
0
];
translate
[
1
]
+=
svgTranslate
[
1
];
}
if
(
svgScale
)
{
scale
*=
svgScale
;
}
svg
.
attr
(
'transform'
,
'translate('
+
translate
[
0
]
+
', '
+
translate
[
1
]
+
') scale('
+
scale
+
')'
);
}))
.
on
(
'dblclick.zoom'
,
null
)
.
append
(
'g'
)
.
attr
(
'width'
,
'100%'
)
.
attr
(
'height'
,
'100%'
);
svgRelationships
=
svg
.
append
(
'g'
)
.
attr
(
'class'
,
'relationships'
);
svgNodes
=
svg
.
append
(
'g'
)
.
attr
(
'class'
,
'nodes'
);
}
function
appendImageToNode
(
node
)
{
return
node
.
append
(
'image'
)
.
attr
(
'height'
,
function
(
d
)
{
return
icon
(
d
)
?
'24px'
:
'30px'
;
})
.
attr
(
'x'
,
function
(
d
)
{
return
icon
(
d
)
?
'5px'
:
'-15px'
;
})
.
attr
(
'xlink:href'
,
function
(
d
)
{
return
image
(
d
);
})
.
attr
(
'y'
,
function
(
d
)
{
return
icon
(
d
)
?
'5px'
:
'-16px'
;
})
.
attr
(
'width'
,
function
(
d
)
{
return
icon
(
d
)
?
'24px'
:
'30px'
;
});
}
function
appendInfoPanel
(
container
)
{
return
container
.
append
(
'div'
)
.
attr
(
'class'
,
'neo4jd3-info'
);
}
function
appendInfoElement
(
cls
,
isNode
,
property
,
value
)
{
var
elem
=
info
.
append
(
'a'
);
elem
.
attr
(
'href'
,
'#'
)
.
attr
(
'class'
,
cls
)
.
html
(
'<strong>'
+
property
+
'</strong>'
+
(
value
?
(
': '
+
value
)
:
''
));
if
(
!
value
)
{
elem
.
style
(
'background-color'
,
function
(
d
)
{
return
options
.
nodeOutlineFillColor
?
options
.
nodeOutlineFillColor
:
(
isNode
?
class2color
(
property
)
:
defaultColor
());
})
.
style
(
'border-color'
,
function
(
d
)
{
return
options
.
nodeOutlineFillColor
?
class2darkenColor
(
options
.
nodeOutlineFillColor
)
:
(
isNode
?
class2darkenColor
(
property
)
:
defaultDarkenColor
());
})
.
style
(
'color'
,
function
(
d
)
{
return
options
.
nodeOutlineFillColor
?
class2darkenColor
(
options
.
nodeOutlineFillColor
)
:
'#fff'
;
});
}
}
function
appendInfoElementClass
(
cls
,
node
)
{
appendInfoElement
(
cls
,
true
,
node
);
}
function
appendInfoElementProperty
(
cls
,
property
,
value
)
{
appendInfoElement
(
cls
,
false
,
property
,
value
);
}
function
appendInfoElementRelationship
(
cls
,
relationship
)
{
appendInfoElement
(
cls
,
false
,
relationship
);
}
function
appendNode
()
{
return
node
.
enter
()
.
append
(
'g'
)
.
attr
(
'class'
,
function
(
d
)
{
var
highlight
,
i
,
classes
=
'node'
,
label
=
d
.
labels
[
0
];
if
(
icon
(
d
))
{
classes
+=
' node-icon'
;
}
if
(
image
(
d
))
{
classes
+=
' node-image'
;
}
if
(
options
.
highlight
)
{
for
(
i
=
0
;
i
<
options
.
highlight
.
length
;
i
++
)
{
highlight
=
options
.
highlight
[
i
];
if
(
d
.
labels
[
0
]
===
highlight
.
class
&&
d
.
properties
[
highlight
.
property
]
===
highlight
.
value
)
{
classes
+=
' node-highlighted'
;
break
;
}
}
}
return
classes
;
})
.
on
(
'click'
,
function
(
d
)
{
d
.
fx
=
d
.
fy
=
null
;
if
(
typeof
options
.
onNodeClick
===
'function'
)
{
options
.
onNodeClick
(
d
);
}
})
.
on
(
'dblclick'
,
function
(
d
)
{
stickNode
(
d
);
if
(
typeof
options
.
onNodeDoubleClick
===
'function'
)
{
options
.
onNodeDoubleClick
(
d
);
}
})
.
on
(
'mouseenter'
,
function
(
d
)
{
if
(
info
)
{
updateInfo
(
d
);
}
if
(
typeof
options
.
onNodeMouseEnter
===
'function'
)
{
options
.
onNodeMouseEnter
(
d
);
}
})
.
on
(
'mouseleave'
,
function
(
d
)
{
if
(
info
)
{
clearInfo
(
d
);
}
if
(
typeof
options
.
onNodeMouseLeave
===
'function'
)
{
options
.
onNodeMouseLeave
(
d
);
}
})
.
call
(
d3
.
drag
()
.
on
(
'start'
,
dragStarted
)
.
on
(
'drag'
,
dragged
)
.
on
(
'end'
,
dragEnded
));
}
function
appendNodeToGraph
()
{
var
n
=
appendNode
();
appendRingToNode
(
n
);
appendOutlineToNode
(
n
);
if
(
options
.
icons
)
{
appendTextToNode
(
n
);
}
if
(
options
.
images
)
{
appendImageToNode
(
n
);
}
return
n
;
}
function
appendOutlineToNode
(
node
)
{
return
node
.
append
(
'circle'
)
.
attr
(
'class'
,
'outline'
)
.
attr
(
'r'
,
options
.
nodeRadius
)
.
style
(
'fill'
,
function
(
d
)
{
return
options
.
nodeOutlineFillColor
?
options
.
nodeOutlineFillColor
:
class2color
(
d
.
labels
[
0
]);
})
.
style
(
'stroke'
,
function
(
d
)
{
return
options
.
nodeOutlineFillColor
?
class2darkenColor
(
options
.
nodeOutlineFillColor
)
:
class2darkenColor
(
d
.
labels
[
0
]);
})
.
append
(
'title'
).
text
(
function
(
d
)
{
return
toString
(
d
);
});
}
function
appendRingToNode
(
node
)
{
return
node
.
append
(
'circle'
)
.
attr
(
'class'
,
'ring'
)
.
attr
(
'r'
,
options
.
nodeRadius
*
1.16
)
.
append
(
'title'
).
text
(
function
(
d
)
{
return
toString
(
d
);
});
}
function
appendTextToNode
(
node
)
{
return
node
.
append
(
'text'
)
.
attr
(
'class'
,
function
(
d
)
{
return
'text'
+
(
icon
(
d
)
?
' icon'
:
''
);
})
.
attr
(
'fill'
,
'#ffffff'
)
.
attr
(
'font-size'
,
function
(
d
)
{
return
icon
(
d
)
?
(
options
.
nodeRadius
+
'px'
)
:
'10px'
;
})
.
attr
(
'pointer-events'
,
'none'
)
.
attr
(
'text-anchor'
,
'middle'
)
.
attr
(
'y'
,
function
(
d
)
{
return
icon
(
d
)
?
(
parseInt
(
Math
.
round
(
options
.
nodeRadius
*
0.32
))
+
'px'
)
:
'4px'
;
})
.
html
(
function
(
d
)
{
var
_icon
=
icon
(
d
);
return
_icon
?
'&#x'
+
_icon
:
d
.
id
;
});
}
function
appendRandomDataToNode
(
d
,
maxNodesToGenerate
)
{
var
data
=
randomD3Data
(
d
,
maxNodesToGenerate
);
updateWithNeo4jData
(
data
);
}
function
appendRelationship
()
{
return
relationship
.
enter
()
.
append
(
'g'
)
.
attr
(
'class'
,
'relationship'
)
.
on
(
'dblclick'
,
function
(
d
)
{
if
(
typeof
options
.
onRelationshipDoubleClick
===
'function'
)
{
options
.
onRelationshipDoubleClick
(
d
);
}
})
.
on
(
'mouseenter'
,
function
(
d
)
{
if
(
info
)
{
updateInfo
(
d
);
}
});
}
function
appendOutlineToRelationship
(
r
)
{
return
r
.
append
(
'path'
)
.
attr
(
'class'
,
'outline'
)
.
attr
(
'fill'
,
'#a5abb6'
)
.
attr
(
'stroke'
,
'none'
);
}
function
appendOverlayToRelationship
(
r
)
{
return
r
.
append
(
'path'
)
.
attr
(
'class'
,
'overlay'
);
}
function
appendTextToRelationship
(
r
)
{
return
r
.
append
(
'text'
)
.
attr
(
'class'
,
'text'
)
.
attr
(
'fill'
,
'#000000'
)
.
attr
(
'font-size'
,
'8px'
)
.
attr
(
'pointer-events'
,
'none'
)
.
attr
(
'text-anchor'
,
'middle'
)
.
text
(
function
(
d
)
{
return
d
.
type
;
});
}
function
appendRelationshipToGraph
()
{
var
relationship
=
appendRelationship
(),
text
=
appendTextToRelationship
(
relationship
),
outline
=
appendOutlineToRelationship
(
relationship
),
overlay
=
appendOverlayToRelationship
(
relationship
);
return
{
outline
:
outline
,
overlay
:
overlay
,
relationship
:
relationship
,
text
:
text
};
}
function
class2color
(
cls
)
{
var
color
=
classes2colors
[
cls
];
if
(
!
color
)
{
// color = options.colors[Math.min(numClasses, options.colors.length - 1)];
color
=
options
.
colors
[
numClasses
%
options
.
colors
.
length
];
classes2colors
[
cls
]
=
color
;
numClasses
++
;
}
return
color
;
}
function
class2darkenColor
(
cls
)
{
return
d3
.
rgb
(
class2color
(
cls
)).
darker
(
1
);
}
function
clearInfo
()
{
info
.
html
(
''
);
}
function
color
()
{
return
options
.
colors
[
options
.
colors
.
length
*
Math
.
random
()
<<
0
];
}
function
colors
()
{
// d3.schemeCategory10,
// d3.schemeCategory20,
return
[
'#68bdf6'
,
// light blue
'#6dce9e'
,
// green #1
'#faafc2'
,
// light pink
'#f2baf6'
,
// purple
'#ff928c'
,
// light red
'#fcea7e'
,
// light yellow
'#ffc766'
,
// light orange
'#405f9e'
,
// navy blue
'#a5abb6'
,
// dark gray
'#78cecb'
,
// green #2,
'#b88cbb'
,
// dark purple
'#ced2d9'
,
// light gray
'#e84646'
,
// dark red
'#fa5f86'
,
// dark pink
'#ffab1a'
,
// dark orange
'#fcda19'
,
// dark yellow
'#797b80'
,
// black
'#c9d96f'
,
// pistacchio
'#47991f'
,
// green #3
'#70edee'
,
// turquoise
'#ff75ea'
// pink
];
}
function
contains
(
array
,
id
)
{
var
filter
=
array
.
filter
(
function
(
elem
)
{
return
elem
.
id
===
id
;
});
return
filter
.
length
>
0
;
}
function
defaultColor
()
{
return
options
.
relationshipColor
;
}
function
defaultDarkenColor
()
{
return
d3
.
rgb
(
options
.
colors
[
options
.
colors
.
length
-
1
]).
darker
(
1
);
}
function
dragEnded
(
d
)
{
if
(
!
d3
.
event
.
active
)
{
simulation
.
alphaTarget
(
0
);
}
if
(
typeof
options
.
onNodeDragEnd
===
'function'
)
{
options
.
onNodeDragEnd
(
d
);
}
}
function
dragged
(
d
)
{
stickNode
(
d
);
}
function
dragStarted
(
d
)
{
if
(
!
d3
.
event
.
active
)
{
simulation
.
alphaTarget
(
0.3
).
restart
();
}
d
.
fx
=
d
.
x
;
d
.
fy
=
d
.
y
;
if
(
typeof
options
.
onNodeDragStart
===
'function'
)
{
options
.
onNodeDragStart
(
d
);
}
}
function
extend
(
obj1
,
obj2
)
{
var
obj
=
{};
merge
(
obj
,
obj1
);
merge
(
obj
,
obj2
);
return
obj
;
}
function
fontAwesomeIcons
()
{
return
{
'glass'
:
'f000'
,
'music'
:
'f001'
,
'search'
:
'f002'
,
'envelope-o'
:
'f003'
,
'heart'
:
'f004'
,
'star'
:
'f005'
,
'star-o'
:
'f006'
,
'user'
:
'f007'
,
'film'
:
'f008'
,
'th-large'
:
'f009'
,
'th'
:
'f00a'
,
'th-list'
:
'f00b'
,
'check'
:
'f00c'
,
'remove,close,times'
:
'f00d'
,
'search-plus'
:
'f00e'
,
'search-minus'
:
'f010'
,
'power-off'
:
'f011'
,
'signal'
:
'f012'
,
'gear,cog'
:
'f013'
,
'trash-o'
:
'f014'
,
'home'
:
'f015'
,
'file-o'
:
'f016'
,
'clock-o'
:
'f017'
,
'road'
:
'f018'
,
'download'
:
'f019'
,
'arrow-circle-o-down'
:
'f01a'
,
'arrow-circle-o-up'
:
'f01b'
,
'inbox'
:
'f01c'
,
'play-circle-o'
:
'f01d'
,
'rotate-right,repeat'
:
'f01e'
,
'refresh'
:
'f021'
,
'list-alt'
:
'f022'
,
'lock'
:
'f023'
,
'flag'
:
'f024'
,
'headphones'
:
'f025'
,
'volume-off'
:
'f026'
,
'volume-down'
:
'f027'
,
'volume-up'
:
'f028'
,
'qrcode'
:
'f029'
,
'barcode'
:
'f02a'
,
'tag'
:
'f02b'
,
'tags'
:
'f02c'
,
'book'
:
'f02d'
,
'bookmark'
:
'f02e'
,
'print'
:
'f02f'
,
'camera'
:
'f030'
,
'font'
:
'f031'
,
'bold'
:
'f032'
,
'italic'
:
'f033'
,
'text-height'
:
'f034'
,
'text-width'
:
'f035'
,
'align-left'
:
'f036'
,
'align-center'
:
'f037'
,
'align-right'
:
'f038'
,
'align-justify'
:
'f039'
,
'list'
:
'f03a'
,
'dedent,outdent'
:
'f03b'
,
'indent'
:
'f03c'
,
'video-camera'
:
'f03d'
,
'photo,image,picture-o'
:
'f03e'
,
'pencil'
:
'f040'
,
'map-marker'
:
'f041'
,
'adjust'
:
'f042'
,
'tint'
:
'f043'
,
'edit,pencil-square-o'
:
'f044'
,
'share-square-o'
:
'f045'
,
'check-square-o'
:
'f046'
,
'arrows'
:
'f047'
,
'step-backward'
:
'f048'
,
'fast-backward'
:
'f049'
,
'backward'
:
'f04a'
,
'play'
:
'f04b'
,
'pause'
:
'f04c'
,
'stop'
:
'f04d'
,
'forward'
:
'f04e'
,
'fast-forward'
:
'f050'
,
'step-forward'
:
'f051'
,
'eject'
:
'f052'
,
'chevron-left'
:
'f053'
,
'chevron-right'
:
'f054'
,
'plus-circle'
:
'f055'
,
'minus-circle'
:
'f056'
,
'times-circle'
:
'f057'
,
'check-circle'
:
'f058'
,
'question-circle'
:
'f059'
,
'info-circle'
:
'f05a'
,
'crosshairs'
:
'f05b'
,
'times-circle-o'
:
'f05c'
,
'check-circle-o'
:
'f05d'
,
'ban'
:
'f05e'
,
'arrow-left'
:
'f060'
,
'arrow-right'
:
'f061'
,
'arrow-up'
:
'f062'
,
'arrow-down'
:
'f063'
,
'mail-forward,share'
:
'f064'
,
'expand'
:
'f065'
,
'compress'
:
'f066'
,
'plus'
:
'f067'
,
'minus'
:
'f068'
,
'asterisk'
:
'f069'
,
'exclamation-circle'
:
'f06a'
,
'gift'
:
'f06b'
,
'leaf'
:
'f06c'
,
'fire'
:
'f06d'
,
'eye'
:
'f06e'
,
'eye-slash'
:
'f070'
,
'warning,exclamation-triangle'
:
'f071'
,
'plane'
:
'f072'
,
'calendar'
:
'f073'
,
'random'
:
'f074'
,
'comment'
:
'f075'
,
'magnet'
:
'f076'
,
'chevron-up'
:
'f077'
,
'chevron-down'
:
'f078'
,
'retweet'
:
'f079'
,
'shopping-cart'
:
'f07a'
,
'folder'
:
'f07b'
,
'folder-open'
:
'f07c'
,
'arrows-v'
:
'f07d'
,
'arrows-h'
:
'f07e'
,
'bar-chart-o,bar-chart'
:
'f080'
,
'twitter-square'
:
'f081'
,
'facebook-square'
:
'f082'
,
'camera-retro'
:
'f083'
,
'key'
:
'f084'
,
'gears,cogs'
:
'f085'
,
'comments'
:
'f086'
,
'thumbs-o-up'
:
'f087'
,
'thumbs-o-down'
:
'f088'
,
'star-half'
:
'f089'
,
'heart-o'
:
'f08a'
,
'sign-out'
:
'f08b'
,
'linkedin-square'
:
'f08c'
,
'thumb-tack'
:
'f08d'
,
'external-link'
:
'f08e'
,
'sign-in'
:
'f090'
,
'trophy'
:
'f091'
,
'github-square'
:
'f092'
,
'upload'
:
'f093'
,
'lemon-o'
:
'f094'
,
'phone'
:
'f095'
,
'square-o'
:
'f096'
,
'bookmark-o'
:
'f097'
,
'phone-square'
:
'f098'
,
'twitter'
:
'f099'
,
'facebook-f,facebook'
:
'f09a'
,
'github'
:
'f09b'
,
'unlock'
:
'f09c'
,
'credit-card'
:
'f09d'
,
'feed,rss'
:
'f09e'
,
'hdd-o'
:
'f0a0'
,
'bullhorn'
:
'f0a1'
,
'bell'
:
'f0f3'
,
'certificate'
:
'f0a3'
,
'hand-o-right'
:
'f0a4'
,
'hand-o-left'
:
'f0a5'
,
'hand-o-up'
:
'f0a6'
,
'hand-o-down'
:
'f0a7'
,
'arrow-circle-left'
:
'f0a8'
,
'arrow-circle-right'
:
'f0a9'
,
'arrow-circle-up'
:
'f0aa'
,
'arrow-circle-down'
:
'f0ab'
,
'globe'
:
'f0ac'
,
'wrench'
:
'f0ad'
,
'tasks'
:
'f0ae'
,
'filter'
:
'f0b0'
,
'briefcase'
:
'f0b1'
,
'arrows-alt'
:
'f0b2'
,
'group,users'
:
'f0c0'
,
'chain,link'
:
'f0c1'
,
'cloud'
:
'f0c2'
,
'flask'
:
'f0c3'
,
'cut,scissors'
:
'f0c4'
,
'copy,files-o'
:
'f0c5'
,
'paperclip'
:
'f0c6'
,
'save,floppy-o'
:
'f0c7'
,
'square'
:
'f0c8'
,
'navicon,reorder,bars'
:
'f0c9'
,
'list-ul'
:
'f0ca'
,
'list-ol'
:
'f0cb'
,
'strikethrough'
:
'f0cc'
,
'underline'
:
'f0cd'
,
'table'
:
'f0ce'
,
'magic'
:
'f0d0'
,
'truck'
:
'f0d1'
,
'pinterest'
:
'f0d2'
,
'pinterest-square'
:
'f0d3'
,
'google-plus-square'
:
'f0d4'
,
'google-plus'
:
'f0d5'
,
'money'
:
'f0d6'
,
'caret-down'
:
'f0d7'
,
'caret-up'
:
'f0d8'
,
'caret-left'
:
'f0d9'
,
'caret-right'
:
'f0da'
,
'columns'
:
'f0db'
,
'unsorted,sort'
:
'f0dc'
,
'sort-down,sort-desc'
:
'f0dd'
,
'sort-up,sort-asc'
:
'f0de'
,
'envelope'
:
'f0e0'
,
'linkedin'
:
'f0e1'
,
'rotate-left,undo'
:
'f0e2'
,
'legal,gavel'
:
'f0e3'
,
'dashboard,tachometer'
:
'f0e4'
,
'comment-o'
:
'f0e5'
,
'comments-o'
:
'f0e6'
,
'flash,bolt'
:
'f0e7'
,
'sitemap'
:
'f0e8'
,
'umbrella'
:
'f0e9'
,
'paste,clipboard'
:
'f0ea'
,
'lightbulb-o'
:
'f0eb'
,
'exchange'
:
'f0ec'
,
'cloud-download'
:
'f0ed'
,
'cloud-upload'
:
'f0ee'
,
'user-md'
:
'f0f0'
,
'stethoscope'
:
'f0f1'
,
'suitcase'
:
'f0f2'
,
'bell-o'
:
'f0a2'
,
'coffee'
:
'f0f4'
,
'cutlery'
:
'f0f5'
,
'file-text-o'
:
'f0f6'
,
'building-o'
:
'f0f7'
,
'hospital-o'
:
'f0f8'
,
'ambulance'
:
'f0f9'
,
'medkit'
:
'f0fa'
,
'fighter-jet'
:
'f0fb'
,
'beer'
:
'f0fc'
,
'h-square'
:
'f0fd'
,
'plus-square'
:
'f0fe'
,
'angle-double-left'
:
'f100'
,
'angle-double-right'
:
'f101'
,
'angle-double-up'
:
'f102'
,
'angle-double-down'
:
'f103'
,
'angle-left'
:
'f104'
,
'angle-right'
:
'f105'
,
'angle-up'
:
'f106'
,
'angle-down'
:
'f107'
,
'desktop'
:
'f108'
,
'laptop'
:
'f109'
,
'tablet'
:
'f10a'
,
'mobile-phone,mobile'
:
'f10b'
,
'circle-o'
:
'f10c'
,
'quote-left'
:
'f10d'
,
'quote-right'
:
'f10e'
,
'spinner'
:
'f110'
,
'circle'
:
'f111'
,
'mail-reply,reply'
:
'f112'
,
'github-alt'
:
'f113'
,
'folder-o'
:
'f114'
,
'folder-open-o'
:
'f115'
,
'smile-o'
:
'f118'
,
'frown-o'
:
'f119'
,
'meh-o'
:
'f11a'
,
'gamepad'
:
'f11b'
,
'keyboard-o'
:
'f11c'
,
'flag-o'
:
'f11d'
,
'flag-checkered'
:
'f11e'
,
'terminal'
:
'f120'
,
'code'
:
'f121'
,
'mail-reply-all,reply-all'
:
'f122'
,
'star-half-empty,star-half-full,star-half-o'
:
'f123'
,
'location-arrow'
:
'f124'
,
'crop'
:
'f125'
,
'code-fork'
:
'f126'
,
'unlink,chain-broken'
:
'f127'
,
'question'
:
'f128'
,
'info'
:
'f129'
,
'exclamation'
:
'f12a'
,
'superscript'
:
'f12b'
,
'subscript'
:
'f12c'
,
'eraser'
:
'f12d'
,
'puzzle-piece'
:
'f12e'
,
'microphone'
:
'f130'
,
'microphone-slash'
:
'f131'
,
'shield'
:
'f132'
,
'calendar-o'
:
'f133'
,
'fire-extinguisher'
:
'f134'
,
'rocket'
:
'f135'
,
'maxcdn'
:
'f136'
,
'chevron-circle-left'
:
'f137'
,
'chevron-circle-right'
:
'f138'
,
'chevron-circle-up'
:
'f139'
,
'chevron-circle-down'
:
'f13a'
,
'html5'
:
'f13b'
,
'css3'
:
'f13c'
,
'anchor'
:
'f13d'
,
'unlock-alt'
:
'f13e'
,
'bullseye'
:
'f140'
,
'ellipsis-h'
:
'f141'
,
'ellipsis-v'
:
'f142'
,
'rss-square'
:
'f143'
,
'play-circle'
:
'f144'
,
'ticket'
:
'f145'
,
'minus-square'
:
'f146'
,
'minus-square-o'
:
'f147'
,
'level-up'
:
'f148'
,
'level-down'
:
'f149'
,
'check-square'
:
'f14a'
,
'pencil-square'
:
'f14b'
,
'external-link-square'
:
'f14c'
,
'share-square'
:
'f14d'
,
'compass'
:
'f14e'
,
'toggle-down,caret-square-o-down'
:
'f150'
,
'toggle-up,caret-square-o-up'
:
'f151'
,
'toggle-right,caret-square-o-right'
:
'f152'
,
'euro,eur'
:
'f153'
,
'gbp'
:
'f154'
,
'dollar,usd'
:
'f155'
,
'rupee,inr'
:
'f156'
,
'cny,rmb,yen,jpy'
:
'f157'
,
'ruble,rouble,rub'
:
'f158'
,
'won,krw'
:
'f159'
,
'bitcoin,btc'
:
'f15a'
,
'file'
:
'f15b'
,
'file-text'
:
'f15c'
,
'sort-alpha-asc'
:
'f15d'
,
'sort-alpha-desc'
:
'f15e'
,
'sort-amount-asc'
:
'f160'
,
'sort-amount-desc'
:
'f161'
,
'sort-numeric-asc'
:
'f162'
,
'sort-numeric-desc'
:
'f163'
,
'thumbs-up'
:
'f164'
,
'thumbs-down'
:
'f165'
,
'youtube-square'
:
'f166'
,
'youtube'
:
'f167'
,
'xing'
:
'f168'
,
'xing-square'
:
'f169'
,
'youtube-play'
:
'f16a'
,
'dropbox'
:
'f16b'
,
'stack-overflow'
:
'f16c'
,
'instagram'
:
'f16d'
,
'flickr'
:
'f16e'
,
'adn'
:
'f170'
,
'bitbucket'
:
'f171'
,
'bitbucket-square'
:
'f172'
,
'tumblr'
:
'f173'
,
'tumblr-square'
:
'f174'
,
'long-arrow-down'
:
'f175'
,
'long-arrow-up'
:
'f176'
,
'long-arrow-left'
:
'f177'
,
'long-arrow-right'
:
'f178'
,
'apple'
:
'f179'
,
'windows'
:
'f17a'
,
'android'
:
'f17b'
,
'linux'
:
'f17c'
,
'dribbble'
:
'f17d'
,
'skype'
:
'f17e'
,
'foursquare'
:
'f180'
,
'trello'
:
'f181'
,
'female'
:
'f182'
,
'male'
:
'f183'
,
'gittip,gratipay'
:
'f184'
,
'sun-o'
:
'f185'
,
'moon-o'
:
'f186'
,
'archive'
:
'f187'
,
'bug'
:
'f188'
,
'vk'
:
'f189'
,
'weibo'
:
'f18a'
,
'renren'
:
'f18b'
,
'pagelines'
:
'f18c'
,
'stack-exchange'
:
'f18d'
,
'arrow-circle-o-right'
:
'f18e'
,
'arrow-circle-o-left'
:
'f190'
,
'toggle-left,caret-square-o-left'
:
'f191'
,
'dot-circle-o'
:
'f192'
,
'wheelchair'
:
'f193'
,
'vimeo-square'
:
'f194'
,
'turkish-lira,try'
:
'f195'
,
'plus-square-o'
:
'f196'
,
'space-shuttle'
:
'f197'
,
'slack'
:
'f198'
,
'envelope-square'
:
'f199'
,
'wordpress'
:
'f19a'
,
'openid'
:
'f19b'
,
'institution,bank,university'
:
'f19c'
,
'mortar-board,graduation-cap'
:
'f19d'
,
'yahoo'
:
'f19e'
,
'google'
:
'f1a0'
,
'reddit'
:
'f1a1'
,
'reddit-square'
:
'f1a2'
,
'stumbleupon-circle'
:
'f1a3'
,
'stumbleupon'
:
'f1a4'
,
'delicious'
:
'f1a5'
,
'digg'
:
'f1a6'
,
'pied-piper-pp'
:
'f1a7'
,
'pied-piper-alt'
:
'f1a8'
,
'drupal'
:
'f1a9'
,
'joomla'
:
'f1aa'
,
'language'
:
'f1ab'
,
'fax'
:
'f1ac'
,
'building'
:
'f1ad'
,
'child'
:
'f1ae'
,
'paw'
:
'f1b0'
,
'spoon'
:
'f1b1'
,
'cube'
:
'f1b2'
,
'cubes'
:
'f1b3'
,
'behance'
:
'f1b4'
,
'behance-square'
:
'f1b5'
,
'steam'
:
'f1b6'
,
'steam-square'
:
'f1b7'
,
'recycle'
:
'f1b8'
,
'automobile,car'
:
'f1b9'
,
'cab,taxi'
:
'f1ba'
,
'tree'
:
'f1bb'
,
'spotify'
:
'f1bc'
,
'deviantart'
:
'f1bd'
,
'soundcloud'
:
'f1be'
,
'database'
:
'f1c0'
,
'file-pdf-o'
:
'f1c1'
,
'file-word-o'
:
'f1c2'
,
'file-excel-o'
:
'f1c3'
,
'file-powerpoint-o'
:
'f1c4'
,
'file-photo-o,file-picture-o,file-image-o'
:
'f1c5'
,
'file-zip-o,file-archive-o'
:
'f1c6'
,
'file-sound-o,file-audio-o'
:
'f1c7'
,
'file-movie-o,file-video-o'
:
'f1c8'
,
'file-code-o'
:
'f1c9'
,
'vine'
:
'f1ca'
,
'codepen'
:
'f1cb'
,
'jsfiddle'
:
'f1cc'
,
'life-bouy,life-buoy,life-saver,support,life-ring'
:
'f1cd'
,
'circle-o-notch'
:
'f1ce'
,
'ra,resistance,rebel'
:
'f1d0'
,
'ge,empire'
:
'f1d1'
,
'git-square'
:
'f1d2'
,
'git'
:
'f1d3'
,
'y-combinator-square,yc-square,hacker-news'
:
'f1d4'
,
'tencent-weibo'
:
'f1d5'
,
'qq'
:
'f1d6'
,
'wechat,weixin'
:
'f1d7'
,
'send,paper-plane'
:
'f1d8'
,
'send-o,paper-plane-o'
:
'f1d9'
,
'history'
:
'f1da'
,
'circle-thin'
:
'f1db'
,
'header'
:
'f1dc'
,
'paragraph'
:
'f1dd'
,
'sliders'
:
'f1de'
,
'share-alt'
:
'f1e0'
,
'share-alt-square'
:
'f1e1'
,
'bomb'
:
'f1e2'
,
'soccer-ball-o,futbol-o'
:
'f1e3'
,
'tty'
:
'f1e4'
,
'binoculars'
:
'f1e5'
,
'plug'
:
'f1e6'
,
'slideshare'
:
'f1e7'
,
'twitch'
:
'f1e8'
,
'yelp'
:
'f1e9'
,
'newspaper-o'
:
'f1ea'
,
'wifi'
:
'f1eb'
,
'calculator'
:
'f1ec'
,
'paypal'
:
'f1ed'
,
'google-wallet'
:
'f1ee'
,
'cc-visa'
:
'f1f0'
,
'cc-mastercard'
:
'f1f1'
,
'cc-discover'
:
'f1f2'
,
'cc-amex'
:
'f1f3'
,
'cc-paypal'
:
'f1f4'
,
'cc-stripe'
:
'f1f5'
,
'bell-slash'
:
'f1f6'
,
'bell-slash-o'
:
'f1f7'
,
'trash'
:
'f1f8'
,
'copyright'
:
'f1f9'
,
'at'
:
'f1fa'
,
'eyedropper'
:
'f1fb'
,
'paint-brush'
:
'f1fc'
,
'birthday-cake'
:
'f1fd'
,
'area-chart'
:
'f1fe'
,
'pie-chart'
:
'f200'
,
'line-chart'
:
'f201'
,
'lastfm'
:
'f202'
,
'lastfm-square'
:
'f203'
,
'toggle-off'
:
'f204'
,
'toggle-on'
:
'f205'
,
'bicycle'
:
'f206'
,
'bus'
:
'f207'
,
'ioxhost'
:
'f208'
,
'angellist'
:
'f209'
,
'cc'
:
'f20a'
,
'shekel,sheqel,ils'
:
'f20b'
,
'meanpath'
:
'f20c'
,
'buysellads'
:
'f20d'
,
'connectdevelop'
:
'f20e'
,
'dashcube'
:
'f210'
,
'forumbee'
:
'f211'
,
'leanpub'
:
'f212'
,
'sellsy'
:
'f213'
,
'shirtsinbulk'
:
'f214'
,
'simplybuilt'
:
'f215'
,
'skyatlas'
:
'f216'
,
'cart-plus'
:
'f217'
,
'cart-arrow-down'
:
'f218'
,
'diamond'
:
'f219'
,
'ship'
:
'f21a'
,
'user-secret'
:
'f21b'
,
'motorcycle'
:
'f21c'
,
'street-view'
:
'f21d'
,
'heartbeat'
:
'f21e'
,
'venus'
:
'f221'
,
'mars'
:
'f222'
,
'mercury'
:
'f223'
,
'intersex,transgender'
:
'f224'
,
'transgender-alt'
:
'f225'
,
'venus-double'
:
'f226'
,
'mars-double'
:
'f227'
,
'venus-mars'
:
'f228'
,
'mars-stroke'
:
'f229'
,
'mars-stroke-v'
:
'f22a'
,
'mars-stroke-h'
:
'f22b'
,
'neuter'
:
'f22c'
,
'genderless'
:
'f22d'
,
'facebook-official'
:
'f230'
,
'pinterest-p'
:
'f231'
,
'whatsapp'
:
'f232'
,
'server'
:
'f233'
,
'user-plus'
:
'f234'
,
'user-times'
:
'f235'
,
'hotel,bed'
:
'f236'
,
'viacoin'
:
'f237'
,
'train'
:
'f238'
,
'subway'
:
'f239'
,
'medium'
:
'f23a'
,
'yc,y-combinator'
:
'f23b'
,
'optin-monster'
:
'f23c'
,
'opencart'
:
'f23d'
,
'expeditedssl'
:
'f23e'
,
'battery-4,battery-full'
:
'f240'
,
'battery-3,battery-three-quarters'
:
'f241'
,
'battery-2,battery-half'
:
'f242'
,
'battery-1,battery-quarter'
:
'f243'
,
'battery-0,battery-empty'
:
'f244'
,
'mouse-pointer'
:
'f245'
,
'i-cursor'
:
'f246'
,
'object-group'
:
'f247'
,
'object-ungroup'
:
'f248'
,
'sticky-note'
:
'f249'
,
'sticky-note-o'
:
'f24a'
,
'cc-jcb'
:
'f24b'
,
'cc-diners-club'
:
'f24c'
,
'clone'
:
'f24d'
,
'balance-scale'
:
'f24e'
,
'hourglass-o'
:
'f250'
,
'hourglass-1,hourglass-start'
:
'f251'
,
'hourglass-2,hourglass-half'
:
'f252'
,
'hourglass-3,hourglass-end'
:
'f253'
,
'hourglass'
:
'f254'
,
'hand-grab-o,hand-rock-o'
:
'f255'
,
'hand-stop-o,hand-paper-o'
:
'f256'
,
'hand-scissors-o'
:
'f257'
,
'hand-lizard-o'
:
'f258'
,
'hand-spock-o'
:
'f259'
,
'hand-pointer-o'
:
'f25a'
,
'hand-peace-o'
:
'f25b'
,
'trademark'
:
'f25c'
,
'registered'
:
'f25d'
,
'creative-commons'
:
'f25e'
,
'gg'
:
'f260'
,
'gg-circle'
:
'f261'
,
'tripadvisor'
:
'f262'
,
'odnoklassniki'
:
'f263'
,
'odnoklassniki-square'
:
'f264'
,
'get-pocket'
:
'f265'
,
'wikipedia-w'
:
'f266'
,
'safari'
:
'f267'
,
'chrome'
:
'f268'
,
'firefox'
:
'f269'
,
'opera'
:
'f26a'
,
'internet-explorer'
:
'f26b'
,
'tv,television'
:
'f26c'
,
'contao'
:
'f26d'
,
'500px'
:
'f26e'
,
'amazon'
:
'f270'
,
'calendar-plus-o'
:
'f271'
,
'calendar-minus-o'
:
'f272'
,
'calendar-times-o'
:
'f273'
,
'calendar-check-o'
:
'f274'
,
'industry'
:
'f275'
,
'map-pin'
:
'f276'
,
'map-signs'
:
'f277'
,
'map-o'
:
'f278'
,
'map'
:
'f279'
,
'commenting'
:
'f27a'
,
'commenting-o'
:
'f27b'
,
'houzz'
:
'f27c'
,
'vimeo'
:
'f27d'
,
'black-tie'
:
'f27e'
,
'fonticons'
:
'f280'
,
'reddit-alien'
:
'f281'
,
'edge'
:
'f282'
,
'credit-card-alt'
:
'f283'
,
'codiepie'
:
'f284'
,
'modx'
:
'f285'
,
'fort-awesome'
:
'f286'
,
'usb'
:
'f287'
,
'product-hunt'
:
'f288'
,
'mixcloud'
:
'f289'
,
'scribd'
:
'f28a'
,
'pause-circle'
:
'f28b'
,
'pause-circle-o'
:
'f28c'
,
'stop-circle'
:
'f28d'
,
'stop-circle-o'
:
'f28e'
,
'shopping-bag'
:
'f290'
,
'shopping-basket'
:
'f291'
,
'hashtag'
:
'f292'
,
'bluetooth'
:
'f293'
,
'bluetooth-b'
:
'f294'
,
'percent'
:
'f295'
,
'gitlab'
:
'f296'
,
'wpbeginner'
:
'f297'
,
'wpforms'
:
'f298'
,
'envira'
:
'f299'
,
'universal-access'
:
'f29a'
,
'wheelchair-alt'
:
'f29b'
,
'question-circle-o'
:
'f29c'
,
'blind'
:
'f29d'
,
'audio-description'
:
'f29e'
,
'volume-control-phone'
:
'f2a0'
,
'braille'
:
'f2a1'
,
'assistive-listening-systems'
:
'f2a2'
,
'asl-interpreting,american-sign-language-interpreting'
:
'f2a3'
,
'deafness,hard-of-hearing,deaf'
:
'f2a4'
,
'glide'
:
'f2a5'
,
'glide-g'
:
'f2a6'
,
'signing,sign-language'
:
'f2a7'
,
'low-vision'
:
'f2a8'
,
'viadeo'
:
'f2a9'
,
'viadeo-square'
:
'f2aa'
,
'snapchat'
:
'f2ab'
,
'snapchat-ghost'
:
'f2ac'
,
'snapchat-square'
:
'f2ad'
,
'pied-piper'
:
'f2ae'
,
'first-order'
:
'f2b0'
,
'yoast'
:
'f2b1'
,
'themeisle'
:
'f2b2'
,
'google-plus-circle,google-plus-official'
:
'f2b3'
,
'fa,font-awesome'
:
'f2b4'
};
}
function
icon
(
d
)
{
var
code
;
if
(
options
.
iconMap
&&
options
.
showIcons
&&
options
.
icons
)
{
if
(
options
.
icons
[
d
.
labels
[
0
]]
&&
options
.
iconMap
[
options
.
icons
[
d
.
labels
[
0
]]])
{
code
=
options
.
iconMap
[
options
.
icons
[
d
.
labels
[
0
]]];
}
else
if
(
options
.
iconMap
[
d
.
labels
[
0
]])
{
code
=
options
.
iconMap
[
d
.
labels
[
0
]];
}
else
if
(
options
.
icons
[
d
.
labels
[
0
]])
{
code
=
options
.
icons
[
d
.
labels
[
0
]];
}
}
return
code
;
}
function
image
(
d
)
{
var
i
,
imagesForLabel
,
img
,
imgLevel
,
label
,
labelPropertyValue
,
property
,
value
;
if
(
options
.
images
)
{
imagesForLabel
=
options
.
imageMap
[
d
.
labels
[
0
]];
if
(
imagesForLabel
)
{
imgLevel
=
0
;
for
(
i
=
0
;
i
<
imagesForLabel
.
length
;
i
++
)
{
labelPropertyValue
=
imagesForLabel
[
i
].
split
(
'|'
);
switch
(
labelPropertyValue
.
length
)
{
case
3
:
value
=
labelPropertyValue
[
2
];
/* falls through */
case
2
:
property
=
labelPropertyValue
[
1
];
/* falls through */
case
1
:
label
=
labelPropertyValue
[
0
];
}
if
(
d
.
labels
[
0
]
===
label
&&
(
!
property
||
d
.
properties
[
property
]
!==
undefined
)
&&
(
!
value
||
d
.
properties
[
property
]
===
value
))
{
if
(
labelPropertyValue
.
length
>
imgLevel
)
{
img
=
options
.
images
[
imagesForLabel
[
i
]];
imgLevel
=
labelPropertyValue
.
length
;
}
}
}
}
}
return
img
;
}
function
init
(
_selector
,
_options
)
{
initIconMap
();
merge
(
options
,
_options
);
if
(
options
.
icons
)
{
options
.
showIcons
=
true
;
}
if
(
!
options
.
minCollision
)
{
options
.
minCollision
=
options
.
nodeRadius
*
2
;
}
initImageMap
();
selector
=
_selector
;
container
=
d3
.
select
(
selector
);
container
.
attr
(
'class'
,
'neo4jd3'
)
.
html
(
''
);
if
(
options
.
infoPanel
)
{
info
=
appendInfoPanel
(
container
);
}
appendGraph
(
container
);
simulation
=
initSimulation
();
if
(
options
.
neo4jData
)
{
loadNeo4jData
(
options
.
neo4jData
);
}
else
if
(
options
.
neo4jDataUrl
)
{
loadNeo4jDataFromUrl
(
options
.
neo4jDataUrl
);
}
else
{
console
.
error
(
'Error: both neo4jData and neo4jDataUrl are empty!'
);
}
}
function
initIconMap
()
{
Object
.
keys
(
options
.
iconMap
).
forEach
(
function
(
key
,
index
)
{
var
keys
=
key
.
split
(
','
),
value
=
options
.
iconMap
[
key
];
keys
.
forEach
(
function
(
key
)
{
options
.
iconMap
[
key
]
=
value
;
});
});
}
function
initImageMap
()
{
var
key
,
keys
,
selector
;
for
(
key
in
options
.
images
)
{
if
(
options
.
images
.
hasOwnProperty
(
key
))
{
keys
=
key
.
split
(
'|'
);
if
(
!
options
.
imageMap
[
keys
[
0
]])
{
options
.
imageMap
[
keys
[
0
]]
=
[
key
];
}
else
{
options
.
imageMap
[
keys
[
0
]].
push
(
key
);
}
}
}
}
function
initSimulation
()
{
var
simulation
=
d3
.
forceSimulation
()
// .velocityDecay(0.8)
// .force('x', d3.force().strength(0.002))
// .force('y', d3.force().strength(0.002))
.
force
(
'collide'
,
d3
.
forceCollide
().
radius
(
function
(
d
)
{
return
options
.
minCollision
;
}).
iterations
(
2
))
.
force
(
'charge'
,
d3
.
forceManyBody
())
.
force
(
'link'
,
d3
.
forceLink
().
id
(
function
(
d
)
{
return
d
.
id
;
}))
.
force
(
'center'
,
d3
.
forceCenter
(
svg
.
node
().
parentElement
.
parentElement
.
clientWidth
/
2
,
svg
.
node
().
parentElement
.
parentElement
.
clientHeight
/
2
))
.
on
(
'tick'
,
function
()
{
tick
();
})
.
on
(
'end'
,
function
()
{
if
(
options
.
zoomFit
&&
!
justLoaded
)
{
justLoaded
=
true
;
zoomFit
(
2
);
}
});
return
simulation
;
}
function
loadNeo4jData
()
{
nodes
=
[];
relationships
=
[];
updateWithNeo4jData
(
options
.
neo4jData
);
}
function
loadNeo4jDataFromUrl
(
neo4jDataUrl
)
{
nodes
=
[];
relationships
=
[];
d3
.
json
(
neo4jDataUrl
,
function
(
error
,
data
)
{
if
(
error
)
{
throw
error
;
}
updateWithNeo4jData
(
data
);
});
}
function
merge
(
target
,
source
)
{
Object
.
keys
(
source
).
forEach
(
function
(
property
)
{
target
[
property
]
=
source
[
property
];
});
}
function
neo4jDataToD3Data
(
data
)
{
return
data
;
var
graph
=
{
nodes
:
[],
relationships
:
[]
};
data
.
results
.
forEach
(
function
(
result
)
{
result
.
data
.
forEach
(
function
(
data
)
{
data
.
graph
.
nodes
.
forEach
(
function
(
node
)
{
if
(
!
contains
(
graph
.
nodes
,
node
.
id
))
{
graph
.
nodes
.
push
(
node
);
}
});
data
.
graph
.
relationships
.
forEach
(
function
(
relationship
)
{
relationship
.
source
=
relationship
.
startNode
;
relationship
.
target
=
relationship
.
endNode
;
graph
.
relationships
.
push
(
relationship
);
});
data
.
graph
.
relationships
.
sort
(
function
(
a
,
b
)
{
if
(
a
.
source
>
b
.
source
)
{
return
1
;
}
else
if
(
a
.
source
<
b
.
source
)
{
return
-
1
;
}
else
{
if
(
a
.
target
>
b
.
target
)
{
return
1
;
}
if
(
a
.
target
<
b
.
target
)
{
return
-
1
;
}
else
{
return
0
;
}
}
});
for
(
var
i
=
0
;
i
<
data
.
graph
.
relationships
.
length
;
i
++
)
{
if
(
i
!==
0
&&
data
.
graph
.
relationships
[
i
].
source
===
data
.
graph
.
relationships
[
i
-
1
].
source
&&
data
.
graph
.
relationships
[
i
].
target
===
data
.
graph
.
relationships
[
i
-
1
].
target
)
{
data
.
graph
.
relationships
[
i
].
linknum
=
data
.
graph
.
relationships
[
i
-
1
].
linknum
+
1
;
}
else
{
data
.
graph
.
relationships
[
i
].
linknum
=
1
;
}
}
});
});
return
graph
;
}
function
randomD3Data
(
d
,
maxNodesToGenerate
)
{
var
data
=
{
nodes
:
[],
relationships
:
[]
},
i
,
label
,
node
,
numNodes
=
(
maxNodesToGenerate
*
Math
.
random
()
<<
0
)
+
1
,
relationship
,
s
=
size
();
for
(
i
=
0
;
i
<
numNodes
;
i
++
)
{
label
=
randomLabel
();
node
=
{
id
:
s
.
nodes
+
1
+
i
,
labels
:
[
label
],
properties
:
{
random
:
label
},
x
:
d
.
x
,
y
:
d
.
y
};
data
.
nodes
[
data
.
nodes
.
length
]
=
node
;
relationship
=
{
id
:
s
.
relationships
+
1
+
i
,
type
:
label
.
toUpperCase
(),
startNode
:
d
.
id
,
endNode
:
s
.
nodes
+
1
+
i
,
properties
:
{
from
:
Date
.
now
()
},
source
:
d
.
id
,
target
:
s
.
nodes
+
1
+
i
,
linknum
:
s
.
relationships
+
1
+
i
};
data
.
relationships
[
data
.
relationships
.
length
]
=
relationship
;
}
return
data
;
}
function
randomLabel
()
{
var
icons
=
Object
.
keys
(
options
.
iconMap
);
return
icons
[
icons
.
length
*
Math
.
random
()
<<
0
];
}
function
rotate
(
cx
,
cy
,
x
,
y
,
angle
)
{
var
radians
=
(
Math
.
PI
/
180
)
*
angle
,
cos
=
Math
.
cos
(
radians
),
sin
=
Math
.
sin
(
radians
),
nx
=
(
cos
*
(
x
-
cx
))
+
(
sin
*
(
y
-
cy
))
+
cx
,
ny
=
(
cos
*
(
y
-
cy
))
-
(
sin
*
(
x
-
cx
))
+
cy
;
return
{
x
:
nx
,
y
:
ny
};
}
function
rotatePoint
(
c
,
p
,
angle
)
{
return
rotate
(
c
.
x
,
c
.
y
,
p
.
x
,
p
.
y
,
angle
);
}
function
rotation
(
source
,
target
)
{
return
Math
.
atan2
(
target
.
y
-
source
.
y
,
target
.
x
-
source
.
x
)
*
180
/
Math
.
PI
;
}
function
size
()
{
return
{
nodes
:
nodes
.
length
,
relationships
:
relationships
.
length
};
}
/*
function smoothTransform(elem, translate, scale) {
var animationMilliseconds = 5000,
timeoutMilliseconds = 50,
steps = parseInt(animationMilliseconds / timeoutMilliseconds);
setTimeout(function() {
smoothTransformStep(elem, translate, scale, timeoutMilliseconds, 1, steps);
}, timeoutMilliseconds);
}
function smoothTransformStep(elem, translate, scale, timeoutMilliseconds, step, steps) {
var progress = step / steps;
elem.attr('transform', 'translate(' + (translate[0] * progress) + ', ' + (translate[1] * progress) + ') scale(' + (scale * progress) + ')');
if (step < steps) {
setTimeout(function() {
smoothTransformStep(elem, translate, scale, timeoutMilliseconds, step + 1, steps);
}, timeoutMilliseconds);
}
}
*/
function
stickNode
(
d
)
{
d
.
fx
=
d3
.
event
.
x
;
d
.
fy
=
d3
.
event
.
y
;
}
function
tick
()
{
tickNodes
();
tickRelationships
();
}
function
tickNodes
()
{
if
(
node
)
{
node
.
attr
(
'transform'
,
function
(
d
)
{
return
'translate('
+
d
.
x
+
', '
+
d
.
y
+
')'
;
});
}
}
function
tickRelationships
()
{
if
(
relationship
)
{
relationship
.
attr
(
'transform'
,
function
(
d
)
{
var
angle
=
rotation
(
d
.
source
,
d
.
target
);
return
'translate('
+
d
.
source
.
x
+
', '
+
d
.
source
.
y
+
') rotate('
+
angle
+
')'
;
});
tickRelationshipsTexts
();
tickRelationshipsOutlines
();
tickRelationshipsOverlays
();
}
}
function
tickRelationshipsOutlines
()
{
relationship
.
each
(
function
(
relationship
)
{
var
rel
=
d3
.
select
(
this
),
outline
=
rel
.
select
(
'.outline'
),
text
=
rel
.
select
(
'.text'
),
bbox
=
text
.
node
().
getBBox
(),
padding
=
3
;
outline
.
attr
(
'd'
,
function
(
d
)
{
var
center
=
{
x
:
0
,
y
:
0
},
angle
=
rotation
(
d
.
source
,
d
.
target
),
textBoundingBox
=
text
.
node
().
getBBox
(),
textPadding
=
5
,
u
=
unitaryVector
(
d
.
source
,
d
.
target
),
textMargin
=
{
x
:
(
d
.
target
.
x
-
d
.
source
.
x
-
(
textBoundingBox
.
width
+
textPadding
)
*
u
.
x
)
*
0.5
,
y
:
(
d
.
target
.
y
-
d
.
source
.
y
-
(
textBoundingBox
.
width
+
textPadding
)
*
u
.
y
)
*
0.5
},
n
=
unitaryNormalVector
(
d
.
source
,
d
.
target
),
rotatedPointA1
=
rotatePoint
(
center
,
{
x
:
0
+
(
options
.
nodeRadius
+
1
)
*
u
.
x
-
n
.
x
,
y
:
0
+
(
options
.
nodeRadius
+
1
)
*
u
.
y
-
n
.
y
},
angle
),
rotatedPointB1
=
rotatePoint
(
center
,
{
x
:
textMargin
.
x
-
n
.
x
,
y
:
textMargin
.
y
-
n
.
y
},
angle
),
rotatedPointC1
=
rotatePoint
(
center
,
{
x
:
textMargin
.
x
,
y
:
textMargin
.
y
},
angle
),
rotatedPointD1
=
rotatePoint
(
center
,
{
x
:
0
+
(
options
.
nodeRadius
+
1
)
*
u
.
x
,
y
:
0
+
(
options
.
nodeRadius
+
1
)
*
u
.
y
},
angle
),
rotatedPointA2
=
rotatePoint
(
center
,
{
x
:
d
.
target
.
x
-
d
.
source
.
x
-
textMargin
.
x
-
n
.
x
,
y
:
d
.
target
.
y
-
d
.
source
.
y
-
textMargin
.
y
-
n
.
y
},
angle
),
rotatedPointB2
=
rotatePoint
(
center
,
{
x
:
d
.
target
.
x
-
d
.
source
.
x
-
(
options
.
nodeRadius
+
1
)
*
u
.
x
-
n
.
x
-
u
.
x
*
options
.
arrowSize
,
y
:
d
.
target
.
y
-
d
.
source
.
y
-
(
options
.
nodeRadius
+
1
)
*
u
.
y
-
n
.
y
-
u
.
y
*
options
.
arrowSize
},
angle
),
rotatedPointC2
=
rotatePoint
(
center
,
{
x
:
d
.
target
.
x
-
d
.
source
.
x
-
(
options
.
nodeRadius
+
1
)
*
u
.
x
-
n
.
x
+
(
n
.
x
-
u
.
x
)
*
options
.
arrowSize
,
y
:
d
.
target
.
y
-
d
.
source
.
y
-
(
options
.
nodeRadius
+
1
)
*
u
.
y
-
n
.
y
+
(
n
.
y
-
u
.
y
)
*
options
.
arrowSize
},
angle
),
rotatedPointD2
=
rotatePoint
(
center
,
{
x
:
d
.
target
.
x
-
d
.
source
.
x
-
(
options
.
nodeRadius
+
1
)
*
u
.
x
,
y
:
d
.
target
.
y
-
d
.
source
.
y
-
(
options
.
nodeRadius
+
1
)
*
u
.
y
},
angle
),
rotatedPointE2
=
rotatePoint
(
center
,
{
x
:
d
.
target
.
x
-
d
.
source
.
x
-
(
options
.
nodeRadius
+
1
)
*
u
.
x
+
(
-
n
.
x
-
u
.
x
)
*
options
.
arrowSize
,
y
:
d
.
target
.
y
-
d
.
source
.
y
-
(
options
.
nodeRadius
+
1
)
*
u
.
y
+
(
-
n
.
y
-
u
.
y
)
*
options
.
arrowSize
},
angle
),
rotatedPointF2
=
rotatePoint
(
center
,
{
x
:
d
.
target
.
x
-
d
.
source
.
x
-
(
options
.
nodeRadius
+
1
)
*
u
.
x
-
u
.
x
*
options
.
arrowSize
,
y
:
d
.
target
.
y
-
d
.
source
.
y
-
(
options
.
nodeRadius
+
1
)
*
u
.
y
-
u
.
y
*
options
.
arrowSize
},
angle
),
rotatedPointG2
=
rotatePoint
(
center
,
{
x
:
d
.
target
.
x
-
d
.
source
.
x
-
textMargin
.
x
,
y
:
d
.
target
.
y
-
d
.
source
.
y
-
textMargin
.
y
},
angle
);
return
'M '
+
rotatedPointA1
.
x
+
' '
+
rotatedPointA1
.
y
+
' L '
+
rotatedPointB1
.
x
+
' '
+
rotatedPointB1
.
y
+
' L '
+
rotatedPointC1
.
x
+
' '
+
rotatedPointC1
.
y
+
' L '
+
rotatedPointD1
.
x
+
' '
+
rotatedPointD1
.
y
+
' Z M '
+
rotatedPointA2
.
x
+
' '
+
rotatedPointA2
.
y
+
' L '
+
rotatedPointB2
.
x
+
' '
+
rotatedPointB2
.
y
+
' L '
+
rotatedPointC2
.
x
+
' '
+
rotatedPointC2
.
y
+
' L '
+
rotatedPointD2
.
x
+
' '
+
rotatedPointD2
.
y
+
' L '
+
rotatedPointE2
.
x
+
' '
+
rotatedPointE2
.
y
+
' L '
+
rotatedPointF2
.
x
+
' '
+
rotatedPointF2
.
y
+
' L '
+
rotatedPointG2
.
x
+
' '
+
rotatedPointG2
.
y
+
' Z'
;
});
});
}
function
tickRelationshipsOverlays
()
{
relationshipOverlay
.
attr
(
'd'
,
function
(
d
)
{
var
center
=
{
x
:
0
,
y
:
0
},
angle
=
rotation
(
d
.
source
,
d
.
target
),
n1
=
unitaryNormalVector
(
d
.
source
,
d
.
target
),
n
=
unitaryNormalVector
(
d
.
source
,
d
.
target
,
50
),
rotatedPointA
=
rotatePoint
(
center
,
{
x
:
0
-
n
.
x
,
y
:
0
-
n
.
y
},
angle
),
rotatedPointB
=
rotatePoint
(
center
,
{
x
:
d
.
target
.
x
-
d
.
source
.
x
-
n
.
x
,
y
:
d
.
target
.
y
-
d
.
source
.
y
-
n
.
y
},
angle
),
rotatedPointC
=
rotatePoint
(
center
,
{
x
:
d
.
target
.
x
-
d
.
source
.
x
+
n
.
x
-
n1
.
x
,
y
:
d
.
target
.
y
-
d
.
source
.
y
+
n
.
y
-
n1
.
y
},
angle
),
rotatedPointD
=
rotatePoint
(
center
,
{
x
:
0
+
n
.
x
-
n1
.
x
,
y
:
0
+
n
.
y
-
n1
.
y
},
angle
);
return
'M '
+
rotatedPointA
.
x
+
' '
+
rotatedPointA
.
y
+
' L '
+
rotatedPointB
.
x
+
' '
+
rotatedPointB
.
y
+
' L '
+
rotatedPointC
.
x
+
' '
+
rotatedPointC
.
y
+
' L '
+
rotatedPointD
.
x
+
' '
+
rotatedPointD
.
y
+
' Z'
;
});
}
function
tickRelationshipsTexts
()
{
relationshipText
.
attr
(
'transform'
,
function
(
d
)
{
var
angle
=
(
rotation
(
d
.
source
,
d
.
target
)
+
360
)
%
360
,
mirror
=
angle
>
90
&&
angle
<
270
,
center
=
{
x
:
0
,
y
:
0
},
n
=
unitaryNormalVector
(
d
.
source
,
d
.
target
),
nWeight
=
mirror
?
2
:
-
3
,
point
=
{
x
:
(
d
.
target
.
x
-
d
.
source
.
x
)
*
0.5
+
n
.
x
*
nWeight
,
y
:
(
d
.
target
.
y
-
d
.
source
.
y
)
*
0.5
+
n
.
y
*
nWeight
},
rotatedPoint
=
rotatePoint
(
center
,
point
,
angle
);
return
'translate('
+
rotatedPoint
.
x
+
', '
+
rotatedPoint
.
y
+
') rotate('
+
(
mirror
?
180
:
0
)
+
')'
;
});
}
function
toString
(
d
)
{
var
s
=
d
.
labels
?
d
.
labels
[
0
]
:
d
.
type
;
s
+=
' (<id>: '
+
d
.
id
;
Object
.
keys
(
d
.
properties
).
forEach
(
function
(
property
)
{
s
+=
', '
+
property
+
': '
+
JSON
.
stringify
(
d
.
properties
[
property
]);
});
s
+=
')'
;
return
s
;
}
function
unitaryNormalVector
(
source
,
target
,
newLength
)
{
var
center
=
{
x
:
0
,
y
:
0
},
vector
=
unitaryVector
(
source
,
target
,
newLength
);
return
rotatePoint
(
center
,
vector
,
90
);
}
function
unitaryVector
(
source
,
target
,
newLength
)
{
var
length
=
Math
.
sqrt
(
Math
.
pow
(
target
.
x
-
source
.
x
,
2
)
+
Math
.
pow
(
target
.
y
-
source
.
y
,
2
))
/
Math
.
sqrt
(
newLength
||
1
);
return
{
x
:
(
target
.
x
-
source
.
x
)
/
length
,
y
:
(
target
.
y
-
source
.
y
)
/
length
,
};
}
function
updateWithD3Data
(
d3Data
)
{
updateNodesAndRelationships
(
d3Data
.
nodes
,
d3Data
.
relationships
);
}
function
updateWithNeo4jData
(
neo4jData
)
{
var
d3Data
=
neo4jDataToD3Data
(
neo4jData
);
updateWithD3Data
(
d3Data
);
}
function
updateInfo
(
d
)
{
clearInfo
();
if
(
d
.
labels
)
{
appendInfoElementClass
(
'class'
,
d
.
labels
[
0
]);
}
else
{
appendInfoElementRelationship
(
'class'
,
d
.
type
);
}
appendInfoElementProperty
(
'property'
,
'<id>'
,
d
.
id
);
Object
.
keys
(
d
.
properties
).
forEach
(
function
(
property
)
{
appendInfoElementProperty
(
'property'
,
property
,
JSON
.
stringify
(
d
.
properties
[
property
]));
});
}
function
updateNodes
(
n
)
{
Array
.
prototype
.
push
.
apply
(
nodes
,
n
);
node
=
svgNodes
.
selectAll
(
'.node'
)
.
data
(
nodes
,
function
(
d
)
{
return
d
.
id
;
});
var
nodeEnter
=
appendNodeToGraph
();
node
=
nodeEnter
.
merge
(
node
);
}
function
updateNodesAndRelationships
(
n
,
r
)
{
updateRelationships
(
r
);
updateNodes
(
n
);
simulation
.
nodes
(
nodes
);
simulation
.
force
(
'link'
).
links
(
relationships
);
}
function
updateRelationships
(
r
)
{
Array
.
prototype
.
push
.
apply
(
relationships
,
r
);
relationship
=
svgRelationships
.
selectAll
(
'.relationship'
)
.
data
(
relationships
,
function
(
d
)
{
return
d
.
id
;
});
var
relationshipEnter
=
appendRelationshipToGraph
();
relationship
=
relationshipEnter
.
relationship
.
merge
(
relationship
);
relationshipOutline
=
svg
.
selectAll
(
'.relationship .outline'
);
relationshipOutline
=
relationshipEnter
.
outline
.
merge
(
relationshipOutline
);
relationshipOverlay
=
svg
.
selectAll
(
'.relationship .overlay'
);
relationshipOverlay
=
relationshipEnter
.
overlay
.
merge
(
relationshipOverlay
);
relationshipText
=
svg
.
selectAll
(
'.relationship .text'
);
relationshipText
=
relationshipEnter
.
text
.
merge
(
relationshipText
);
}
function
version
()
{
return
VERSION
;
}
function
zoomFit
(
transitionDuration
)
{
var
bounds
=
svg
.
node
().
getBBox
(),
parent
=
svg
.
node
().
parentElement
.
parentElement
,
fullWidth
=
parent
.
clientWidth
,
fullHeight
=
parent
.
clientHeight
,
width
=
bounds
.
width
,
height
=
bounds
.
height
,
midX
=
bounds
.
x
+
width
/
2
,
midY
=
bounds
.
y
+
height
/
2
;
if
(
width
===
0
||
height
===
0
)
{
return
;
// nothing to fit
}
svgScale
=
0.85
/
Math
.
max
(
width
/
fullWidth
,
height
/
fullHeight
);
svgTranslate
=
[
fullWidth
/
2
-
svgScale
*
midX
,
fullHeight
/
2
-
svgScale
*
midY
];
svg
.
attr
(
'transform'
,
'translate('
+
svgTranslate
[
0
]
+
', '
+
svgTranslate
[
1
]
+
') scale('
+
svgScale
+
')'
);
// smoothTransform(svgTranslate, svgScale);
}
init
(
_selector
,
_options
);
return
{
appendRandomDataToNode
:
appendRandomDataToNode
,
neo4jDataToD3Data
:
neo4jDataToD3Data
,
randomD3Data
:
randomD3Data
,
size
:
size
,
updateWithD3Data
:
updateWithD3Data
,
updateWithNeo4jData
:
updateWithNeo4jData
,
version
:
version
};
}
export
default
Neo4jD3
;
\ No newline at end of file
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论