Holger Knublauch

Tree selection working

...@@ -580,9 +580,34 @@ app:ClassTreeDataProvider ...@@ -580,9 +580,34 @@ app:ClassTreeDataProvider
580 rdfs:label "Class tree data provider"^^xsd:string ; 580 rdfs:label "Class tree data provider"^^xsd:string ;
581 arg:treeChildrenTemplate 581 arg:treeChildrenTemplate
582 app:ClassTreeChildren ; 582 app:ClassTreeChildren ;
583 + arg:treePathTemplate
584 + app:ClassTreePath ;
583 arg:treeRootsTemplate 585 arg:treeRootsTemplate
584 app:ClassTreeRoots . 586 app:ClassTreeRoots .
585 587
588 +app:ClassTreePath
589 + rdf:type spin:SelectTemplate ;
590 + rdfs:label "Class tree path"^^xsd:string ;
591 + rdfs:subClassOf app:TreePathTemplates ;
592 + spin:body
593 + [ rdf:type sp:Select ;
594 + sp:resultVariables ([ sp:varName "path"^^xsd:string
595 + ]) ;
596 + sp:where ([ rdf:type sp:Bind ;
597 + sp:expression
598 + [ rdf:type spif:shortestObjectsPath ;
599 + sp:arg1 [ sp:varName "node"^^xsd:string
600 + ] ;
601 + sp:arg2 rdfs:subClassOf ;
602 + sp:arg3 [ sp:varName "root"^^xsd:string
603 + ]
604 + ] ;
605 + sp:variable
606 + [ sp:varName "path"^^xsd:string
607 + ]
608 + ])
609 + ] .
610 +
586 app:ClassTreeRoots 611 app:ClassTreeRoots
587 rdf:type spin:SelectTemplate ; 612 rdf:type spin:SelectTemplate ;
588 rdfs:label "Class tree roots"^^xsd:string ; 613 rdfs:label "Class tree roots"^^xsd:string ;
...@@ -860,6 +885,7 @@ app:CustomEditForm ...@@ -860,6 +885,7 @@ app:CustomEditForm
860 ] ; 885 ] ;
861 ui:child 886 ui:child
862 [ rdf:type html:Form ; 887 [ rdf:type html:Form ;
888 + html:autocomplete "off"^^xsd:string ;
863 html:class "appForm ui-layout-content"^^xsd:string ; 889 html:class "appForm ui-layout-content"^^xsd:string ;
864 html:id [ sp:varName "fid"^^xsd:string 890 html:id [ sp:varName "fid"^^xsd:string
865 ] ; 891 ] ;
...@@ -3973,6 +3999,7 @@ app:SearchForm ...@@ -3973,6 +3999,7 @@ app:SearchForm
3973 ] ; 3999 ] ;
3974 ui:child 4000 ui:child
3975 [ rdf:type html:Form ; 4001 [ rdf:type html:Form ;
4002 + html:autocomplete "off"^^xsd:string ;
3976 html:class 4003 html:class
3977 [ rdf:type ui:concat ; 4004 [ rdf:type ui:concat ;
3978 sp:arg1 "appForm ui-layout-content "^^xsd:string ; 4005 sp:arg1 "appForm ui-layout-content "^^xsd:string ;
...@@ -5481,7 +5508,9 @@ app:TreeDataProvider ...@@ -5481,7 +5508,9 @@ app:TreeDataProvider
5481 rdf:type ui:NodeClass ; 5508 rdf:type ui:NodeClass ;
5482 rdfs:comment """Instances of this class are used as server callbacks to drive an app:Tree. 5509 rdfs:comment """Instances of this class are used as server callbacks to drive an app:Tree.
5483 5510
5484 -A TreeDataProvider is backed by two SELECT queries - one to get the roots, and one to get the children of a given node. Optionally, a root resource can be supplied to overload the default root(s)."""^^xsd:string ; 5511 +A TreeDataProvider is backed by two SELECT queries - one to get the roots, and one to get the children of a given node. Optionally, a root resource can be supplied to overload the default root(s).
5512 +
5513 +Another operation that trees must support is finding an expansion path from a root to a given node. To support this, each TreeDataProvider points to a SPIN template that delivers a path. This typically uses the spif:shortestObjectsPath function."""^^xsd:string ;
5485 rdfs:label "Tree data provider"^^xsd:string ; 5514 rdfs:label "Tree data provider"^^xsd:string ;
5486 rdfs:subClassOf app:TreeElements ; 5515 rdfs:subClassOf app:TreeElements ;
5487 spin:constraint 5516 spin:constraint
...@@ -5492,6 +5521,12 @@ A TreeDataProvider is backed by two SELECT queries - one to get the roots, and o ...@@ -5492,6 +5521,12 @@ A TreeDataProvider is backed by two SELECT queries - one to get the roots, and o
5492 ] ; 5521 ] ;
5493 spin:constraint 5522 spin:constraint
5494 [ rdf:type spl:Argument ; 5523 [ rdf:type spl:Argument ;
5524 + rdfs:comment "This SPIN template is called with the variable ?node pre-bound to a node in the tree and ?root possibly pointing to a root resource. The template must return a single result variable containing a path from a root to that node. See spif:shortestObjectsPath for a default implementation. The path must be a space-separated string concatenation of URIs."^^xsd:string ;
5525 + spl:predicate arg:treePathTemplate ;
5526 + spl:valueType spin:Template
5527 + ] ;
5528 + spin:constraint
5529 + [ rdf:type spl:Argument ;
5495 rdfs:comment "A subclass of app:TreeRootsTemplates that delivers the roots of the tree. Will be bypassed if the tree itself defined an arg:rootResource."^^xsd:string ; 5530 rdfs:comment "A subclass of app:TreeRootsTemplates that delivers the roots of the tree. Will be bypassed if the tree itself defined an arg:rootResource."^^xsd:string ;
5496 spl:optional "true"^^xsd:boolean ; 5531 spl:optional "true"^^xsd:boolean ;
5497 spl:predicate arg:treeRootsTemplate ; 5532 spl:predicate arg:treeRootsTemplate ;
...@@ -5583,6 +5618,25 @@ app:TreeElements ...@@ -5583,6 +5618,25 @@ app:TreeElements
5583 rdfs:label "Tree elements"^^xsd:string ; 5618 rdfs:label "Tree elements"^^xsd:string ;
5584 rdfs:subClassOf app:Elements . 5619 rdfs:subClassOf app:Elements .
5585 5620
5621 +app:TreePathTemplates
5622 + rdf:type spin:SelectTemplate ;
5623 + rdfs:comment "An abstract superclass for SPIN templates used by TreeDataProviders to find a path from a node to a root."^^xsd:string ;
5624 + rdfs:label "Tree path templates"^^xsd:string ;
5625 + rdfs:subClassOf spin:SelectTemplates ;
5626 + spin:constraint
5627 + [ rdf:type spl:Argument ;
5628 + rdfs:comment "The node to start traversal at."^^xsd:string ;
5629 + spl:predicate arg:node ;
5630 + spl:valueType rdfs:Resource
5631 + ] ;
5632 + spin:constraint
5633 + [ rdf:type spl:Argument ;
5634 + rdfs:comment "An optional root resource to stop traversal at."^^xsd:string ;
5635 + spl:optional "true"^^xsd:boolean ;
5636 + spl:predicate arg:root ;
5637 + spl:valueType rdfs:Resource
5638 + ] .
5639 +
5586 app:TreeRootsTemplates 5640 app:TreeRootsTemplates
5587 rdf:type spin:SelectTemplate ; 5641 rdf:type spin:SelectTemplate ;
5588 rdfs:comment "Abstract superclass for queries that can deliver the roots of a tree."^^xsd:string ; 5642 rdfs:comment "Abstract superclass for queries that can deliver the roots of a tree."^^xsd:string ;
...@@ -5596,6 +5650,115 @@ app:TreeRootsTemplates ...@@ -5596,6 +5650,115 @@ app:TreeRootsTemplates
5596 spl:valueType rdfs:Resource 5650 spl:valueType rdfs:Resource
5597 ] . 5651 ] .
5598 5652
5653 +app:TreeShortestPathCallback
5654 + rdf:type ui:NodeClass ;
5655 + rdfs:comment "An element building a JSON array with URIs based on spif:shortestObjectsPath. Called using uispin?_viewClass=app:TreeShortestPathCallback&_format=json&subject=...&dataProvider=..."^^xsd:string ;
5656 + rdfs:label "Tree shortest path callback"^^xsd:string ;
5657 + rdfs:subClassOf app:TreeElements ;
5658 + spin:constraint
5659 + [ rdf:type spl:Argument ;
5660 + rdfs:comment "The TreeDataProvider that contains the pathExpression needed to walk to the root."^^xsd:string ;
5661 + spl:predicate arg:dataProvider ;
5662 + spl:valueType app:TreeDataProvider
5663 + ] ;
5664 + spin:constraint
5665 + [ rdf:type spl:Argument ;
5666 + rdfs:comment "The node resource to start traversal at."^^xsd:string ;
5667 + spl:predicate arg:node ;
5668 + spl:valueType rdfs:Resource
5669 + ] ;
5670 + spin:constraint
5671 + [ rdf:type spl:Argument ;
5672 + rdfs:comment "The root resource to stop at."^^xsd:string ;
5673 + spl:optional "true"^^xsd:boolean ;
5674 + spl:predicate arg:root ;
5675 + spl:valueType rdfs:Resource
5676 + ] ;
5677 + ui:prototype
5678 + [ rdf:type ui:group ;
5679 + let:template
5680 + [ rdf:type sp:Select ;
5681 + sp:resultVariables ([ sp:varName "template"^^xsd:string
5682 + ]) ;
5683 + sp:where ([ rdf:type sp:NamedGraph ;
5684 + sp:elements ([ sp:object
5685 + [ sp:varName "template"^^xsd:string
5686 + ] ;
5687 + sp:predicate arg:treePathTemplate ;
5688 + sp:subject
5689 + [ sp:varName "dataProvider"^^xsd:string
5690 + ]
5691 + ]) ;
5692 + sp:graphNameNode ui:graph
5693 + ])
5694 + ] ;
5695 + ui:child
5696 + [ rdf:type ui:call ;
5697 + arg:node
5698 + [ sp:varName "node"^^xsd:string
5699 + ] ;
5700 + arg:root
5701 + [ sp:varName "root"^^xsd:string
5702 + ] ;
5703 + ui:child
5704 + [ rdf:type ui:group ;
5705 + let:path
5706 + [ rdf:type spr:cell ;
5707 + sp:arg1 [ sp:varName "rs"^^xsd:string
5708 + ] ;
5709 + sp:arg2 0 ;
5710 + sp:arg3 0
5711 + ] ;
5712 + ui:child
5713 + [ rdf:type swon:RSArray ;
5714 + arg:resultSet
5715 + [ rdf:type sp:Select ;
5716 + sp:resultVariables ([ sp:varName "value"^^xsd:string
5717 + ]) ;
5718 + sp:where ([ sp:object
5719 + [ sp:varName "?0"^^xsd:string
5720 + ] ;
5721 + sp:predicate spif:split ;
5722 + sp:subject
5723 + [ sp:varName "value"^^xsd:string
5724 + ]
5725 + ] [ sp:object
5726 + [ sp:varName "path"^^xsd:string
5727 + ] ;
5728 + sp:predicate rdf:first ;
5729 + sp:subject
5730 + [ sp:varName "?0"^^xsd:string
5731 + ]
5732 + ] [ sp:object
5733 + [ sp:varName "?1"^^xsd:string
5734 + ] ;
5735 + sp:predicate rdf:rest ;
5736 + sp:subject
5737 + [ sp:varName "?0"^^xsd:string
5738 + ]
5739 + ] [ sp:object " " ;
5740 + sp:predicate rdf:first ;
5741 + sp:subject
5742 + [ sp:varName "?1"^^xsd:string
5743 + ]
5744 + ] [ sp:object () ;
5745 + sp:predicate rdf:rest ;
5746 + sp:subject
5747 + [ sp:varName "?1"^^xsd:string
5748 + ]
5749 + ])
5750 + ] ;
5751 + ui:childIndex 0
5752 + ] ;
5753 + ui:childIndex 0
5754 + ] ;
5755 + ui:childIndex 0 ;
5756 + ui:template
5757 + [ sp:varName "template"^^xsd:string
5758 + ]
5759 + ]
5760 + ] .
5761 +
5599 app:TreeTemplates 5762 app:TreeTemplates
5600 rdf:type spin:SelectTemplate ; 5763 rdf:type spin:SelectTemplate ;
5601 rdfs:comment """Base class for SELECT templates that are used to populate trees. There are two kinds of queries: 5764 rdfs:comment """Base class for SELECT templates that are used to populate trees. There are two kinds of queries:
...@@ -7354,6 +7517,11 @@ arg:treeChildrenTemplate ...@@ -7354,6 +7517,11 @@ arg:treeChildrenTemplate
7354 rdfs:label "tree children template"^^xsd:string ; 7517 rdfs:label "tree children template"^^xsd:string ;
7355 rdfs:subPropertyOf sp:arg . 7518 rdfs:subPropertyOf sp:arg .
7356 7519
7520 +arg:treePathTemplate
7521 + rdf:type rdf:Property ;
7522 + rdfs:label "tree path template"^^xsd:string ;
7523 + rdfs:subPropertyOf sp:arg .
7524 +
7357 arg:treeRootsTemplate 7525 arg:treeRootsTemplate
7358 rdf:type rdf:Property ; 7526 rdf:type rdf:Property ;
7359 rdfs:label "tree roots template"^^xsd:string ; 7527 rdfs:label "tree roots template"^^xsd:string ;
...@@ -7379,6 +7547,16 @@ arg:width ...@@ -7379,6 +7547,16 @@ arg:width
7379 rdfs:label "width"^^xsd:string ; 7547 rdfs:label "width"^^xsd:string ;
7380 rdfs:subPropertyOf sp:arg . 7548 rdfs:subPropertyOf sp:arg .
7381 7549
7550 +html:treedataprovider
7551 + rdf:type html:Attribute ;
7552 + rdfs:label "tree data provider"^^xsd:string ;
7553 + rdfs:subPropertyOf html:attributes .
7554 +
7555 +html:treeroot
7556 + rdf:type html:Attribute ;
7557 + rdfs:label "tree root"^^xsd:string ;
7558 + rdfs:subPropertyOf html:attributes .
7559 +
7382 ui:SubjectWidgetRowClass 7560 ui:SubjectWidgetRowClass
7383 rdf:type rdfs:Class ; 7561 rdf:type rdfs:Class ;
7384 rdfs:label "Subject widget row class"^^xsd:string ; 7562 rdfs:label "Subject widget row class"^^xsd:string ;
......
...@@ -339,6 +339,73 @@ function appReloadForm(resourceURI, queryGraphURI, linkElementId) { ...@@ -339,6 +339,73 @@ function appReloadForm(resourceURI, queryGraphURI, linkElementId) {
339 339
340 340
341 /** 341 /**
342 + * Selects a given node in a given tree.
343 + * Will expand if necessary, using a server-side shortest path algorithm.
344 + * @param treeId the id of the tree
345 + * @param nodeURI the URI of the resource to select
346 + */
347 +function appSelectTreeNode(treeId, nodeURI) {
348 +
349 + // TODO: Currently this only works on the Tree that was created last
350 + // but not if multiple trees are on a page
351 +
352 + var tree = $('#' + treeId);
353 + var dataProviderURI = tree.attr('treedataprovider');
354 + if(!dataProviderURI) {
355 + alert('Error: Element with id ' + treeId + ' does not have treedataprovider attribute');
356 + return;
357 + }
358 +
359 + var rootURI = tree.attr('treeroot');
360 +
361 + // Do nothing if it's already selected
362 + var sel = tree.jstree('get_selected');
363 + if(sel) {
364 + if(sel.attr('resource') == nodeURI) {
365 + return;
366 + }
367 + }
368 +
369 + // Load path to root from the server and then call helper function
370 + var data = {
371 + _format: 'json',
372 + _viewClass: 'app:TreeShortestPathCallback',
373 + dataProvider: '<' + dataProviderURI + '>',
374 + node: '<' + nodeURI + '>'
375 + };
376 + if(rootURI) {
377 + data.root = '<' + rootURI + '>';
378 + }
379 + $.get(uispinServlet, data, function(path) {
380 + appSelectTreeNodeHelper(tree, tree, path, 0);
381 + });
382 +}
383 +
384 +
385 +// Private helper function - walks an array, expanding nodes along the way
386 +function appSelectTreeNodeHelper(tree, node, path, index) {
387 +
388 + var next = path[index];
389 +
390 + node.children("ul").children("li").each(function(i, o) {
391 + var child = $(o);
392 + if(child.attr('resource') == next) {
393 + if(index == path.length - 1) {
394 + // End reached: select this node
395 + tree.jstree('select_node', child, true);
396 + child[0].scrollIntoView();
397 + }
398 + else {
399 + tree.jstree('open_node', child, function() {
400 + appSelectTreeNodeHelper(tree, child, path, index + 1);
401 + });
402 + }
403 + }
404 + });
405 +}
406 +
407 +
408 +/**
342 * Submits a form and switches it to viewing mode when done. 409 * Submits a form and switches it to viewing mode when done.
343 * @param form the id of the form 410 * @param form the id of the form
344 * @param servlet the optional name of the servlet 411 * @param servlet the optional name of the servlet
......
...@@ -5,8 +5,7 @@ ...@@ -5,8 +5,7 @@
5 ui:view="{= ?dataProvider }" 5 ui:view="{= ?dataProvider }"
6 arg:root="{= ?root }"> 6 arg:root="{= ?root }">
7 7
8 - <!-- The div that will be turned into a jsTree below --> 8 + <div id="{= ?id }" treedataprovider="{= ?dataProvider }" treeroot="{= ?root }"/>
9 - <div id="{= ?id }" />
10 9
11 <script type="text/javascript"> 10 <script type="text/javascript">
12 $(function () { 11 $(function () {
...@@ -15,12 +14,7 @@ ...@@ -15,12 +14,7 @@
15 "plugins" : [ 14 "plugins" : [
16 "themes", 15 "themes",
17 "json_data", 16 "json_data",
18 - "ui", 17 + "ui" ],
19 - "crrm",
20 - "cookies",
21 - "search",
22 - "types",
23 - "hotkeys" ],
24 18
25 "json_data" : { 19 "json_data" : {
26 "ajax" : { 20 "ajax" : {
...@@ -40,6 +34,10 @@ ...@@ -40,6 +34,10 @@
40 34
41 "themes" : { 35 "themes" : {
42 "theme" : "classic" 36 "theme" : "classic"
37 + },
38 +
39 + "ui": {
40 + "select_limit": 1
43 } 41 }
44 }); 42 });
45 }); 43 });
......