-
Notifications
You must be signed in to change notification settings - Fork 120
/
graph.xsl
150 lines (129 loc) · 8.66 KB
/
graph.xsl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet [
<!ENTITY def "https://w3id.org/atomgraph/linkeddatahub/default#">
<!ENTITY ldh "https://w3id.org/atomgraph/linkeddatahub#">
<!ENTITY ac "https://w3id.org/atomgraph/client#">
<!ENTITY rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<!ENTITY ldt "https://www.w3.org/ns/ldt#">
]>
<xsl:stylesheet version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ixsl="http://saxonica.com/ns/interactiveXSLT"
xmlns:prop="http://saxonica.com/ns/html-property"
xmlns:xhtml="http://www.w3.org/1999/xhtml"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:map="http://www.w3.org/2005/xpath-functions/map"
xmlns:json="http://www.w3.org/2005/xpath-functions"
xmlns:array="http://www.w3.org/2005/xpath-functions/array"
xmlns:ac="∾"
xmlns:ldh="&ldh;"
xmlns:rdf="&rdf;"
xmlns:ldt="&ldt;"
xmlns:bs2="http://graphity.org/xsl/bootstrap/2.3.2"
extension-element-prefixes="ixsl"
exclude-result-prefixes="#all"
>
<xsl:key name="lines-by-start" match="svg:line" use="@data-id1"/>
<xsl:key name="lines-by-end" match="svg:line" use="@data-id2"/>
<xsl:variable name="highlight-color" select="'gold'" as="xs:string"/>
<xsl:variable name="highlighted-marker-id" select="'triangle-hl'" as="xs:string"/>
<!-- TEMPLATES -->
<xsl:template name="add-highlighted-marker">
<xsl:param name="id" as="xs:string"/>
<xsl:if test="not(svg:defs/svg:marker[@id = $id])">
<xsl:for-each select="svg:defs">
<xsl:result-document href="?." method="ixsl:append-content">
<svg:marker id="{$id}" viewBox="0 0 10 10" refX="10" refY="5" markerUnits="strokeWidth" markerWidth="8" markerHeight="6" orient="auto">
<svg:path d="M 0 0 L 10 5 L 0 10 z" fill="{$highlight-color}"/>
</svg:marker>
</xsl:result-document>
</xsl:for-each>
</xsl:if>
</xsl:template>
<!-- EVENT HANDLERS -->
<xsl:template match="svg:g[@class = 'subject']" mode="ixsl:onmouseover"> <!-- should be ixsl:onmouseenter but it's not supported by Saxon-JS 2.3 -->
<xsl:variable name="svg" select="ancestor::svg:svg" as="element()"/>
<!-- add highlighted <marker> if it doesn't exist yet -->
<xsl:for-each select="$svg">
<xsl:call-template name="add-highlighted-marker">
<xsl:with-param name="id" select="$highlighted-marker-id"/>
</xsl:call-template>
</xsl:for-each>
<!-- highlight this node -->
<ixsl:set-attribute name="stroke" select="$highlight-color" object="svg:circle"/>
<!-- highlight the lines going to/from this node and move to the end of the document (visually, move to front) -->
<xsl:for-each select="key('lines-by-start', @id, ixsl:page()) | key('lines-by-end', @id, ixsl:page())">
<ixsl:set-attribute name="stroke" select="$highlight-color"/>
<ixsl:set-attribute name="marker-end" select="'url(#' || $highlighted-marker-id || ')'"/>
<xsl:sequence select="ixsl:call(ancestor::svg:svg, 'appendChild', [ . ])[current-date() lt xs:date('2000-01-01')]"/>
</xsl:for-each>
<!-- move line end nodes to the end of the document (visually, move to front) -->
<xsl:for-each select="id(key('lines-by-start', @id, ixsl:page())/@data-id2, ixsl:page()) | id(key('lines-by-end', @id, ixsl:page())/@data-id1, ixsl:page())">
<ixsl:set-attribute name="stroke" select="$highlight-color" object="svg:circle"/>
<xsl:sequence select="ixsl:call($svg, 'appendChild', [ . ])[current-date() lt xs:date('2000-01-01')]"/>
</xsl:for-each>
<!-- move start node to the end of the document (visually, move to front) -->
<xsl:sequence select="ixsl:call($svg, 'appendChild', [ . ])[current-date() lt xs:date('2000-01-01')]"/>
</xsl:template>
<xsl:template match="svg:g[@class = 'subject']" mode="ixsl:onmouseout">
<!-- unhighlight this node -->
<ixsl:set-attribute name="stroke" select="'gray'" object="svg:circle"/>
<!-- unhighlight end nodes -->
<xsl:for-each select="id(key('lines-by-start', @id, ixsl:page())/@data-id2, ixsl:page()) | id(key('lines-by-end', @id, ixsl:page())/@data-id1, ixsl:page())">
<ixsl:set-attribute name="stroke" select="'gray'" object="svg:circle"/>
</xsl:for-each>
<!-- unhighlight the lines going to/from this node -->
<xsl:for-each select="key('lines-by-start', @id, ixsl:page()) | key('lines-by-end', @id, ixsl:page())">
<ixsl:set-attribute name="stroke" select="'gray'"/>
<ixsl:set-attribute name="marker-end" select="'url(#triangle)'"/>
</xsl:for-each>
</xsl:template>
<xsl:template match="svg:svg" mode="ixsl:onmousedown">
<xsl:if test="ixsl:get(ixsl:event(), 'target')/ancestor-or-self::svg:g[@class = 'subject']">
<xsl:variable name="selected-node" select="ixsl:get(ixsl:event(), 'target')/ancestor-or-self::svg:g[@class = 'subject']" as="element()"/>
<xsl:variable name="dom-x" select="ixsl:get(ixsl:event(), 'clientX')"/>
<xsl:variable name="dom-y" select="ixsl:get(ixsl:event(), 'clientY')"/>
<xsl:variable name="bound" select="ixsl:call($selected-node, 'getBoundingClientRect', [])"/>
<xsl:variable name="offset-x" select="ixsl:get($bound, 'width') div 2 - ($dom-x - ixsl:get($bound, 'x'))"/>
<xsl:variable name="offset-y" select="ixsl:get($bound, 'height') div 2 - ($dom-y - ixsl:get($bound, 'y'))"/>
<ixsl:set-property name="offset-x" select="$offset-x" object="ixsl:get(ixsl:window(), 'LinkedDataHub.graph')"/>
<ixsl:set-property name="offset-y" select="$offset-y" object="ixsl:get(ixsl:window(), 'LinkedDataHub.graph')"/>
<ixsl:set-property name="selected-node" select="$selected-node" object="ixsl:get(ixsl:window(), 'LinkedDataHub.graph')"/>
</xsl:if>
</xsl:template>
<xsl:template match="svg:svg" mode="ixsl:onmousemove">
<xsl:if test="ixsl:contains(ixsl:get(ixsl:window(), 'LinkedDataHub.graph'), 'selected-node')">
<xsl:sequence select="ixsl:call(ixsl:event(), 'preventDefault', [])"/>
<xsl:variable name="selected-node" select="ixsl:get(ixsl:window(), 'LinkedDataHub.graph.selected-node')" as="element()"/>
<xsl:variable name="offset-x" select="ixsl:get(ixsl:window(), 'LinkedDataHub.graph.offset-x')"/>
<xsl:variable name="offset-y" select="ixsl:get(ixsl:window(), 'LinkedDataHub.graph.offset-y')"/>
<!-- add the mouse offset within the element which was stored in onmousedown -->
<xsl:variable name="dom-x" select="ixsl:get(ixsl:event(), 'clientX') + $offset-x"/>
<xsl:variable name="dom-y" select="ixsl:get(ixsl:event(), 'clientY') + $offset-y"/>
<xsl:variable name="point" select="ldh:new('DOMPoint', [ $dom-x, $dom-y ])"/>
<xsl:variable name="ctm" select="ixsl:call(., 'getScreenCTM', [])"/>
<xsl:variable name="svg-point" select="ixsl:call($point, 'matrixTransform', [ ixsl:call($ctm, 'inverse', []) ])"/>
<xsl:variable name="svg-x" select="ixsl:get($svg-point, 'x')"/>
<xsl:variable name="svg-y" select="ixsl:get($svg-point, 'y')"/>
<xsl:variable name="transforms" select="ixsl:get($selected-node, 'transform.baseVal')"/>
<!-- the element must have existing @transform, otherwise we'll get DOMException -->
<xsl:variable name="transform" select="ixsl:call($transforms, 'getItem', [ 0 ])"/>
<xsl:sequence select="ixsl:call($transform, 'setTranslate', [ $svg-x, $svg-y ])"/>
<!-- move line ends together with the target node -->
<xsl:for-each select="key('lines-by-start', $selected-node/@id, ixsl:page())">
<ixsl:set-attribute name="x1" select="string($svg-x)"/>
<ixsl:set-attribute name="y1" select="string($svg-y)"/>
</xsl:for-each>
<xsl:for-each select="key('lines-by-end', $selected-node/@id, ixsl:page())">
<ixsl:set-attribute name="x2" select="string($svg-x)"/>
<ixsl:set-attribute name="y2" select="string($svg-y)"/>
</xsl:for-each>
</xsl:if>
</xsl:template>
<xsl:template match="svg:svg" mode="ixsl:onmouseup">
<xsl:if test="ixsl:contains(ixsl:get(ixsl:window(), 'LinkedDataHub.graph'), 'selected-node')">
<ixsl:remove-property name="selected-node" object="ixsl:get(ixsl:window(), 'LinkedDataHub.graph')"/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>