This documentation is aimed at developers needing to include page-tree (page reordering) functionality in their Confluence or Plugin code.
Let's start with an example - editing a page deep inside the Confluence Doc space.
This tree is generated by the following markup in listpages-dirview.vm :
1 2#requireResource("confluence.web.resources:jquery") #requireResource("confluence.web.resources:page-ordering-tree") <div id="tree-div"></div>
and the following JavaScript :
1 2var expandedNodes; #if ($openNode) expandedNodes = [ {pageId: "$openId"} #foreach ($nodeId in $openedNodes) ,{pageId: "$nodeId"} #end ]; #end jQuery(function ($) { tree = $("#tree-div").tree( { url: contextPath + '/pages/children.action', initUrl: contextPath + '/pages/children.action?spaceKey=$space.key&node=root', parameters: ["pageId"], append: function() { recordMove(this.source.pageId, this.target.pageId, "append"); }, insertabove: function() { recordMove(this.source.pageId, this.target.pageId, "above"); }, insertbelow: function() { recordMove(this.source.pageId, this.target.pageId, "below"); }, onready: function () { if (typeof expandedNodes != "undefined") { var doHighlight = function() { tree.findNodeBy("pageId", "$openId").highlight() }; tree.expandPath.apply(tree, expandedNodes.reverse().concat(doHighlight)); } } } ); ## Callbacks when append/insert events are fired by the tree. var recordMove = function (sourceId, targetId, position) { $ .ajax({ url: contextPath + "/pages/movepage.action", data: {pageId: sourceId, point: position, targetId: targetId}, complete: function(xmlhttp) { var resultsDiv = document.getElementById("resultsDiv"); resultsDiv.innerHTML = xmlhttp.responseText; if (xmlhttp.getResponseHeader("success") != "true") { tree = tree.reload(); } if ( position == "append") { tree.findNodeBy("pageId", targetId).reload(); } } }); } });
Once you understand the above code you'll have a good overview of how the tree works.
To start, "expandedNodes" is simply a JS array of objects with "pageId" variables. The pageIds are populated using Velocity but any method is okay.
Next, "jQuery(function ($) {" is just a way of enabling $ to be used to gain access to a jQuery object. The page tree code has been written as an extension of the jQuery object, so we call $("#tree-div") to get a jQuery object wrapping the div with id "tree-div" that we added to our HTML markup.
When the tree() function is called, an object with options is passed. We'll work through each of the options in turn:
1 2url
This is the location that the tree will load its nodes from as the user navigates it. The alternative is to directly include the tree data in the HTML in nested <ul> or <ol> format.
1 2initurl
(optional) This is the location that the tree will load its "trunk" (initial nodes) from. If not specified, the "url" will be used and the server would be expected to return something useful. If specified, it can (as in this case) pass extra information to the same server address.
1 2parameters
(optional but important) This array specifies the key/value pairs that will be sent to the url when making node requests. The nodes returned from the server will be expected to include key/value pairs for each of the parameters in the array, which are stored in the tree internals and sent with any future requests from that node.
1 2append, insertabove, insertbelow
(optional) These options specify callback functions that should be executed when their respective event occurs:
For each of these events the most important data is source and target. Source is the node that is being moved and target is the "other" node that the source is interacting with.
While these three events are the most common, you can also hook callbacks to :
1 2onready
(optional) Called when the tree has finished loading, from either its first initUrl call or from hard-coded list data. In this case, if "expandedNodes" exist the tree should be expanded to show them. The way that this is done is worth explaining in more detail.
Once the first level of tree data has been loaded into the browser, the next step is often to drill into the tree to expose a particular element. This is done by calling :
1 2tree.expandPath(expandedNodes, callback)
Internally, this function works recursively through the array of expandedNodes, locating the node in the loaded tree and, if present, opening it. In the screenshot above, this is equivalent to passing an array of nodes:
"Confluence Documentation Home", "Confluence Development Hub", "Confluence Architecture", "Confluence Internals". Note that the nodes are referenced by pageId and must be in the correct order - each node to expand must already be loaded. Once each node is expanded the callback function (if present) is executed. In this example, the callback highlights a node inside the expanded nodes - note that the "Bandana caching" node is only loaded from the server when the "Confluence Internals" node is expanded, so the highlighting must occur after this.
Individual nodes are located with this syntax:
1 2tree.findNodeBy(attribute-name, attribute-value)
Usually the attribute-name will be one of the parameters in the options originally used to create the tree; in this case it is "pageId".
The object returned by findNodeBy has a number of functions that can be called on it :
In addition to the functions covered in the example above, the tree object exposes the following variables and functions:
Rate this page: