Subversion Repositories public iLand

Rev

Rev 1221 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1185 werner 1
/* global $:true */
2
$(function() {
3
    'use strict';
4
 
5
    // ************************************************************************* //
6
    //  HTML templates
7
    // ************************************************************************* //
8
 
9
    // (None)
10
 
11
 
12
    // ************************************************************************* //
13
    //  Functions
14
    // ************************************************************************* //
15
 
16
    function setUpActiveTab() {
17
        if(localStorage.getItem('main-nav')){
18
            $('a[href="'+ localStorage['main-nav'] + '"]').tab('show');
19
        }
20
    }
21
 
22
    function setUpOptionsCheckboxes() {
23
        if(localStorage.getItem('options')){
24
            var optionsArr = JSON.parse(localStorage.options),
25
                optionsForm = $('#options-form');
26
 
27
            for(var i=0;i<optionsArr.length;i++){
28
                var box = optionsForm.find('input:checkbox').eq(i);
29
                box.prop('checked', optionsArr[i]);
30
                setOptionDisplayState(box);
31
            }
32
        }
33
    }
34
 
35
    function setUpWidgets() {
36
        var sideSource = [], navbarSource = [], sidebarSearch, navbarSearch;
37
 
38
        $('#sidebar .tab-pane.active li a').each(function(index, elem) {
39
            sideSource.push($(elem).text());
40
        });
41
        sidebarSearch = $('#sidebar input[type="search"]');
42
        sidebarSearch.typeahead({
43
            source: sideSource,
44
            updater : function(item) {
45
                $('#sidebar .tab-pane.active a:contains(' + item + ')')[0].click();
46
                return item;
47
            }
48
        });
49
 
50
        $('#sidebar .tab-pane li a').each(function(index, elem) {
51
            var $el = $(elem),
52
                type = $el.parents('.tab-pane').is('#classes') ? 'classes/' : 'modules/';
53
            navbarSource.push(type + $el.text());
54
        });
55
        navbarSearch = $('.navbar input');
56
        navbarSearch.typeahead({
57
            source : navbarSource,
58
            updater : function(item) {
59
                var type = item.split('/')[0], name = item.split('/')[1],
60
                    $parent = $('#sidebar .tab-pane#' + type);
61
                $parent.find('a:contains(' + name + ')')[0].click();
62
                return item;
63
            }
64
        });
65
    }
66
 
67
    function setOptionDisplayState(box) {
68
        var cssName = $.trim(box.parent('label').text()).toLowerCase();
69
        if(box.is(':checked')){
70
            $('div.'+cssName).css('display', 'block');
71
            $('li.'+cssName).css('display', 'block');
72
            $('span.'+cssName).css('display', 'inline');
73
        }else{
74
            $('.'+cssName).css('display', 'none');
75
        }
76
    }
77
 
78
    function scrollToAnchor($anchor) {
79
        var navbarHeight = $('.navbar-fixed-top').outerHeight(true);
80
        $(document).scrollTop( $anchor.offset().top - navbarHeight);
81
    }
82
 
83
    $('[data-toggle=tab]').on('click', function (event, extraArgs) {
84
        // Why?  If responding to the click of a link or hashchange already, we really
85
        //  don't want to change window hash
86
        if (extraArgs && extraArgs.ignore === true) {
87
            return;
88
        }
89
        window.location.hash = $(this).attr('href');
90
    });
91
 
92
    $('[data-tabid]').on('click', function(event) {
93
        var tabToActivate = $(this).attr('data-tabid'),
94
        anchor = $(this).attr('data-anchor');
95
        event.preventDefault();
96
 
97
        $('[data-toggle=tab][href="'+ tabToActivate + '"]').click();
98
        // ...huh?  http://stackoverflow.com/a/9930611
99
        // otherwise, can't select an element by ID if the ID has a '.' in it
100
        var scrollAnchor = anchor.replace(/\./g, '\\.');
101
        scrollToAnchor($(scrollAnchor));
102
        window.location.hash = anchor;
103
    });
104
 
105
    function moveToWindowHash() {
106
        var hash = window.location.hash,
107
            tabToActivate = hash,
108
            $tabToActivate = false,
109
            $scroll = $(hash);
110
 
111
        if (!hash) {
112
            return;
113
        }
114
 
115
        if (hash.match(/^#method_/)) {
116
            tabToActivate = '#methods';
117
        }
118
        else if (hash.match(/^#property_/)) {
119
            tabToActivate = '#properties';
120
        }
121
        else if (hash.match(/^#event_/)) {
122
            tabToActivate = '#event';
123
        }
124
        else if (hash.match(/#l\d+/)) {
125
            var lineNumber = /#l(\d+)/.exec(hash)[1];
126
            var whichLi = parseInt(lineNumber, 10) - 1; //e.g. line 1 is 0th element
127
            $scroll = $('ol.linenums > li').eq(whichLi);
128
        }
129
 
130
        $tabToActivate = $('[data-toggle=tab][href="'+ tabToActivate + '"]');
131
        if ($tabToActivate.length) {
132
            $tabToActivate.trigger('click', { ignore: true });
133
        }
134
 
135
        if ($scroll.length) {
136
            scrollToAnchor($scroll);
137
        }
138
    }
139
 
140
    // ************************************************************************* //
141
    //  Initializations + Event listeners
142
    // ************************************************************************* //
143
 
144
    //
145
    // Store last clicked tab in local storage
146
    //
147
    $('#main-nav li').on('click', function(e) {
148
        e.preventDefault();
149
        localStorage['main-nav'] = $(this).find('a').attr('href');
150
    });
151
 
152
    //
153
    // Refresh typeahead source arrays when user changes tabs
154
    //
155
    $('#main-nav li').on('shown', function(e) {
156
        e.preventDefault();
157
        setUpWidgets();
158
    });
159
 
160
    //
161
    // Bind change events for options form checkboxes
162
    //
163
    $('#options-form input:checkbox').on('change', function(){
164
        setOptionDisplayState($(this));
165
 
166
        // Update localstorage
167
        var optionsArr = [];
168
        $('#options-form input:checkbox').each(function(i,el) {
169
            optionsArr.push($(el).is(':checked'));
170
        });
171
        localStorage.options = JSON.stringify(optionsArr);
172
    });
173
 
174
    //
175
    // Keyboard shortcut - 's' key
176
    // This brings the api search input into focus.
177
    //
178
    $(window).keyup(function(e) {
179
        // Listen for 's' key and focus search input if pressed
180
        if(e.keyCode === 83){ // 's'
181
            $('#api-tabview-filter input').focus();
182
        }
183
    });
184
 
185
    //
186
    // Keyboard shortcut - 'ctrl+left', 'ctrl+right', 'up', 'down'
187
    // These shortcuts offer sidebar navigation via keyboard,
188
    // *only* when sidebar or any element within has focus.
189
    //
190
    var nextIndex;
191
    $('#sidebar').keydown(function(e) {
192
        var $this = $(this);
193
 
194
        // Determine if the control/command key was pressed
195
        if(e.ctrlKey){
196
            if(e.keyCode === 37){ // left arrow
197
                $('#main-nav li a:first').tab('show');
198
            } else if(e.keyCode === 39){ // right arrow
199
                $('#main-nav li a:last').tab('show');
200
            }
201
        } else {
202
            if(e.keyCode === 40){ // down arrow
203
                if ($('#api-tabview-filter input').is(':focus')) {
204
                    // Scenario 1: We're focused on the search input; move down to the first li
205
                    $this.find('.tab-content .tab-pane.active li:first a').focus();
206
                } else if ($this.find('.tab-content .tab-pane.active li:last a').is(':focus')) {
207
                    // Scenario 2: We're focused on the last li; move up to search input
208
                    $('#api-tabview-filter input').focus();
209
                } else {
210
                    // Scenario 3: We're in the list but not on the last element, simply move down
211
                    nextIndex = $this
212
                    .find('.tab-content .tab-pane.active li')
213
                    .find('a:focus')
214
                    .parent('li').index() + 1;
215
                    $this.find('.tab-content .tab-pane.active li:eq('+nextIndex+') a').focus();
216
                }
217
                e.preventDefault(); // Stop page from scrolling
218
            } else if (e.keyCode === 38){ // up arrow
219
                if($('#api-tabview-filter input').is(':focus')) {
220
                    // Scenario 1: We're focused on the search input; move down to the last li
221
                    $this.find('.tab-content .tab-pane.active li:last a').focus();
222
                }else if($this.find('.tab-content .tab-pane.active li:first a').is(':focus')){
223
                    // Scenario 2: We're focused on the first li; move up to search input
224
                    $('#api-tabview-filter input').focus();
225
                }else{
226
                    // Scenario 3: We're in the list but not on the first element, simply move up
227
                    nextIndex = $this
228
                    .find('.tab-content .tab-pane.active li')
229
                    .find('a:focus')
230
                    .parent('li').index() - 1;
231
                    $this.find('.tab-content .tab-pane.active li:eq('+nextIndex+') a').focus();
232
                }
233
                e.preventDefault(); // Stop page from scrolling
234
            }
235
        }
236
    });
237
 
238
    function setUpHashChange() {
239
        $(window).on('hashchange', moveToWindowHash);
240
    }
241
 
242
 
243
    // ************************************************************************* //
244
    //  Immediate function calls
245
    // ************************************************************************* //
246
 
247
    setUpActiveTab();
248
    setUpOptionsCheckboxes();
249
    setUpWidgets();
250
    setUpHashChange();
251
    if (window.location.hash) {
252
        moveToWindowHash();
253
    }
254
 
255
});