1jQuery.fn.dw_tree = function(overrides) {
2    var dw_tree = {
3
4        /**
5         * Delay in ms before showing the throbber.
6         * Used to skip the throbber for fast AJAX calls.
7         */
8        throbber_delay: 500,
9
10        $obj: this,
11
12        toggle_selector: 'a.idx_dir',
13
14        init: function () {
15            this.$obj.on('click', this.toggle_selector, this,
16                               this.toggle);
17            jQuery('ul:first', this.$obj).attr('role', 'tree');
18            jQuery('ul', this.$obj).not(':first').attr('role', 'group');
19            jQuery('li', this.$obj).attr('role', 'treeitem');
20            jQuery('li.open > ul', this.$obj).attr('aria-expanded', 'true');
21            jQuery('li.closed > ul', this.$obj).attr('aria-expanded', 'false');
22            jQuery('li.closed', this.$obj).attr('aria-live', 'assertive');
23        },
24
25        /**
26         * Open or close a subtree using AJAX
27         * The contents of subtrees are "cached" until the page is reloaded.
28         * A "loading" indicator is shown only when the AJAX call is slow.
29         *
30         * @author Andreas Gohr <andi@splitbrain.org>
31         * @author Ben Coburn <btcoburn@silicodon.net>
32         * @author Pierre Spring <pierre.spring@caillou.ch>
33         */
34        toggle: function (e) {
35            var $listitem, $sublist, timeout, $clicky, show_sublist, dw_tree, opening;
36
37            e.preventDefault();
38
39            dw_tree = e.data;
40            $clicky = jQuery(this);
41            $listitem = $clicky.closest('li');
42            $sublist = $listitem.find('ul').first();
43            opening = $listitem.hasClass('closed');
44            dw_tree.toggle_display($clicky, opening);
45            if ($sublist.is(':visible')) {
46                $listitem.removeClass('open').addClass('closed');
47                $sublist.attr('aria-expanded', 'false');
48            } else {
49                $listitem.removeClass('closed').addClass('open');
50                $sublist.attr('aria-expanded', 'true');
51            }
52
53            // if already open, close by hiding the sublist
54            if (!opening) {
55                $sublist.dw_hide();
56                return;
57            }
58
59            show_sublist = function (data) {
60                $sublist.hide();
61                if (typeof data !== 'undefined') {
62                    $sublist.html(data);
63                    $sublist.parent().attr('aria-busy', 'false').removeAttr('aria-live');
64                    jQuery('li.closed', $sublist).attr('aria-live', 'assertive');
65                }
66                if ($listitem.hasClass('open')) {
67                    // Only show if user didn’t close the list since starting
68                    // to load the content
69                    $sublist.dw_show();
70                }
71            };
72
73            // just show if already loaded
74            if ($sublist.length > 0) {
75                show_sublist();
76                return;
77            }
78
79            //prepare the new ul
80            $sublist = jQuery('<ul class="idx" role="group"/>');
81            $listitem.append($sublist);
82
83            timeout = window.setTimeout(
84                bind(show_sublist, '<li aria-busy="true"><img src="' + DOKU_BASE + 'lib/images/throbber.gif" alt="loading..." title="loading..." /></li>'), dw_tree.throbber_delay);
85
86            dw_tree.load_data(function (data) {
87                                  window.clearTimeout(timeout);
88                                  show_sublist(data);
89                              }, $clicky);
90        },
91
92        toggle_display: function ($clicky, opening) {
93        },
94
95        load_data: function (show_data, $clicky) {
96            show_data();
97        }
98    };
99
100    jQuery.extend(dw_tree, overrides);
101
102    if (!overrides.deferInit) {
103        dw_tree.init();
104    }
105
106    return dw_tree;
107};
108