@@ -13,14 +13,14 @@ $(document).ready(function () {
1313 autoWidth : false ,
1414 paging : true ,
1515 pageLength : 25 ,
16- order : [ [ 0 , 'asc' ] ] , // Name ascending
16+ order : [ [ 0 , 'asc' ] ] ,
1717 columnDefs : [
18- { targets : 0 , responsivePriority : 1 , orderable : true } , // Name - always visible
19- { targets : 1 , responsivePriority : 4 , orderable : false } , // Game Type - not sortable
20- { targets : 2 , responsivePriority : 5 , orderable : false } , // Files - not sortable
21- { targets : 3 , responsivePriority : 3 , orderable : false } , // Remote Status - not sortable
22- { targets : 4 , responsivePriority : 6 , orderable : false } , // Popularity - not sortable
23- { targets : 5 , responsivePriority : 7 , orderable : false } // Image - not sortable
18+ { targets : 0 , responsivePriority : 2 , orderable : true } , // # (sort order)
19+ { targets : 1 , responsivePriority : 1 , orderable : true } , // Name - always visible
20+ { targets : 2 , responsivePriority : 5 , orderable : false } , // Map Files
21+ { targets : 3 , responsivePriority : 3 , orderable : false } , // Remote Status
22+ { targets : 4 , responsivePriority : 6 , orderable : false } , // Popularity
23+ { targets : 5 , responsivePriority : 7 , orderable : false } // Image
2424 ]
2525 } ) ;
2626 }
@@ -38,14 +38,95 @@ $(document).ready(function () {
3838 autoWidth : false ,
3939 paging : true ,
4040 pageLength : 25 ,
41- order : [ [ 0 , 'asc' ] ] , // Name ascending
41+ order : [ [ 0 , 'asc' ] ] ,
4242 columnDefs : [
43- { targets : 0 , responsivePriority : 1 , orderable : true } , // Name - always visible
44- { targets : 1 , responsivePriority : 4 , orderable : false } , // Path - not sortable
45- { targets : 2 , responsivePriority : 3 , orderable : false } , // Rotation Status - not sortable
46- { targets : 3 , responsivePriority : 5 , orderable : false } , // Modified - not sortable
47- { targets : 4 , responsivePriority : 2 , orderable : false } // Actions - not sortable
43+ { targets : 0 , responsivePriority : 1 , orderable : true } , // Name
44+ { targets : 1 , responsivePriority : 4 , orderable : false } , // Path
45+ { targets : 2 , responsivePriority : 3 , orderable : false } , // Rotation Status
46+ { targets : 3 , responsivePriority : 5 , orderable : false } , // Health
47+ { targets : 4 , responsivePriority : 6 , orderable : false } , // Modified
48+ { targets : 5 , responsivePriority : 2 , orderable : false } // Actions
4849 ]
4950 } ) ;
5051 }
52+
53+ // Push Map to Remote - Map Search
54+ initPushMapSearch ( ) ;
5155} ) ;
56+
57+ function initPushMapSearch ( ) {
58+ const $input = $ ( '#MapName' ) ;
59+ if ( $input . length === 0 ) return ;
60+
61+ $ ( document ) . off ( 'click.pushMapSearch' ) ;
62+
63+ let timer = null ;
64+ const $wrapper = $input . parent ( ) ;
65+ $wrapper . css ( 'position' , 'relative' ) ;
66+
67+ const $suggestions = $ ( '<div class="map-suggestions list-group position-absolute bg-white shadow" style="z-index:1050; max-height:300px; overflow-y:auto; display:none; width:100%;"></div>' ) ;
68+ $input . after ( $suggestions ) ;
69+
70+ function clearSuggestions ( ) {
71+ $suggestions . hide ( ) . empty ( ) ;
72+ }
73+
74+ function search ( term ) {
75+ if ( ! term || term . length < 2 ) { clearSuggestions ( ) ; return ; }
76+
77+ const gameTypeAttr = document . getElementById ( 'pushMapGameType' ) ;
78+ const gt = gameTypeAttr ? gameTypeAttr . value : '' ;
79+ const url = '/MapSearch/Maps?term=' + encodeURIComponent ( term ) + ( gt ? '&gameType=' + encodeURIComponent ( gt ) : '' ) ;
80+
81+ fetch ( url )
82+ . then ( r => r . json ( ) )
83+ . then ( results => {
84+ $suggestions . empty ( ) ;
85+ if ( ! Array . isArray ( results ) || results . length === 0 ) { clearSuggestions ( ) ; return ; }
86+
87+ results . forEach ( r => {
88+ const $item = $ ( '<button type="button" class="list-group-item list-group-item-action py-2 px-3 d-flex align-items-center" role="option"></button>' ) ;
89+ $item . append ( $ ( '<img>' ) . attr ( 'src' , r . imageUrl || '/images/noimage.jpg' ) . css ( { width : '40px' , height : '28px' , objectFit : 'cover' , borderRadius : '3px' } ) . addClass ( 'me-2' ) ) ;
90+ $item . append ( $ ( '<span>' ) . text ( r . text ) ) ;
91+ $item . on ( 'click' , function ( ) {
92+ $input . val ( r . text ) ;
93+ clearSuggestions ( ) ;
94+ } ) ;
95+ $suggestions . append ( $item ) ;
96+ } ) ;
97+
98+ if ( $suggestions . children ( ) . length > 0 ) {
99+ $suggestions . show ( ) ;
100+ } else {
101+ clearSuggestions ( ) ;
102+ }
103+ } )
104+ . catch ( ( ) => clearSuggestions ( ) ) ;
105+ }
106+
107+ $input . on ( 'input' , function ( ) {
108+ clearTimeout ( timer ) ;
109+ const term = $ ( this ) . val ( ) . trim ( ) ;
110+ timer = setTimeout ( ( ) => search ( term ) , 300 ) ;
111+ } ) ;
112+
113+ $input . on ( 'keydown' , function ( e ) {
114+ if ( ! $suggestions . is ( ':visible' ) ) return ;
115+ const $items = $suggestions . find ( '.list-group-item' ) ;
116+ if ( $items . length === 0 ) return ;
117+ let idx = $items . index ( $items . filter ( '.active' ) ) ;
118+ if ( e . key === 'ArrowDown' ) { e . preventDefault ( ) ; idx = ( idx + 1 ) % $items . length ; }
119+ else if ( e . key === 'ArrowUp' ) { e . preventDefault ( ) ; idx = ( idx <= 0 ? $items . length - 1 : idx - 1 ) ; }
120+ else if ( e . key === 'Enter' ) { e . preventDefault ( ) ; if ( idx >= 0 ) $items . eq ( idx ) . click ( ) ; return ; }
121+ else if ( e . key === 'Escape' ) { clearSuggestions ( ) ; return ; }
122+ else return ;
123+ $items . removeClass ( 'active' ) ;
124+ $items . eq ( idx ) . addClass ( 'active' ) [ 0 ] . scrollIntoView ( { block : 'nearest' } ) ;
125+ } ) ;
126+
127+ $ ( document ) . on ( 'click.pushMapSearch' , function ( e ) {
128+ if ( ! $ ( e . target ) . closest ( '#MapName' ) . length && ! $ ( e . target ) . closest ( '.map-suggestions' ) . length ) {
129+ clearSuggestions ( ) ;
130+ }
131+ } ) ;
132+ }
0 commit comments