@@ -61,68 +61,81 @@ LIMIT 10
6161 <xsl : template name =" ldh:LeftSidebar" >
6262 <xsl : param name =" base" select =" ldt:base()" as =" xs:anyURI" />
6363
64- <h2 class =" nav-header btn" >
65- <xsl : apply-templates select =" key('resources', 'document-tree', document(resolve-uri('static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/translations.rdf', $ac:contextUri)))" mode =" ac:label" />
66- </h2 >
67-
68- <ul class =" well well-small nav nav-list" >
69- <!-- TO-DO: generalize -->
70- <li >
71- <button class =" btn btn-small btn-expand-tree" ></button >
72- <a href =" {$base}" class =" btn-logo btn-container" >
73- <xsl : apply-templates select =" key('resources', 'root', document(resolve-uri('static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/translations.rdf', $ac:contextUri)))" mode =" ac:label" />
74- </a >
75- </li >
76- <!-- non-expandable containers (not based on ldh:SelectChildren) -->
77- <!--
78- <li>
79- <a href="{$base}geo/" class="btn-logo btn-geo">
80- <xsl:apply-templates select="key('resources', 'geo', document(resolve-uri('static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/translations.rdf', $ac:contextUri)))" mode="ac:label"/>
81- </a>
82- </li>
83- <li>
84- <a href="{$base}latest/" class="btn-logo btn-latest">
85- <xsl:apply-templates select="key('resources', 'latest', document(resolve-uri('static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/translations.rdf', $ac:contextUri)))" mode="ac:label"/>
86- </a>
87- </li>
88- -->
89- </ul >
90-
91- <h2 class =" nav-header btn" >
92- <xsl : apply-templates select =" key('resources', 'classes', document(resolve-uri('static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/translations.rdf', $ac:contextUri)))" mode =" ac:label" />
93- </h2 >
94-
95- <ul class =" well well-small nav nav-list" id =" class-list" >
96- <!-- class list will be loaded dynamically -->
97- </ul >
64+ <!-- Document tree container -->
65+ <div id =" document-tree" >
66+ <h2 class =" nav-header btn" >
67+ <xsl : apply-templates select =" key('resources', 'document-tree', document(resolve-uri('static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/translations.rdf', $ac:contextUri)))" mode =" ac:label" />
68+ </h2 >
69+
70+ <ul class =" well well-small nav nav-list" >
71+ <!-- TO-DO: generalize -->
72+ <li >
73+ <button class =" btn btn-small btn-expand-tree" ></button >
74+ <a href =" {$base}" class =" btn-logo btn-container" >
75+ <xsl : apply-templates select =" key('resources', 'root', document(resolve-uri('static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/translations.rdf', $ac:contextUri)))" mode =" ac:label" />
76+ </a >
77+ </li >
78+ <!-- non-expandable containers (not based on ldh:SelectChildren) -->
79+ <!--
80+ <li>
81+ <a href="{$base}geo/" class="btn-logo btn-geo">
82+ <xsl:apply-templates select="key('resources', 'geo', document(resolve-uri('static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/translations.rdf', $ac:contextUri)))" mode="ac:label"/>
83+ </a>
84+ </li>
85+ <li>
86+ <a href="{$base}latest/" class="btn-logo btn-latest">
87+ <xsl:apply-templates select="key('resources', 'latest', document(resolve-uri('static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/translations.rdf', $ac:contextUri)))" mode="ac:label"/>
88+ </a>
89+ </li>
90+ -->
91+ </ul >
92+ </div >
93+
94+ <!-- Class list container -->
95+ <div id =" class-list-container" >
96+ <h2 class =" nav-header btn" >
97+ <xsl : apply-templates select =" key('resources', 'classes', document(resolve-uri('static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2/translations.rdf', $ac:contextUri)))" mode =" ac:label" />
98+ </h2 >
99+
100+ <ul class =" well well-small nav nav-list" id =" class-list" >
101+ <!-- class list will be loaded dynamically -->
102+ </ul >
103+ </div >
98104 </xsl : template >
99105
100106 <xsl : template name =" ldh:DocTreeActivateHref" >
101107 <xsl : context-item as =" element()" use =" required" /> <!-- document tree container -->
102108 <xsl : param name =" href" as =" xs:anyURI" />
103-
109+
110+ <!-- Strip query params from href to ensure consistent matching -->
111+ <xsl : variable name =" target-uri" select =" ac:document-uri($href)" as =" xs:anyURI" />
112+
104113 <xsl : message >
105- ldh:DocTreeActivateHref $href: <xsl : value-of select =" $href" />
114+ ldh:DocTreeActivateHref $href: <xsl : value-of select =" $href" />, stripped: < xsl : value-of select = " $target-uri " />
106115 </xsl : message >
107116
108117 <!-- make the previously active list items inactive -->
109118 <xsl : for-each select =" .//li[contains-token(@class, 'active')]" >
110119 <xsl : sequence select =" ixsl:call(ixsl:get(., 'classList'), 'toggle', [ 'active', false() ])[current-date() lt xs:date('2000-01-01')]" />
111120 </xsl : for-each >
112- <xsl : for-each select =" .//li[a/@href = $href]" >
121+ <!-- Find li elements whose href (without query params) matches target href (without query params) -->
122+ <xsl : for-each select =" .//li[a[ac:document-uri(xs:anyURI(@href)) = $target-uri]]" >
113123 <!-- mark the new list item as active -->
114124 <xsl : sequence select =" ixsl:call(ixsl:get(., 'classList'), 'toggle', [ 'active', true() ])[current-date() lt xs:date('2000-01-01')]" />
115125 </xsl : for-each >
116126 </xsl : template >
117127
118- <!-- Update both left-sidebar and class-list after navigation -->
128+ <!-- Update both document-tree and class-list after navigation -->
119129 <xsl : template name =" ldh:NavigationUpdate" >
120130 <xsl : param name =" href" as =" xs:anyURI" />
121131
122132 <!-- activate the current URL in the document tree -->
123- <xsl : for-each select =" id('left-sidebar', ixsl:page())" >
124- <xsl : call-template name =" ldh:DocTreeActivateHref" >
125- <xsl : with-param name =" href" select =" $href" />
133+ <xsl : for-each select =" id('document-tree', ixsl:page())" >
134+ <xsl : variable name =" href-string" select =" string($href)" as =" xs:string" />
135+ <xsl : variable name =" target" select =" xs:anyURI(if (contains($href-string, '?')) then substring-before($href-string, '?') else $href-string)" as =" xs:anyURI" />
136+ <xsl : call-template name =" ldh:DocTreeExpandPathAndActivate" >
137+ <xsl : with-param name =" container" select =" ." />
138+ <xsl : with-param name =" target" select =" $target" />
126139 </xsl : call-template >
127140 </xsl : for-each >
128141
@@ -135,6 +148,27 @@ LIMIT 10
135148 </xsl : for-each >
136149 </xsl : template >
137150
151+ <xsl : template name =" ldh:DocTreeExpandPathAndActivate" >
152+ <xsl : param name =" container" as =" element()" /> <!-- document-tree element -->
153+ <xsl : param name =" target" as =" xs:anyURI" /> <!-- target document URI (already stripped of query params) -->
154+
155+ <xsl : message >ldh:DocTreeExpandPathAndActivate - starting descent for target: <xsl : value-of select =" $target" /></xsl : message >
156+
157+ <!-- Find the root <li> element (first top-level li in the tree) -->
158+ <xsl : variable name =" root-li" select =" $container/ul/li[1]" as =" element()?" />
159+
160+ <xsl : choose >
161+ <xsl : when test =" $root-li" >
162+ <xsl : message >ldh:DocTreeExpandPathAndActivate - found root: <xsl : value-of select =" $root-li/a/@href" /></xsl : message >
163+ <!-- Start recursive descent from root -->
164+ <xsl : sequence select =" ldh:doctree-descend($root-li, $target, $container)[current-date() lt xs:date('2000-01-01')]" />
165+ </xsl : when >
166+ <xsl : otherwise >
167+ <xsl : message >ldh:DocTreeExpandPathAndActivate - no root found in tree</xsl : message >
168+ </xsl : otherwise >
169+ </xsl : choose >
170+ </xsl : template >
171+
138172 <xsl : template name =" ldh:DocTreeResourceLoad" >
139173 <xsl : param name =" container" as =" element()" />
140174 <xsl : param name =" uri" as =" xs:anyURI" />
@@ -223,15 +257,15 @@ LIMIT 10
223257 </xsl : if >
224258 </xsl : template >
225259
226- <xsl : template match =" div[@id = 'left-sidebar ']//li/a[@href]" mode =" ixsl:onclick" priority =" 1" >
260+ <xsl : template match =" div[@id = 'document-tree ']//li/a[@href]" mode =" ixsl:onclick" priority =" 1" >
227261 <xsl : variable name =" href" select =" @href" as =" xs:anyURI" />
228-
229- <xsl : for-each select =" ancestor::div[@id = 'left-sidebar ']" >
262+
263+ <xsl : for-each select =" ancestor::div[@id = 'document-tree ']" >
230264 <xsl : call-template name =" ldh:DocTreeActivateHref" >
231265 <xsl : with-param name =" href" select =" $href" />
232266 </xsl : call-template >
233267 </xsl : for-each >
234-
268+
235269 <xsl : next-match />
236270 </xsl : template >
237271
@@ -387,6 +421,164 @@ LIMIT 10
387421 <xsl : sequence select =" $context" />
388422 </xsl : function >
389423
424+ <!-- Recursive descent function: expands path from current-li down to target-uri -->
425+ <xsl : function name =" ldh:doctree-descend" as =" map(*)" ixsl : updating =" yes" >
426+ <xsl : param name =" current-li" as =" element()" /> <!-- the <li> element we're currently at -->
427+ <xsl : param name =" target-uri" as =" xs:anyURI" /> <!-- the document URI we want to reach -->
428+ <xsl : param name =" tree-container" as =" element()" /> <!-- the document-tree element -->
429+
430+ <xsl : variable name =" current-href-full" select =" xs:anyURI($current-li/a/@href)" as =" xs:anyURI" />
431+ <!-- Strip query parameters for comparison -->
432+ <xsl : variable name =" current-href" select =" ac:document-uri($current-href-full)" as =" xs:anyURI" />
433+
434+ <xsl : message >ldh:doctree-descend - current: <xsl : value-of select =" $current-href" />, target: <xsl : value-of select =" $target-uri" /></xsl : message >
435+
436+ <xsl : choose >
437+ <!-- Case 1: We've reached the target - activate it -->
438+ <xsl : when test =" $current-href = $target-uri" >
439+ <xsl : message >ldh:doctree-descend - reached target, activating</xsl : message >
440+ <xsl : for-each select =" $tree-container" >
441+ <xsl : call-template name =" ldh:DocTreeActivateHref" >
442+ <xsl : with-param name =" href" select =" $target-uri" />
443+ </xsl : call-template >
444+ </xsl : for-each >
445+ <xsl : sequence select =" map{}" />
446+ </xsl : when >
447+
448+ <!-- Case 2: Target URI starts with current href - need to descend further -->
449+ <xsl : when test =" starts-with(string($target-uri), string($current-href))" >
450+ <xsl : variable name =" expand-button" select =" $current-li/button[contains-token(@class, 'btn-expand-tree')]" as =" element()?" />
451+
452+ <xsl : choose >
453+ <!-- Case 2a: Has expand button and not expanded yet - expand and load children -->
454+ <xsl : when test =" $expand-button and not($current-li/ul)" >
455+ <xsl : message >ldh:doctree-descend - expanding: <xsl : value-of select =" $current-href" /></xsl : message >
456+
457+ <!-- Create <ul> for children -->
458+ <xsl : for-each select =" $current-li" >
459+ <xsl : result-document href =" ?." method =" ixsl:append-content" >
460+ <ul class =" well well-small nav nav-list" ></ul >
461+ </xsl : result-document >
462+ </xsl : for-each >
463+
464+ <!-- Toggle button class -->
465+ <xsl : for-each select =" $expand-button" >
466+ <xsl : sequence select =" ixsl:call(ixsl:get(., 'classList'), 'toggle', [ 'btn-expand-tree', false() ])[current-date() lt xs:date('2000-01-01')]" />
467+ <xsl : sequence select =" ixsl:call(ixsl:get(., 'classList'), 'toggle', [ 'btn-expanded-tree', true() ])[current-date() lt xs:date('2000-01-01')]" />
468+ </xsl : for-each >
469+
470+ <!-- Load children and continue descent after loading -->
471+ <!-- Build query to load children (inline from ldh:DocTreeResourceLoad) -->
472+ <xsl : variable name =" select-string" select =" key('resources', '&ldh; SelectChildren', document(ac:document-uri('&ldh; ')))/sp:text" as =" xs:string" />
473+ <xsl : variable name =" select-string" select =" replace($select-string, '$this', '< ' || $current-href || '> ', 'q')" as =" xs:string" />
474+ <xsl : variable name =" select-json" as =" item()" >
475+ <xsl : variable name =" select-builder" select =" ixsl:call(ixsl:get(ixsl:get(ixsl:window(), 'SPARQLBuilder'), 'SelectBuilder'), 'fromString', [ $select-string ])" />
476+ <xsl : sequence select =" ixsl:call($select-builder, 'build', [])" />
477+ </xsl : variable >
478+ <xsl : variable name =" select-json-string" select =" ixsl:call(ixsl:get(ixsl:window(), 'JSON'), 'stringify', [ $select-json ])" as =" xs:string" />
479+ <xsl : variable name =" select-xml" as =" document-node()" >
480+ <xsl : document >
481+ <xsl : apply-templates select =" json-to-xml($select-json-string)" mode =" ldh:replace-variables" >
482+ <xsl : with-param name =" var-names" select =" ('child')" tunnel =" yes" />
483+ </xsl : apply-templates >
484+ </xsl : document >
485+ </xsl : variable >
486+
487+ <!-- Wrap SELECT into a DESCRIBE -->
488+ <xsl : variable name =" query-xml" as =" element()" >
489+ <xsl : apply-templates select =" $select-xml" mode =" ldh:wrap-describe" />
490+ </xsl : variable >
491+ <xsl : variable name =" query-json-string" select =" xml-to-json($query-xml)" as =" xs:string" />
492+ <xsl : variable name =" query-json" select =" ixsl:call(ixsl:get(ixsl:window(), 'JSON'), 'parse', [ $query-json-string ])" />
493+ <xsl : variable name =" query-string" select =" ixsl:call(ixsl:call(ixsl:get(ixsl:get(ixsl:window(), 'SPARQLBuilder'), 'SelectBuilder'), 'fromQuery', [ $query-json ]), 'toString', [])" as =" xs:string" />
494+ <xsl : variable name =" results-uri" select =" ac:build-uri(sd:endpoint(), map{ 'query': $query-string })" as =" xs:anyURI" />
495+ <xsl : variable name =" request-uri" select =" ldh:href($results-uri, map{})" as =" xs:anyURI" />
496+ <xsl : variable name =" request" select =" map{ 'method': 'GET', 'href': $request-uri, 'headers': map{ 'Accept': 'application/rdf+xml' } }" as =" map(*)" />
497+
498+ <xsl : variable name =" load-context" as =" map(*)" select ="
499+ map{
500+ 'request': $request,
501+ 'container': $current-li/ul,
502+ 'uri': $current-href
503+ }" />
504+
505+ <ixsl : promise select =" ixsl:http-request($load-context('request')) =>
506+ ixsl:then(ldh:rethread-response($load-context, ?)) =>
507+ ixsl:then(ldh:handle-response#1) =>
508+ ixsl:then(ldh:left-sidebar-resource-response#1) =>
509+ ixsl:then(ldh:doctree-descend-after-load(?, $current-li, $target-uri, $tree-container))" />
510+ <xsl : sequence select =" map{}" />
511+ </xsl : when >
512+
513+ <!-- Case 2b: Already expanded - find next child to descend into -->
514+ <xsl : when test =" $current-li/ul/li" >
515+ <xsl : message >ldh:doctree-descend - already expanded, finding next child</xsl : message >
516+
517+ <!-- Find which child's href (without query params) is a prefix of target-uri -->
518+ <xsl : variable name =" next-li" select =" $current-li/ul/li[starts-with(string($target-uri), string(ac:document-uri(xs:anyURI(a/@href))))][1]" as =" element()?" />
519+
520+ <xsl : choose >
521+ <xsl : when test =" $next-li" >
522+ <xsl : message >ldh:doctree-descend - descending to: <xsl : value-of select =" $next-li/a/@href" /></xsl : message >
523+ <xsl : sequence select =" ldh:doctree-descend($next-li, $target-uri, $tree-container)" />
524+ </xsl : when >
525+ <xsl : otherwise >
526+ <xsl : message >ldh:doctree-descend - no matching child found, activating target</xsl : message >
527+ <xsl : for-each select =" $tree-container" >
528+ <xsl : call-template name =" ldh:DocTreeActivateHref" >
529+ <xsl : with-param name =" href" select =" $target-uri" />
530+ </xsl : call-template >
531+ </xsl : for-each >
532+ <xsl : sequence select =" map{}" />
533+ </xsl : otherwise >
534+ </xsl : choose >
535+ </xsl : when >
536+
537+ <!-- Case 2c: Has expand button but <ul> exists and is empty (loading in progress) -->
538+ <xsl : otherwise >
539+ <xsl : message >ldh:doctree-descend - waiting for children to load</xsl : message >
540+ <xsl : sequence select =" map{}" />
541+ </xsl : otherwise >
542+ </xsl : choose >
543+ </xsl : when >
544+
545+ <!-- Case 3: Target is not under this branch -->
546+ <xsl : otherwise >
547+ <xsl : message >ldh:doctree-descend - target not under this branch</xsl : message >
548+ <xsl : sequence select =" map{}" />
549+ </xsl : otherwise >
550+ </xsl : choose >
551+ </xsl : function >
552+
553+ <!-- Helper to continue descent after children are loaded -->
554+ <xsl : function name =" ldh:doctree-descend-after-load" as =" map(*)" ixsl : updating =" yes" >
555+ <xsl : param name =" load-context" as =" map(*)" /> <!-- context from loading -->
556+ <xsl : param name =" current-li" as =" element()" />
557+ <xsl : param name =" target-uri" as =" xs:anyURI" />
558+ <xsl : param name =" tree-container" as =" element()" />
559+
560+ <xsl : message >ldh:doctree-descend-after-load - children loaded for: <xsl : value-of select =" $current-li/a/@href" /></xsl : message >
561+
562+ <!-- Find which child's href (without query params) is a prefix of target-uri -->
563+ <xsl : variable name =" next-li" select =" $current-li/ul/li[starts-with(string($target-uri), string(ac:document-uri(xs:anyURI(a/@href))))][1]" as =" element()?" />
564+
565+ <xsl : choose >
566+ <xsl : when test =" $next-li" >
567+ <xsl : message >ldh:doctree-descend-after-load - descending to: <xsl : value-of select =" $next-li/a/@href" /></xsl : message >
568+ <xsl : sequence select =" ldh:doctree-descend($next-li, $target-uri, $tree-container)" />
569+ </xsl : when >
570+ <xsl : otherwise >
571+ <xsl : message >ldh:doctree-descend-after-load - no matching child, activating target</xsl : message >
572+ <xsl : for-each select =" $tree-container" >
573+ <xsl : call-template name =" ldh:DocTreeActivateHref" >
574+ <xsl : with-param name =" href" select =" $target-uri" />
575+ </xsl : call-template >
576+ </xsl : for-each >
577+ <xsl : sequence select =" $load-context" />
578+ </xsl : otherwise >
579+ </xsl : choose >
580+ </xsl : function >
581+
390582 <xsl : function name =" ldh:left-sidebar-resource-response" as =" map(*)" ixsl : updating =" yes" >
391583 <xsl : param name =" context" as =" map(*)" />
392584 <xsl : variable name =" response" select =" $context('response')" as =" map(*)" />
0 commit comments