Skip to content

Commit fdef11c

Browse files
namedgraphclaude
andcommitted
Add zoom-to-fit, info panel, and filter panel to 3D graph view
- NodeClick writes to info-content panel (dl/dt/dd) instead of tooltip - Tooltip retained only for hover (position-aware) - Zoom-to-fit button and filter checkboxes wired via data-canvas-id - ldh:redisplay-graph reads per-canvas filter state; used by Init and Update - canvas-id param added to all ldh:UpdateForceGraph3D call sites - layout.xsl and view.xsl output info/filter/zoom UI inside canvas div Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent d7d3ff0 commit fdef11c

3 files changed

Lines changed: 127 additions & 33 deletions

File tree

src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/block/view.xsl

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1131,9 +1131,17 @@ exclude-result-prefixes="#all"
11311131
<xsl:param name="canvas-id" as="xs:string"/>
11321132

11331133
<div id="{$canvas-id}" class="graph-3d-canvas">
1134-
</div>
1135-
<div id="tooltip-{$canvas-id}" class="graph-3d-tooltip"
1136-
style="display:none;position:absolute;background:rgba(0,0,0,0.75);color:#fff;padding:4px 8px;border-radius:4px;pointer-events:none;font-size:12px;z-index:10;">
1134+
<div id="tooltip-{$canvas-id}" class="graph-3d-tooltip"/>
1135+
<div id="info-panel-{$canvas-id}" class="graph-3d-info-panel">
1136+
<div id="info-content-{$canvas-id}">Click a node to see details</div>
1137+
</div>
1138+
<div id="show-panel-{$canvas-id}" class="graph-3d-show-panel">
1139+
<label><input type="checkbox" id="show-stubs-{$canvas-id}" data-canvas-id="{$canvas-id}" class="graph-3d-filter" checked="checked"/> Resources without descriptions</label>
1140+
<label><input type="checkbox" id="show-literals-{$canvas-id}" data-canvas-id="{$canvas-id}" class="graph-3d-filter"/> Literals
1141+
<label class="sub-option"><input type="checkbox" id="show-locale-literals-{$canvas-id}" data-canvas-id="{$canvas-id}" class="graph-3d-filter" disabled="disabled"/> Matching locale only</label>
1142+
</label>
1143+
</div>
1144+
<button data-canvas-id="{$canvas-id}" class="graph-3d-zoom btn btn-small">Zoom to fit</button>
11371145
</div>
11381146
</xsl:template>
11391147

src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/client/graph3d.xsl

Lines changed: 103 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,8 @@ exclude-result-prefixes="#all"
3737
<xsl:variable name="rdf-doc" select="ixsl:get($graph-state, 'document')" as="document-node()"/>
3838
<xsl:variable name="description" select="key('resources', $node-id, $rdf-doc)"/>
3939

40-
<xsl:variable name="tooltip-id" select="'tooltip-' || $canvas-id" as="xs:string"/>
41-
<xsl:for-each select="id($tooltip-id, ixsl:page())">
42-
<ixsl:set-style name="display" select="'block'"/>
40+
<xsl:variable name="info-content-id" select="'info-content-' || $canvas-id" as="xs:string"/>
41+
<xsl:for-each select="id($info-content-id, ixsl:page())">
4342
<xsl:result-document href="?." method="ixsl:replace-content">
4443
<xsl:apply-templates select="if (exists($description)) then $description else $node-label" mode="ldh:graph3d-info">
4544
<xsl:with-param name="node-id" select="$node-id"/>
@@ -85,6 +84,7 @@ exclude-result-prefixes="#all"
8584
<xsl:with-param name="current-doc" select="$current-doc"/>
8685
<xsl:with-param name="graph-instance" select="$graph-instance"/>
8786
<xsl:with-param name="graph-state" select="$graph-state"/>
87+
<xsl:with-param name="canvas-id" select="$canvas-id"/>
8888
</xsl:call-template>
8989
</xsl:if>
9090
</xsl:when>
@@ -158,13 +158,81 @@ exclude-result-prefixes="#all"
158158
</xsl:for-each>
159159
</xsl:template>
160160

