Note:

If you want to create a new page for developers, you should create it on the Moodle Developer Resource site.

Navigation 2.0 globalnav proposal

From MoodleDocs

Globalnav proposal

This proposal covers one of the changes that will be happening as part of the navigation 2.0 implementation. The idea is to present the structure of a Moodle site in an easily navigable tree structure. Of course this tree structure would be mammoth, particularly for large installations so it is important to note that there will be a limit to the amount of information that will be shown initially, although it should be expandable by AJAX methods.

The globalnav will be used to represent the Moodle site structure and loosely translates to the following branching structure

Site -> Categories -> Courses -> Module Types -> Module Instance -> Module Specific
                              -> Structure    -> Module Instance -> Module Specific
                                              -> Resources

The structure that is visible to the user will need to be dependent on the users permissions.

The overall structure of this nav block would be huge, and is certainly one area where having a smooth ajax expander is essential. I also think that having a clear way to bring focus to the current position will be critical to the success of this block.

Implementation

Step One: The globalnav object

As suggested in Navigation 2.0 implementation plan the globalnav object will be available through the $PAGE object. It will need to be robust enough to generate much of its own content (items) whilst still being flexible enough that it can be interacted with as required.

The bulk of the code behind the globalnav object will be created in the following files:

   moodle/lib/navigationlib.php
   moodle/lib/ajax/getnavdata.php

The globalnav object will be initiated by $PAGE at the same time as theme and output are initiated within the page::initialise_theme_and_output() method. During initialisation the globalnav object will build the immediate part of the tree, this will probably be the site level, which contains all of the categories. The globalnav object at that point will investigate the PAGE object in order to work the position of the current user by looking for and at the categories, course, and cm objects. Once the current position has been worked out the tree can be `grown` or generated to accommodate the users current position and next possible position in the tree.

The following method will be called to initialise the globalnav within page::initialise_theme_and_output()

globalnav::generate_initial_items(); // Public

This method will look at the current page context and currently available objects (category, course, module) to determine what areas of the structure should be automatically generated.

The following are internal (private) methods that will then be automatically called as part of the initialisation:

// Generates items for categories and courses, or subcategories and courses if given a category object or categoryid
globalnav::generate_category_items($category=null);

// Generates items for the structure of a course
globalnav::generate_course_structure_items($course);

// Generates items for the modules used in a course
globalnav::generate_course_module_items($course); 

// Generates items for the resources used in a course structure
globalnav::generate_resource_items($course, $structure);

// Generates items for the module instances within a course and adds them to the structure and module branches
globalnav::generate_activity_items($course, $module);

The user's position within the tree will determine which of these function will get called with what options. It is important to note that these function will not just be used on the current object. They will of course be used to get information for objects that are both up, and down the tree from the users current position if required.

The globalnav object would be primarily used by a tree block (also yet to be developed) to produce the appropriate XHTML or XML (for Ajax). The final tree structure can be returned from the navbar object using the following public methods

$OUTPUT->globalnav->get_tree();

The structure generated the get_tree() method should be as follows:

$tree = Array() {
    $item = stdClass {
        ->type  = int [GLOBALNAV_BRANCH or GLOBALNAV_NODE]
        ->title = string
        ->link  = string or null     # Always null if type=branch
        ->icon  = string or null
        ->expanded = bool            # Always true for type=node
        ->focuspos = bool            # Should only be true for ONE item in the structure
        ->children = array or null   # Array of $item always null if type=node
    }
}

One of the requirements that will greatly impact this implementation is the ability for a module to add its own custom structure to the tree, as this means that we need some way to get this custom tree structure information from the module.

The solution that I purpose for this is to introduce a specific function that will be looked for when the user is expanding (either by AJAX, or refresh) the module section of a tree. The function won't be a requirement to ensure backwards compatibility but will be checked for whenever an appropriate expansion is occuring. The functions should exist in lib.php for the module, and should be as follows:

// Within mod/{module}/lib.php
/**
 * Adds custom module items/branches to the globalnav object.
 * Returns true if modifications are made, false if not.
 */
