﻿/*
 * nested-accordion.js
 *
 * Implements the NestedAccordion class.
 */


//
// Class: NestedAccordion
//
// Used to implement a nested accordion control, based on the Mootools Fx.Accordion class.
//
// Wouldn't have been able to get this working without the help of the following article:
// http://blog.medianotions.de/en/articles/2008/mootools-nested-accordion
// Example: http://blog.medianotions.de/assets/demos/mootools-nested-accordion_1.2/
//
NestedAccordion = new Class({

    //
    // Function: initialize()
    //
    // Constructor for this class. Initialises the nested accoordion control.
    //
    initialize: function(controlName, accordions, path) {
        var control = $(controlName);
        if (!control)
            return; // Control is missing on the page. Just exit?

        if (!accordions || !accordions.length)
            return; // Accordion declarations are missing or empty. Just exit?

        if (!path) {
            // Get the current file path from the page's URL.
            path = this.getPath(window.location);
        }

        // For testing:
        // path = '/skilled-visa/why_use_skilled.asp';
        // path = '/parent-visa/visa_descriptions_entitlements.asp';


        // Have we found the current URL in the accordion control?
        var found = false;

        // Set up all the accordion controls.
        for (i = 0; i < accordions.length; ++i) {
            acc = accordions[i];

            // Go looking for the current selected URL in the control.
            found = found || this.findSelectedItem(acc.headings, acc.items, path);

            // Get the initial state of the accordion control (i.e. the index of the open item in the control).
            // -1 = closed.
            index = (found) ? this.getSelectedIndex(acc.headings, acc.subheadings) : -1;

            // Create the new accordion control.
            // Note the use of the onComplete() function, which is a workaround for getting
            // nested accordions working properly.
            new Fx.Accordion(control, acc.headings, acc.lists,
                {   // options:
                    show: index,
                    alwaysHide: true,
                    onComplete: function() {
                        var element = $(this.elements[this.previous]);
                        if (element && element.offsetHeight > 0)
                            element.setStyle('height', (window.ie6) ? '100%' : '');
                    }
                });
        }

        // Now that the control is initialised, it can be shown.
        control.removeClass('hidden');

    },  // initialize


    //
    // function: getPath()
    //
    // Returns the file path for the URL passed in.
    //
    getPath: function(url) {
        uri = new URI(url);
        return (uri.get('directory') || "/").toLowerCase() + (uri.get('file') || "").toLowerCase();
    },


    //
    // function: checkHref()
    //
    // Returns true if the href of the anchor matches the dir/file parameters passed in.
    //
    checkHref: function(a, path) {
        return (a && a.href) ? (this.getPath(a.href) == path) : false;
    },  // checkHref


    //
    // function: findSelectedItem()
    //
    // Goes looking through the headings and items of an accordion control.
    // If it finds a heading or item with a link that matches the current dir/file, it adds the class 'selected'
    // to the heading and returns true (found).
    //
    findSelectedItem: function(headings, items, path) {
        found = false;
        me = this; // because 'this' is bound to something else in the .each() method below.
        $$(headings).each(function(div, i) {
            a = div.getElement('a');
            if (me.checkHref(a, path)) {
                // Found a heading that matches the current file path.
                found = true;
                div.addClass('selected');
            }
        });
        if (!found) {
            $$(items).each(function(li, i) {
                div = li.getElement('div');
                a = div.getElement('a');
                if (me.checkHref(a, path)) {
                    // Found an item in the subnavigation that matches the current file path.
                    found = true;
                    div.addClass('selected');
                }
            });
        }
        return found;
    },  // findSelectedItem


    //
    // Function: getSelectedIndex()
    //
    // Gets the correct index for the currently selected item in an accordion control, based on the which
    // heading/subheading has the class 'selected'.
    //
    getSelectedIndex: function(headings, subheadings) {
        index = -1; // Default to -1 (not selected).
        $$(headings).each(function(heading, i) {
            if (heading.hasClass('selected')) {
                // This heading is selected - use this item's index as the selected index.
                index = i;
            }
            else {
                heading.getParent().getElements(subheadings).each(function(subheading) {
                    if (subheading.hasClass('selected')) {
                        // One of the subheadings beneath this heading is selected - use this item's index as the selected index.
                        index = i;
                    }
                });
            }
        });
        return index;
    }   // getSelectedIndex

});