161+
<!-- ZOOM TO FIT -->
162+
163+
<xsl:template name="ldh:zoom-to-fit">
164+
<xsl:param name="graph-state" as="item()"/>
165+
<xsl:param name="zoom-transition-duration" select="1000" as="xs:integer"/>
166+
<xsl:param name="zoom-padding" select="20" as="xs:integer"/>
167+
168+
<xsl:variable name="graph-instance" select="ixsl:get($graph-state, 'instance')"/>
169+
<xsl:sequence select="ixsl:call($graph-instance, 'zoomToFit', [ $zoom-transition-duration, $zoom-padding ])[current-date() lt xs:date('2000-01-01')]"/>
170+
</xsl:template>
171+
172+
<xsl:template match="button[contains-token(@class, 'graph-3d-zoom')]" mode="ixsl:onclick">
173+
<xsl:variable name="canvas-id" select="@data-canvas-id" as="xs:string"/>
174+
<xsl:variable name="graph-state" select="ixsl:get(ixsl:get(ixsl:window(), 'LinkedDataHub.graphs'), $canvas-id)"/>
175+
<xsl:call-template name="ldh:zoom-to-fit">
176+
<xsl:with-param name="graph-state" select="$graph-state"/>
177+
</xsl:call-template>
178+
</xsl:template>
179+
180+
<!-- FILTER PANEL -->
181+
182+
<!-- Re-render graph data using the current show-panel filter state -->
183+
<xsl:template name="ldh:redisplay-graph">
184+
<xsl:param name="canvas-id" as="xs:string"/>
185+
<xsl:param name="graph-state" as="item()"/>
186+
<xsl:param name="graph-instance" as="item()"/>
187+
188+
<xsl:variable name="show-stubs-cb" select="id('show-stubs-' || $canvas-id, ixsl:page())"/>
189+
<xsl:variable name="show-stubs" select="if (exists($show-stubs-cb)) then xs:boolean(ixsl:get($show-stubs-cb, 'checked')) else true()" as="xs:boolean"/>
190+
191+
<xsl:variable name="show-literals-cb" select="id('show-literals-' || $canvas-id, ixsl:page())"/>
192+
<xsl:variable name="show-literals" select="if (exists($show-literals-cb)) then xs:boolean(ixsl:get($show-literals-cb, 'checked')) else false()" as="xs:boolean"/>
193+
194+
<xsl:variable name="locale-cb" select="id('show-locale-literals-' || $canvas-id, ixsl:page())"/>
195+
<xsl:variable name="locale-filter" select="if ($show-literals and exists($locale-cb) and xs:boolean(ixsl:get($locale-cb, 'checked'))) then tokenize($ac:lang, '-')[1] else ()" as="xs:string?"/>
196+
197+
<xsl:variable name="rdf-doc" select="ixsl:get($graph-state, 'document')" as="document-node()"/>
198+
<xsl:variable name="graph-data" as="item()">
199+
<xsl:apply-templates select="$rdf-doc" mode="ldh:ForceGraph3D-convert-data">
200+
<xsl:with-param name="show-stubs" select="$show-stubs" tunnel="yes"/>
201+
<xsl:with-param name="show-literals" select="$show-literals" tunnel="yes"/>
202+
<xsl:with-param name="locale-filter" select="$locale-filter" tunnel="yes"/>
203+
</xsl:apply-templates>
204+
</xsl:variable>
205+
<xsl:sequence select="ixsl:call($graph-instance, 'graphData', [$graph-data], map{'convert-args': false()})[current-date() lt xs:date('2000-01-01')]"/>
206+
</xsl:template>
207+
208+
<xsl:template match="input[contains-token(@class, 'graph-3d-filter')]" mode="ixsl:onchange">
209+
<xsl:variable name="canvas-id" select="@data-canvas-id" as="xs:string"/>
210+
211+
<!-- when literals is unchecked, disable the locale sub-option -->
212+
<xsl:if test="@id = 'show-literals-' || $canvas-id">
213+
<xsl:variable name="locale-cb" select="id('show-locale-literals-' || $canvas-id, ixsl:page())"/>
214+
<xsl:if test="exists($locale-cb)">
215+
<ixsl:set-property name="disabled" select="not(ixsl:get(., 'checked'))" object="$locale-cb"/>
216+
</xsl:if>
217+
</xsl:if>
218+
219+
<xsl:variable name="graph-state" select="ixsl:get(ixsl:get(ixsl:window(), 'LinkedDataHub.graphs'), $canvas-id)"/>
220+
<xsl:variable name="graph-instance" select="ixsl:get($graph-state, 'instance')"/>
221+
<xsl:call-template name="ldh:redisplay-graph">
222+
<xsl:with-param name="canvas-id" select="$canvas-id"/>
223+
<xsl:with-param name="graph-state" select="$graph-state"/>
224+
<xsl:with-param name="graph-instance" select="$graph-instance"/>
225+
</xsl:call-template>
226+
</xsl:template>
227+
161228
<!-- UPDATE -->
162229

