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 | }); |