function custom_globalnav_branch() {
    .....
    $OUTPUT->globalnav->module($courseid, $moduleid)->add('title', 'link', 'icon');
    $branchid = $OUTPUT->globalnav->module($courseid, $moduleid)->add_branch('branch title');
    $OUTPUT->globalnav->module($courseid, $moduleid)->branch($branchid)->add('title', 'link', 'icon');
    return true;
    .....
}

The next requirement to explore is the AJAX expansion of branches within the tree. The tree will be designed to refresh with a page refresh however JS and PHP methods will be implemented to allow expansion to occur via AXAJ. This will require that the tree block provide some supporting functionality and produce an XHTML structure that allows this occur easily. It also requires that an AJAX callback file be created the accommodate the generation of XML data for the expanding branch.

Step Two: The globalnav block

In order to fully implement globalnav a tree block also need to be developed that can display the tree as a block to the user. Currently Alan Trick has started initial development on such a tree MDL-19300, the block will need to iterate the tree structure returned by globalnav and then produce its output.

Step Three: AJAX requirement

There will as discussed above need to be a script that can be called by an AJAX request to deliver a branch of tree as require when expanding. Along with this script there will also need to be a Javascript file that contains the code necessary to achieve this.

Interaction

Interaction is essential to this item to allow modules to expand the tree with module specific information. It is important to note that it is only required at the module level and can only occur once the user has reached (or expanded) the course for which a module instance belongs.

The following methods should be made available for interacting with the globalnav object:

// Adds an item directly under the module, this item can be a link or 
$OUTPUT->globalnav->module($courseid, $moduleid)->add($title, $link=null, $icon=null);

// Adds a new branch to the module
$branchid = $OUTPUT->globalnav->module($courseid, $moduleid)->add_branch($title);

// Adds an item to the new branch
$OUTPUT->globalnav->module($courseid, $moduleid)->branch($branchid)->add('title', 'link', 'icon');

// Adds a subbranch to the branch created above
$branchid = $OUTPUT->globalnav->module($courseid, $moduleid)->add_branch($branchid)->add_branch($title);

Usability and configuration

There are several ideas that should be implemented in order to make this new globalnav a useful block.

  • The first is to remember what areas of the tree have been expanded, and ensure that they are re-expanded every time the tree is closed until they have once again been collapsed. This can of course be achieved by using the get_user_preferences and set_user_preferences, and can be done as the tree is expanded and collapsed in PHP code whether it be through a refresh or AJAX.
  • Next the tree should automatically expand to the users position, this is essential but requires consideration to ensure that where it is the first time generating the tree (no user pref's yet) or simply that they have clicked on an inpage link to navigate elsewhere the tree always reflects where they are.
  • JS functionality to auto-load an extra level of the globalnav tree if JavaScript is enabled. This would mean that everyone would get the initial tree and those who have JavaScript enabled would get the next level, or even maybe just a full list of courses, and categories or such. This would of course speed up the deliver of the users tree expansion should they choose to expand, whilst also greatly improving the usefulness of the following feature.
  • Another feature I imagine would be very handy would be a tree search, and highlight function that would allow the user to enter some search text and then would highlight all instances of the found text. This function would of course have to be JavaScript based, however I think it would be a fantastic feature in large installations even if it only search the established tree. It would also be an aid to focus on the found text, and/or inform the user of the number of matches.

Future Improvements

The following are ideas that maybe sometime in the future could be implement, should someone at some point in time feel like doing it.

  • Allow bookmarking of pages from the tree, maybe by context menu, maybe by icon... of course you'd have to implement bookmarking first
  • Allow the developer or maybe admin through settings to add items to the root of the tree (at the site level) that could be used to represent a larger site structure. This could be useful in circumstances where Moodle was being used as part of a larger intranet, collection of related sites (e.g. all university sites) to get the entire localweb structure into the navigation... handy.

Further Information

Navigation 2.0

Navigation 2.0 implementation plan

Navigation 2.0 navbar proposal

MDL-19300