163230
<xsl:template name="ldh:UpdateForceGraph3D">
164231
<xsl:param name="new-descriptions" as="document-node()"/>
165232
<xsl:param name="current-doc" as="document-node()"/>
166233
<xsl:param name="graph-instance" as="item()"/>
167234
<xsl:param name="graph-state" as="item()"/>
235+
<xsl:param name="canvas-id" as="xs:string"/>
168236

169237
<xsl:variable name="merged-doc" as="document-node()">
170238
<xsl:document>
@@ -176,13 +244,11 @@ exclude-result-prefixes="#all"
176244

177245
<ixsl:set-property name="document" select="$merged-doc" object="$graph-state"/>
178246

179-
<xsl:variable name="graph-data" as="item()">
180-
<xsl:apply-templates select="$merged-doc" mode="ldh:ForceGraph3D-convert-data">
181-
<xsl:with-param name="show-stubs" select="true()" tunnel="yes"/>
182-
<xsl:with-param name="show-literals" select="false()" tunnel="yes"/>
183-
</xsl:apply-templates>
184-
</xsl:variable>
185-
<xsl:sequence select="ixsl:call($graph-instance, 'graphData', [$graph-data], map{'convert-args': false()})[current-date() lt xs:date('2000-01-01')]"/>
247+
<xsl:call-template name="ldh:redisplay-graph">
248+
<xsl:with-param name="canvas-id" select="$canvas-id"/>
249+
<xsl:with-param name="graph-state" select="$graph-state"/>
250+
<xsl:with-param name="graph-instance" select="$graph-instance"/>
251+
</xsl:call-template>
186252
</xsl:template>
187253

188254
<!-- HTTP RESPONSE HANDLER -->
@@ -213,6 +279,7 @@ exclude-result-prefixes="#all"
213279
<xsl:with-param name="current-doc" select="$current-doc"/>
214280
<xsl:with-param name="graph-instance" select="$graph-instance"/>
215281
<xsl:with-param name="graph-state" select="$graph-state"/>
282+
<xsl:with-param name="canvas-id" select="$canvas-id"/>
216283
</xsl:call-template>
217284
</xsl:for-each>
218285
</xsl:function>
@@ -238,21 +305,32 @@ exclude-result-prefixes="#all"
238305
<xsl:template match="rdf:Description" mode="ldh:graph3d-info">
239306
<xsl:param name="node-id" as="xs:string"/>
240307
<xsl:param name="node-label" as="xs:string"/>
241-
<strong><xsl:value-of select="$node-label"/></strong>
242-
<xsl:if test="starts-with($node-id, 'http://') or starts-with($node-id, 'https://')">
243-
<br/>
244-
<a href="{$node-id}" target="_blank"><xsl:value-of select="$node-id"/></a>
245-
</xsl:if>
246-
<xsl:if test="rdf:type/@rdf:resource">
247-
<br/>
248-
<xsl:value-of select="tokenize(rdf:type[1]/@rdf:resource, '[/#]')[last()]"/>
249-
</xsl:if>
308+
<h4><xsl:value-of select="$node-label"/></h4>
309+
<dl>
310+
<dt>ID</dt>
311+
<dd>
312+
<xsl:choose>
313+
<xsl:when test="starts-with($node-id, 'http://') or starts-with($node-id, 'https://')">
314+
<a href="{$node-id}" target="_blank"><xsl:value-of select="$node-id"/></a>
315+
</xsl:when>
316+
<xsl:otherwise><xsl:value-of select="$node-id"/></xsl:otherwise>
317+
</xsl:choose>
318+
</dd>
319+
<xsl:if test="rdf:type">
320+
<dt>Types</dt>
321+
<dd><xsl:value-of select="distinct-values(rdf:type/tokenize(@rdf:resource, '[/#]')[last()])" separator=", "/></dd>
322+
</xsl:if>
323+
</dl>
250324
</xsl:template>
251325

