@@ -5,6 +5,7 @@ import HighlightedSearchMethod from './HighlightedSearchMethod';
5
5
import type { ApiInterface , ApiMethod , ApiMethodParameter , ApiServices , SidebarGroupData } from './interfaces' ;
6
6
import { ApiSearcher } from './search' ;
7
7
8
+ const sidebar = ref < HTMLElement | null > ( null ) ;
8
9
const inputSearch = ref < HTMLInputElement | null > ( null ) ;
9
10
const inputApiKey = ref < HTMLInputElement | null > ( null ) ;
10
11
const inputAccessToken = ref < HTMLInputElement | null > ( null ) ;
@@ -88,6 +89,7 @@ export default defineComponent({
88
89
format : 'json' ,
89
90
favorites : new Set < string > ( ) ,
90
91
} ,
92
+ skipNextHashChange : false ,
91
93
keyInputType : 'password' ,
92
94
hasValidWebApiKey : false ,
93
95
hasValidAccessToken : false ,
@@ -105,6 +107,7 @@ export default defineComponent({
105
107
} ,
106
108
setup ( ) {
107
109
return {
110
+ sidebar,
108
111
inputSearch,
109
112
inputApiKey,
110
113
inputAccessToken,
@@ -167,25 +170,18 @@ export default defineComponent({
167
170
localStorage . removeItem ( 'steamid' ) ;
168
171
}
169
172
} ,
170
- currentInterface ( newInterface : string ) : void {
171
- if ( newInterface ) {
172
- document . title = `${ newInterface } – Steam Web API Documentation` ;
173
- } else {
174
- document . title = `Steam Web API Documentation` ;
175
- }
176
-
177
- if ( document . scrollingElement ) {
178
- document . scrollingElement . scrollTop = 0 ;
179
- }
180
- } ,
181
173
currentFilter ( newFilter : string , oldFilter : string ) : void {
182
174
if ( ! newFilter ) {
183
175
this . $nextTick ( this . scrollInterfaceIntoView ) ;
176
+
177
+ if ( oldFilter ) {
178
+ this . sidebar ! . scrollTop = 0 ;
179
+ }
184
180
} else {
185
- this . currentInterface = '' ;
181
+ this . setInterface ( '' ) ;
186
182
187
183
if ( ! oldFilter ) {
188
- document . querySelector ( '. sidebar' ) ! . scrollTop = 0 ;
184
+ this . sidebar ! . scrollTop = 0 ;
189
185
}
190
186
}
191
187
} ,
@@ -215,12 +211,19 @@ export default defineComponent({
215
211
console . error ( e ) ;
216
212
}
217
213
218
- this . setInterface ( ) ;
214
+ if ( location . hash . startsWith ( '#' ) ) {
215
+ this . setInterface ( location . hash . substring ( 1 ) , true ) ;
216
+ }
219
217
220
218
window . addEventListener (
221
219
'hashchange' ,
222
220
( ) => {
223
- this . setInterface ( ) ;
221
+ if ( this . skipNextHashChange ) {
222
+ this . skipNextHashChange = false ;
223
+ return ;
224
+ }
225
+
226
+ this . setInterface ( location . hash . substring ( 1 ) ) ;
224
227
} ,
225
228
false ,
226
229
) ;
@@ -284,42 +287,46 @@ export default defineComponent({
284
287
} ,
285
288
} ,
286
289
methods : {
287
- setInterface ( ) : void {
288
- let currentInterface = location . hash ;
289
- let currentMethod = '' ;
290
-
291
- if ( currentInterface [ 0 ] === '#' ) {
292
- const split = currentInterface . substring ( 1 ) . split ( '/' , 2 ) ;
293
- currentInterface = split [ 0 ] ;
294
-
295
- if ( split [ 1 ] ) {
296
- currentMethod = split [ 1 ] ;
297
- }
298
- }
290
+ setInterface ( interfaceAndMethod : string , setFromUrl = false ) : void {
291
+ const split = interfaceAndMethod . split ( '/' , 2 ) ;
292
+ let currentInterface : string | null = split [ 0 ] ;
293
+ let currentMethod : string | null = split . length > 1 ? split [ 1 ] : null ;
299
294
300
295
if ( ! Object . hasOwn ( this . interfaces , currentInterface ) ) {
301
- currentInterface = '' ;
302
- currentMethod = '' ;
303
- } else if ( ! Object . hasOwn ( this . interfaces [ currentInterface ] , currentMethod ) ) {
304
- currentMethod = '' ;
296
+ currentInterface = null ;
297
+ currentMethod = null ;
298
+ } else if ( currentMethod !== null && ! Object . hasOwn ( this . interfaces [ currentInterface ] , currentMethod ) ) {
299
+ currentMethod = null ;
305
300
}
306
301
307
- const interfaceChanged = this . currentInterface !== currentInterface ;
302
+ this . currentInterface = currentInterface || '' ;
308
303
309
- this . currentInterface = currentInterface ;
304
+ if ( currentInterface ) {
305
+ document . title = `${ currentInterface } – Steam Web API Documentation` ;
306
+ } else {
307
+ document . title = `Steam Web API Documentation` ;
308
+ }
310
309
311
- if ( interfaceChanged ) {
312
- // Have to scroll manually because location.hash doesn't exist in DOM as target yet
313
- this . $nextTick ( ( ) => {
314
- const element = document . getElementById ( ` ${ currentInterface } / ${ currentMethod } ` ) ;
310
+ // Since we won't scroll to a method, scroll to top (as there is no element with just interface id)
311
+ if ( document . scrollingElement && ! currentMethod ) {
312
+ document . scrollingElement . scrollTop = 0 ;
313
+ }
315
314
316
- if ( element ) {
317
- element . scrollIntoView ( {
318
- block : 'start' ,
319
- } ) ;
320
- }
321
- } ) ;
315
+ if ( setFromUrl ) {
316
+ return ;
322
317
}
318
+
319
+ this . $nextTick ( ( ) => {
320
+ this . skipNextHashChange = true ;
321
+
322
+ if ( currentMethod ) {
323
+ location . hash = `#${ currentInterface } /${ currentMethod } ` ;
324
+ } else if ( currentInterface ) {
325
+ location . hash = `#${ currentInterface } ` ;
326
+ } else {
327
+ location . hash = '' ;
328
+ }
329
+ } ) ;
323
330
} ,
324
331
fillSteamidParameter ( ) : void {
325
332
if ( ! this . userData . steamid ) {
@@ -590,19 +597,23 @@ export default defineComponent({
590
597
localStorage . setItem ( 'favorites' , JSON . stringify ( [ ...this . userData . favorites ] ) ) ;
591
598
} ,
592
599
navigateSidebar ( direction : number ) : void {
593
- const keys = Object . keys ( this . filteredInterfaces ) ;
594
-
595
- const size = keys . length ;
596
- const index = keys . indexOf ( this . currentInterface ) + direction ;
600
+ const entries = Object . entries ( this . filteredInterfaces ) ;
601
+ const index = entries . findIndex ( ( x ) => x [ 0 ] === this . currentInterface ) + direction ;
602
+ const size = entries . length ;
603
+ const [ interfaceName , methods ] = entries [ ( ( index % size ) + size ) % size ] ;
604
+ const firstMethodName = Object . keys ( methods ) [ 0 ] ;
597
605
598
- this . currentInterface = keys [ ( ( index % size ) + size ) % size ] ;
606
+ this . setInterface ( ` ${ interfaceName } / ${ firstMethodName } ` ) ;
599
607
this . scrollInterfaceIntoView ( ) ;
608
+
609
+ // This is trash, but the focus gets lost because of location.hash change
610
+ this . $nextTick ( ( ) => {
611
+ this . inputSearch ?. focus ( ) ;
612
+ } ) ;
600
613
} ,
601
614
focusApiKey ( ) : void {
602
- location . hash = '' ;
603
-
604
- this . currentInterface = '' ;
605
615
this . currentFilter = '' ;
616
+ this . setInterface ( '' ) ;
606
617
607
618
this . $nextTick ( ( ) => {
608
619
const element = this . hasValidAccessToken ? this . inputAccessToken : this . inputApiKey ;
@@ -612,7 +623,7 @@ export default defineComponent({
612
623
}
613
624
} ) ;
614
625
} ,
615
- onSearchInput ( e : InputEvent ) {
626
+ onSearchInput ( e : Event ) {
616
627
requestAnimationFrame ( ( ) => {
617
628
this . currentFilter = ( e . target as HTMLInputElement ) . value ;
618
629
} ) ;
0 commit comments