Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
C
CiS Projekt
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Ockenden, Samuel
CiS Projekt
Merge requests
!14
stable version and bug fixes for graph update
Code
Review changes
Check out branch
Download
Patches
Plain diff
Merged
stable version and bug fixes for graph update
bav1758/ci-s-projekt-verarbeitung:main
into
main
Overview
0
Commits
9
Pipelines
0
Changes
18
Merged
Schokolowski, Malte
requested to merge
bav1758/ci-s-projekt-verarbeitung:main
into
main
3 years ago
Overview
0
Commits
9
Pipelines
0
Changes
18
Expand
0
0
Merge request reports
Viewing commit
408971b5
Prev
Next
Show latest version
18 files
+
736
−
46
Inline
Compare changes
Side-by-side
Inline
Show whitespace changes
Show one file at a time
Files
18
Search (e.g. *.vue) (Ctrl+P)
408971b5
Merge branch 'main' of
https://gitlab.rrz.uni-hamburg.de/bav1758/ci-s-projekt-verarbeitung
· 408971b5
Malte Schokolowski
authored
3 years ago
assets/cn.js
0 → 100644
+
548
−
0
Options
/**
* creates a new zoom behavior
*/
var
zoom
=
d3
.
zoom
().
on
(
"
zoom
"
,
handle_zoom
);
/**
* creates svg object and associated attributes
* applies the zoom behavior to svg
*/
var
svg
=
d3
.
select
(
"
svg.graph
"
)
.
call
(
zoom
),
width
=
svg
.
attr
(
"
width
"
),
height
=
svg
.
attr
(
"
height
"
),
perc
;
/**
* scale functions that return y coordinate/color of node depending on group
*/
var
color
=
d3
.
scaleOrdinal
()
.
domain
([
"
height
"
,
"
input
"
,
"
depth
"
])
.
range
([
'
#01d7c0
'
,
'
#8b90fe
'
,
'
#a15eb2
'
]),
y_scale
=
d3
.
scaleOrdinal
()
.
domain
([
"
height
"
,
"
input
"
,
"
depth
"
])
.
range
([
0
,
200
,
400
]),
to_remove
;
/**
* creates node object and (default) radius
*/
var
node
,
r
=
10
;
/**
* creates link object
*/
var
link
;
/**
* creates a background with a click functionality
*/
var
rect
=
svg
.
append
(
"
rect
"
)
.
attr
(
"
x
"
,
0
)
.
attr
(
"
y
"
,
0
)
.
attr
(
"
height
"
,
height
)
.
attr
(
"
width
"
,
width
)
.
style
(
"
fill
"
,
'
white
'
)
.
on
(
'
click
'
,
click_rect
);
/**
* creates svg object (legend) and associated attributes
*/
var
svg_legend
=
d3
.
select
(
"
svg.legendsvg
"
),
legend_position
=
[
65
,
95
,
125
],
arrow_legend_position
=
[
0
,
25
],
arrow_group_names
=
[
"
citation
"
,
"
self-citation
"
],
group_names
=
[
"
cited by
"
,
"
input
"
,
"
reference
"
],
line_type
=
d3
.
scaleOrdinal
()
.
domain
([
"
line
"
,
"
dotted
"
])
.
range
([(
"
8,0
"
),(
"
8,8
"
)]),
text_info
=
''
,
text_abstract
=
''
;
var
legend
=
svg_legend
.
selectAll
(
"
.legend
"
)
.
data
(
legend_position
)
.
enter
()
.
append
(
"
g
"
)
.
attr
(
"
class
"
,
"
legend
"
)
.
attr
(
"
transform
"
,
function
(
d
,
i
)
{
return
"
translate(0,
"
+
d
+
"
)
"
;
});
legend
.
append
(
"
text
"
)
.
attr
(
"
x
"
,
80
)
.
attr
(
"
y
"
,
0
)
.
attr
(
"
dy
"
,
"
.35em
"
)
.
style
(
"
text-anchor
"
,
"
start
"
)
.
text
(
function
(
d
,
i
)
{
return
group_names
[
i
]});
legend
.
append
(
"
circle
"
)
.
attr
(
"
r
"
,
r
)
.
attr
(
"
cx
"
,
30
-
r
)
.
style
(
"
fill
"
,
color
);
var
legend_arrow
=
svg_legend
.
selectAll
(
"
.legendarr
"
)
.
data
(
arrow_legend_position
)
.
enter
()
.
append
(
"
g
"
)
.
attr
(
"
class
"
,
"
legendarr
"
)
.
attr
(
"
transform
"
,
function
(
d
)
{
return
"
translate(0,
"
+
d
+
"
)
"
;
});
legend_arrow
.
append
(
"
line
"
)
.
attr
(
"
x1
"
,
10
)
.
attr
(
"
x2
"
,
50
)
.
attr
(
"
y1
"
,
10
)
.
attr
(
"
y2
"
,
10
)
.
style
(
"
stroke-dasharray
"
,
line_type
)
.
style
(
"
stroke
"
,
'
#999
'
)
.
style
(
"
stroke-width
"
,
"
1px
"
)
.
style
(
'
pointer-events
'
,
'
none
'
)
.
attr
(
'
marker-end
'
,
update_marker
(
'
#999
'
,
this
));
legend_arrow
.
append
(
"
text
"
)
.
attr
(
"
x
"
,
80
)
.
attr
(
"
y
"
,
10
)
.
attr
(
"
dy
"
,
"
.35em
"
)
.
style
(
"
text-anchor
"
,
"
start
"
)
.
text
(
function
(
d
,
i
){
return
arrow_group_names
[
i
]});
/**
* creates a new simulation
* updates the positions of the links and nodes when the
state of the layout has changed (simulation has advanced by a tick)
*/
var
simulation
=
d3
.
forceSimulation
()
.
force
(
"
link
"
,
d3
.
forceLink
().
id
(
function
(
d
)
{
return
d
.
doi
;}).
distance
(
50
).
strength
(
function
(
d
)
{
if
(
d
.
group
==
"
input
"
)
{
return
0
;}
else
{
return
5
;}
}))
.
force
(
"
collide
"
,
d3
.
forceCollide
(
function
(
d
)
{
if
(
d
.
group
==
"
input
"
)
{
return
100
;}
else
{
return
65
;}
}).
strength
(
0.5
))
.
force
(
"
charge
"
,
d3
.
forceManyBody
().
strength
(
0.001
))
.
force
(
"
center
"
,
d3
.
forceCenter
(
width
/
2
,
height
/
2
+
20
))
.
force
(
"
yscale
"
,
d3
.
forceY
().
strength
(
function
(
d
)
{
if
(
d
.
group
==
"
input
"
)
{
return
1000
;}
else
{
return
50
;}
}).
y
(
function
(
d
)
{
return
y_scale
(
d
.
group
)}))
.
alpha
(
0.005
)
.
on
(
"
end
"
,
zoom_to
);
/**
* creates group element
*/
var
g
=
svg
.
append
(
"
g
"
)
.
attr
(
"
class
"
,
"
everything
"
)
/**
* loads JSON data and calls the update function
*/
d3
.
json
(
"
json_text.json
"
).
then
(
function
(
graph
)
{
update
(
graph
.
links
,
graph
.
nodes
);
})
/**
* calls update functions for links and nodes
* adds the nodes, links and tick functionality to the simulation
* @param {object} nodes - nodes
* @param {object} links - links
*/
function
update
(
links
,
nodes
)
{
update_links
(
links
);
update_nodes
(
nodes
);
simulation
.
nodes
(
nodes
)
.
on
(
"
tick
"
,
handle_tick
);
simulation
.
force
(
"
link
"
)
.
links
(
links
);
link
.
attr
(
'
marker-end
'
,
function
(
d
)
{
return
update_marker
(
"
#999
"
,
d
.
target
);})
.
style
(
"
stroke-dasharray
"
,
function
(
d
){
return
self_citation
(
d
.
source
,
d
.
target
)?
(
"
8,8
"
):
(
"
1,0
"
)});
}
/**
* initializes and shows links
* @param {object} links - links
*/
function
update_links
(
links
)
{
link
=
g
.
append
(
"
g
"
)
.
selectAll
(
"
.link
"
)
.
data
(
links
)
.
enter
()
.
append
(
"
line
"
)
.
style
(
"
stroke-width
"
,
"
1px
"
)
.
style
(
"
stroke
"
,
"
#999
"
)
.
attr
(
"
class
"
,
"
link
"
);
}
/**
* initializes and shows nodes with circles, texts and a click functionality
* creates a new drag behavior and applies it to the circles
* @param {object} nodes - nodes
*/
function
update_nodes
(
nodes
)
{
node
=
g
.
selectAll
(
"
.node
"
)
.
data
(
nodes
)
.
enter
()
.
append
(
"
g
"
)
.
attr
(
"
class
"
,
"
node
"
)
.
call
(
d3
.
drag
()
.
on
(
"
start
"
,
start_drag
)
.
on
(
"
drag
"
,
dragged
)
);
node
.
append
(
"
circle
"
)
.
attr
(
"
class
"
,
"
circle
"
)
.
attr
(
"
r
"
,
function
(
d
)
{
return
1.5
*
r
+
d
.
citations
*
0.05
})
.
style
(
"
fill
"
,
function
(
d
){
return
color
(
d
.
group
)})
.
on
(
'
click
'
,
click_node
);
node
.
append
(
"
text
"
)
.
attr
(
"
class
"
,
"
text
"
)
.
style
(
"
font-size
"
,
"
15px
"
)
.
style
(
'
pointer-events
'
,
'
auto
'
)
.
text
(
function
(
d
)
{
const
first_author
=
d
.
author
[
0
].
split
(
"
"
)
return
first_author
[
first_author
.
length
-
1
];})
.
on
(
'
click
'
,
click_node
);
}
/**
* creates arrowhead and returns its url
* @param {string} color - color of arrowhead
* @param {string} target - target node
*/
function
update_marker
(
color
,
target
)
{
var
radius
=
1.5
*
r
+
target
.
citations
*
0.05
;
svg
.
append
(
'
defs
'
).
append
(
'
marker
'
)
.
attr
(
'
id
'
,
color
.
replace
(
"
#
"
,
""
)
+
radius
)
.
attr
(
'
viewBox
'
,
'
-0 -5 10 10
'
)
.
attr
(
'
refX
'
,
radius
+
9.5
)
.
attr
(
'
refY
'
,
0
)
.
attr
(
'
orient
'
,
'
auto
'
)
.
attr
(
'
markerWidth
'
,
10
)
.
attr
(
'
markerHeight
'
,
15
)
.
attr
(
'
xoverflow
'
,
'
visible
'
)
.
append
(
'
svg:path
'
)
.
attr
(
'
d
'
,
'
M 0,-5 L 10 ,0 L 0,5
'
)
.
attr
(
'
fill
'
,
color
)
.
style
(
'
stroke
'
,
'
none
'
);
return
"
url(
"
+
color
+
radius
+
"
)
"
;
};
/**
* sets color of circle and its links to black and removes the previous highlights
* displays overview info of node in textbox
* @param {object} node - node
*/
function
click_node
(
node
)
{
d3
.
select
(
this
.
parentNode
).
raise
();
fix_nodes
(
node
);
if
(
to_remove
){
d3
.
select
(
to_remove
).
selectAll
(
"
.circle
"
).
style
(
"
stroke
"
,
"
none
"
)
}
to_remove
=
this
.
parentNode
;
d3
.
select
(
this
.
parentNode
).
selectAll
(
"
.circle
"
).
style
(
"
stroke
"
,
"
black
"
)
mark_link
(
node
)
textbox_content
(
node
)
reset_button_highlight
()
highlight_button
(
"
overview
"
)
}
/**
* removes the highlights of the circles and their links
*/
function
click_rect
()
{
fix_nodes
(
node
);
d3
.
selectAll
(
"
.circle
"
).
style
(
"
stroke
"
,
"
none
"
)
d3
.
selectAll
(
"
.link
"
)
.
style
(
"
stroke
"
,
"
#999
"
)
.
attr
(
'
marker-end
'
,
function
(
d
)
{
return
update_marker
(
'
#999
'
,
d
.
target
);})
text_abstract
=
''
;
text_info
=
''
;
reset_button_highlight
()
document
.
getElementById
(
'
textbox
'
).
innerHTML
=
"
Click node
"
;
}
/**
* returns true if journals have a common author (self-citation)
* @param {object} source - node
* @param {object} target - node
*/
function
self_citation
(
source
,
target
)
{
return
source
.
author
.
some
(
item
=>
target
.
author
.
includes
(
item
))
}
/**
* sets color of link (line and arrowhead) to black if it is directly connected to node
* and to grey otherwise
* @param {object} node - node
*/
function
mark_link
(
node
)
{
d3
.
selectAll
(
"
.link
"
)
.
style
(
"
stroke
"
,
function
(
o
)
{
return
is_link_for_node
(
node
,
o
)
?
"
black
"
:
"
#999
"
;})
.
attr
(
'
marker-end
'
,
function
(
o
)
{
return
is_link_for_node
(
node
,
o
)
?
update_marker
(
'
#000000
'
,
o
.
target
)
:
update_marker
(
'
#999
'
,
o
.
target
);})
}
/**
* returns true if link is directly connected to node and false if it is not
* @param {object} node - node
* @param {object} link - link
*/
function
is_link_for_node
(
node
,
link
)
{
return
link
.
source
.
index
==
node
.
index
||
link
.
target
.
index
==
node
.
index
;
}
/**
* saves text for overview and abstract of node
* outputs node info to textbox
* @param {object} node - node
*/
function
textbox_content
(
node
)
{
text_info
=
"
Title:
"
+
'
</br>
'
+
node
.
name
+
'
</br>
'
+
'
</br>
'
+
"
Author:
"
+
'
</br>
'
+
node
.
author
+
'
</br>
'
+
'
</br>
'
+
"
Date:
"
+
'
</br>
'
+
node
.
year
+
'
</br>
'
+
'
</br>
'
+
"
Journal:
"
+
'
</br>
'
+
node
.
journal
+
'
</br>
'
+
'
</br>
'
+
"
doi:
"
+
'
</br>
'
+
'
<a href="
'
+
node
.
doi
+
'
">
'
+
node
.
doi
+
'
</a>
'
+
'
</br>
'
+
'
</br>
'
+
"
Citations:
"
+
'
</br>
'
+
node
.
citations
;
text_abstract
=
node
.
abstract
;
document
.
getElementById
(
'
textbox
'
).
innerHTML
=
text_info
;
}
/**
* sets color of btn to dark gray
* @param {object} btn - button
*/
function
highlight_button
(
btn
)
{
reset_button_highlight
();
document
.
getElementById
(
btn
).
style
.
background
=
"
#CACACA
"
;
}
/**
* sets color of all buttons to default light gray
*/
function
reset_button_highlight
()
{
document
.
getElementById
(
"
overview
"
).
style
.
background
=
''
;
document
.
getElementById
(
"
abstract
"
).
style
.
background
=
''
;
}
/**
* displays abstract in textbox if a is true, overview text otherwise
* @param {bool} a- bool
*/
function
display_abstract
(
a
)
{
if
(
text_abstract
==
''
&&
text_info
==
''
)
{
document
.
getElementById
(
'
textbox
'
).
innerHTML
=
"
Click node
"
;
}
else
{
if
(
a
==
true
)
{
document
.
getElementById
(
'
textbox
'
).
innerHTML
=
text_abstract
;
}
else
{
document
.
getElementById
(
'
textbox
'
).
innerHTML
=
text_info
;
}
}
}
/**
* updates the positions of the links and nodes
*/
function
handle_tick
()
{
link
.
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
;});
node
.
attr
(
"
transform
"
,
function
(
d
)
{
return
"
translate(
"
+
d
.
x
+
"
,
"
+
d
.
y
+
"
)
"
;});
}
/**
* initializes the dragging of the node
* @param {object} node - node
*/
function
start_drag
(
node
)
{
d3
.
select
(
this
).
raise
();
if
(
!
d3
.
event
.
active
)
simulation
.
alphaTarget
(
0.3
).
restart
()
node
.
fx
=
node
.
x
;
node
.
fy
=
node
.
y
;
fix_nodes
(
node
);
}
/**
* applies the dragging to the node
* @param {object} node - node
*/
function
dragged
(
node
)
{
node
.
fx
=
d3
.
event
.
x
;
node
.
fy
=
d3
.
event
.
y
;
fix_nodes
(
node
);
}
/**
* fix positions of all nodes except for the current node
* @param {object} this_node - node
*/
function
fix_nodes
(
this_node
)
{
node
.
each
(
function
(
d
)
{
if
(
this_node
!=
d
)
{
d
.
fx
=
d
.
x
;
d
.
fy
=
d
.
y
;
}
});
}
/**
* applies the transformation (zooming or dragging) to the g element
*/
function
handle_zoom
()
{
d3
.
select
(
'
g
'
).
attr
(
"
transform
"
,
d3
.
event
.
transform
);
}
/**
* transforms svg so that the zoom is adapted to the size of the graph
*/
function
zoom_to
()
{
node_bounds
=
d3
.
selectAll
(
"
svg.graph
"
).
node
().
getBBox
();
svg_bounds
=
d3
.
select
(
"
rect
"
).
node
().
getBBox
();
perc_x
=
width
/
(
node_bounds
.
width
+
100
);
perc_y
=
height
/
(
node_bounds
.
height
+
100
);
perc
=
d3
.
min
([
perc_x
,
perc_y
])
d3
.
select
(
'
svg
'
)
.
call
(
zoom
.
scaleBy
,
perc
);
}
/**
* transforms svg so that the zoom and drag is reset
*/
function
reset_view
()
{
d3
.
select
(
'
svg
'
)
.
call
(
zoom
.
scaleTo
,
1
)
d3
.
select
(
'
svg
'
)
.
call
(
zoom
.
translateTo
,
0.5
*
width
,
0.5
*
height
);
d3
.
select
(
'
svg
'
)
.
call
(
zoom
.
scaleBy
,
perc
);
}
/**
* save svg as png
*/
function
save_svg
(){
var
svgString
=
get_svg_string
(
svg
.
node
());
svg_string_to_image
(
svgString
,
2
*
width
,
2
*
height
,
'
png
'
,
save
);
// passes Blob and filesize String to the callback
function
save
(
dataBlob
,
filesize
){
saveAs
(
dataBlob
,
'
D3 vis exported to PNG.png
'
);
// FileSaver.js function
}
};
/**
* generate svgString
* @param {object} svgNode - node
*/
function
get_svg_string
(
svgNode
)
{
svgNode
.
setAttribute
(
'
xlink
'
,
'
http://www.w3.org/1999/xlink
'
);
var
cssStyleText
=
get_css_styles
(
svgNode
);
append_css
(
cssStyleText
,
svgNode
);
var
serializer
=
new
XMLSerializer
();
var
svgString
=
serializer
.
serializeToString
(
svgNode
);
svgString
=
svgString
.
replace
(
/
(\w
+
)?
:
?
xlink=/g
,
'
xmlns:xlink=
'
);
// Fix root xlink without namespace
svgString
=
svgString
.
replace
(
/NS
\d
+:href/g
,
'
xlink:href
'
);
// Safari NS namespace fix
return
svgString
;
function
get_css_styles
(
parentElement
)
{
var
selectorTextArr
=
[];
// Add Parent element Id and Classes to the list
selectorTextArr
.
push
(
'
#
'
+
parentElement
.
id
);
for
(
var
c
=
0
;
c
<
parentElement
.
classList
.
length
;
c
++
)
if
(
!
contains
(
'
.
'
+
parentElement
.
classList
[
c
],
selectorTextArr
))
selectorTextArr
.
push
(
'
.
'
+
parentElement
.
classList
[
c
]);
// Add Children element Ids and Classes to the list
var
nodes
=
parentElement
.
getElementsByTagName
(
"
*
"
);
for
(
var
i
=
0
;
i
<
nodes
.
length
;
i
++
)
{
var
id
=
nodes
[
i
].
id
;
if
(
!
contains
(
'
#
'
+
id
,
selectorTextArr
))
selectorTextArr
.
push
(
'
#
'
+
id
);
var
classes
=
nodes
[
i
].
classList
;
for
(
var
c
=
0
;
c
<
classes
.
length
;
c
++
)
if
(
!
contains
(
'
.
'
+
classes
[
c
],
selectorTextArr
))
selectorTextArr
.
push
(
'
.
'
+
classes
[
c
]);
}
// Extract CSS Rules
var
extractedCSSText
=
""
;
for
(
var
i
=
0
;
i
<
document
.
styleSheets
.
length
;
i
++
)
{
var
s
=
document
.
styleSheets
[
i
];
try
{
if
(
!
s
.
cssRules
)
continue
;
}
catch
(
e
)
{
if
(
e
.
name
!==
'
SecurityError
'
)
throw
e
;
// for Firefox
continue
;
}
var
cssRules
=
s
.
cssRules
;
for
(
var
r
=
0
;
r
<
cssRules
.
length
;
r
++
)
{
if
(
contains
(
cssRules
[
r
].
selectorText
,
selectorTextArr
))
extractedCSSText
+=
cssRules
[
r
].
cssText
;
}
}
return
extractedCSSText
;
function
contains
(
str
,
arr
)
{
return
arr
.
indexOf
(
str
)
===
-
1
?
false
:
true
;
}
}
function
append_css
(
cssText
,
element
)
{
var
styleElement
=
document
.
createElement
(
"
style
"
);
styleElement
.
setAttribute
(
"
type
"
,
"
text/css
"
);
styleElement
.
innerHTML
=
cssText
;
var
refNode
=
element
.
hasChildNodes
()
?
element
.
children
[
0
]
:
null
;
element
.
insertBefore
(
styleElement
,
refNode
);
}
}
/**
* convert svgString to image and export it
* @param {object} svgString - svgString
* @param {object} width - width of image
* @param {object} height - height of image
* @param {object} format - format to save image in
* @param {object} callback - callback function
*/
function
svg_string_to_image
(
svgString
,
width
,
height
,
format
,
callback
)
{
var
format
=
format
?
format
:
'
png
'
;
var
imgsrc
=
'
data:image/svg+xml;base64,
'
+
btoa
(
unescape
(
encodeURIComponent
(
svgString
)));
// Convert SVG string to data URL
var
canvas
=
document
.
createElement
(
"
canvas
"
);
var
context
=
canvas
.
getContext
(
"
2d
"
);
canvas
.
width
=
width
;
canvas
.
height
=
height
;
var
image
=
new
Image
();
image
.
onload
=
function
()
{
context
.
clearRect
(
0
,
0
,
width
,
height
);
context
.
drawImage
(
image
,
0
,
0
,
width
,
height
);
canvas
.
toBlob
(
function
(
blob
)
{
var
filesize
=
Math
.
round
(
blob
.
length
/
1024
)
+
'
KB
'
;
if
(
callback
)
callback
(
blob
,
filesize
);
});
};
image
.
src
=
imgsrc
;
}
Loading