252326
<xsl:template match="xs:string" mode="ldh:graph3d-info">
253327
<xsl:param name="node-id" as="xs:string"/>
254328
<xsl:param name="node-label" as="xs:string"/>
255-
<span><xsl:value-of select="$node-label"/></span>
329+
<h4><xsl:value-of select="."/></h4>
330+
<dl>
331+
<dt>ID</dt>
332+
<dd><xsl:value-of select="$node-id"/></dd>
333+
</dl>
256334
</xsl:template>
257335

258336
<!-- DOCUMENT-MODE GRAPH INIT (called from ldh:rdf-document-response) -->
@@ -293,13 +371,11 @@ exclude-result-prefixes="#all"
293371
<ixsl:set-property name="{$canvas-id}" select="$graph-state" object="$graphs"/>
294372

295373
<xsl:variable name="graph-instance" select="ixsl:get($graph-state, 'instance')"/>
296-
<xsl:variable name="graph-data" as="item()">
297-
<xsl:apply-templates select="$rdf-doc" mode="ldh:ForceGraph3D-convert-data">
298-
<xsl:with-param name="show-stubs" select="true()" tunnel="yes"/>
299-
<xsl:with-param name="show-literals" select="false()" tunnel="yes"/>
300-
</xsl:apply-templates>
301-
</xsl:variable>
302-
<xsl:sequence select="ixsl:call($graph-instance, 'graphData', [$graph-data], map{'convert-args': false()})[current-date() lt xs:date('2000-01-01')]"/>
374+
<xsl:call-template name="ldh:redisplay-graph">
375+
<xsl:with-param name="canvas-id" select="$canvas-id"/>
376+
<xsl:with-param name="graph-state" select="$graph-state"/>
377+
<xsl:with-param name="graph-instance" select="$graph-instance"/>
378+
</xsl:call-template>
303379
</xsl:template>
304380

305381
</xsl:stylesheet>

src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/layout.xsl

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -936,9 +936,19 @@ exclude-result-prefixes="#all">
936936
</xsl:when>
937937
<xsl:when test="$ac:mode = '&ac;GraphMode'">
938938
<xsl:variable name="canvas-id" select="generate-id() || '-graph-canvas'" as="xs:string"/>
939-
<div id="{$canvas-id}" class="graph-3d-canvas"/>
940-
<div id="tooltip-{$canvas-id}" class="graph-3d-tooltip"
941-
style="display:none;position:absolute;background:rgba(0,0,0,0.75);color:#fff;padding:4px 8px;border-radius:4px;pointer-events:none;font-size:12px;z-index:10;"/>
939+
<div id="{$canvas-id}" class="graph-3d-canvas">
940+
<div id="tooltip-{$canvas-id}" class="graph-3d-tooltip"/>
941+
<div id="info-panel-{$canvas-id}" class="graph-3d-info-panel">
942+
<div id="info-content-{$canvas-id}">Click a node to see details</div>
943+
</div>
944+
<div id="show-panel-{$canvas-id}" class="graph-3d-show-panel">
945+
<label><input type="checkbox" id="show-stubs-{$canvas-id}" data-canvas-id="{$canvas-id}" class="graph-3d-filter" checked="checked"/> Resources without descriptions</label>
946+
<label><input type="checkbox" id="show-literals-{$canvas-id}" data-canvas-id="{$canvas-id}" class="graph-3d-filter"/> Literals
947+
<label class="sub-option"><input type="checkbox" id="show-locale-literals-{$canvas-id}" data-canvas-id="{$canvas-id}" class="graph-3d-filter" disabled="disabled"/> Matching locale only</label>
948+
</label>
949+
</div>
950+
<button data-canvas-id="{$canvas-id}" class="graph-3d-zoom btn btn-small">Zoom to fit</button>
951+
</div>
942952
</xsl:when>
943953
<xsl:otherwise>
944954
<xsl:apply-templates select="." mode="bs2:Row">

0 commit comments

Comments
 (0)