Confluence Docs 3.0 : Page Tree API Documentation This page last changed on May 01, 2008 by dtaylor. 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 :
    #requireResource("confluence.web.resources:jquery")
    #requireResource("confluence.web.resources:page-ordering-tree")
    <div id="tree-div"></div>
and the following JavaScript :
    var 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. ### Stepping through the code 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. #### Creating the tree When the tree() function is called, an object with options is passed. We'll work through each of the options in turn:
    url
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.
    initurl
(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.
    parameters
(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.
    append, insertabove, insertbelow
(optional) These options specify callback functions that should be executed when their respective event occurs: append - means that a tree node (i.e. a page) has been moved inside another node insertabove - means that a tree node has been moved above another node insertbelow - means that a tree node has been moved below another node 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 : grab - when the user clicks and holds on a node drag - when the user moves the mouse while a node is grabbed drop - when the user releases the mouse button load - when node data is returned from the server nodeover - when a node is dragged over another node nodeout - when a node is dragged out of a node it was previously over onready - covered next
    onready
(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. #### Finding and Expanding Nodes 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 :
    tree.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:
    tree.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 : open(callback) - expand this node. If the node has not been opened yet and the tree has a url, child-node JSONs will be requested from the server and appended to the node. close() - closes an opened node getAttribute(attrName) - returns the attribute value for the given name (eg "pageId") setAttribute(attrName, attrValue) - sets an attribute highlight() - adds "highlighted" class to the node makeDraggable() - allows the node to be moved in the tree makeUndraggable() - stops the node from being moved (e.g. when moving a page while editing, other nodes in the tree cannot be moved) setText(text) - updates the node text append(node) - appends a node to this node below(node) - places the passed node after this node above(node) - places the passed node before this node remove() - removes this node from the tree reload() - if this node has children, reload them from the server #### Other tree functions In addition to the functions covered in the example above, the tree object exposes the following variables and functions: options - the options passed in the original tree() function call reload() - clears and rebuilds the tree append(node) - appends a node to the tree root Attachments: page-tree-snap.png (image/png)

Document generated by Confluence on Nov 05, 2009 23:34