@@ -78,7 +78,7 @@ Requires core.js and SelectBox.js.
78
78
remove_link . className = 'selector-remove' ;
79
79
80
80
// <div class="selector-chosen">
81
- const selector_chosen = quickElement ( 'div' , selector_div ) ;
81
+ const selector_chosen = quickElement ( 'div' , selector_div , '' , 'id' , field_id + '_selector_chosen' ) ;
82
82
selector_chosen . className = 'selector-chosen' ;
83
83
const title_chosen = quickElement ( 'h2' , selector_chosen , interpolate ( gettext ( 'Chosen %s' ) + ' ' , [ field_name ] ) ) ;
84
84
quickElement (
@@ -93,9 +93,30 @@ Requires core.js and SelectBox.js.
93
93
[ field_name ]
94
94
)
95
95
) ;
96
+
97
+ const filter_selected_p = quickElement ( 'p' , selector_chosen , '' , 'id' , field_id + '_filter_selected' ) ;
98
+ filter_selected_p . className = 'selector-filter' ;
99
+
100
+ const search_filter_selected_label = quickElement ( 'label' , filter_selected_p , '' , 'for' , field_id + '_selected_input' ) ;
101
+
102
+ quickElement (
103
+ 'span' , search_filter_selected_label , '' ,
104
+ 'class' , 'help-tooltip search-label-icon' ,
105
+ 'title' , interpolate ( gettext ( "Type into this box to filter down the list of selected %s." ) , [ field_name ] )
106
+ ) ;
107
+
108
+ filter_selected_p . appendChild ( document . createTextNode ( ' ' ) ) ;
109
+
110
+ const filter_selected_input = quickElement ( 'input' , filter_selected_p , '' , 'type' , 'text' , 'placeholder' , gettext ( "Filter" ) ) ;
111
+ filter_selected_input . id = field_id + '_selected_input' ;
96
112
97
113
const to_box = quickElement ( 'select' , selector_chosen , '' , 'id' , field_id + '_to' , 'multiple' , '' , 'size' , from_box . size , 'name' , from_box . name ) ;
98
114
to_box . className = 'filtered' ;
115
+
116
+ const warning_footer = quickElement ( 'div' , selector_chosen , '' , 'class' , 'list-footer-display' ) ;
117
+ quickElement ( 'span' , warning_footer , '' , 'id' , field_id + '_list-footer-display-text' ) ;
118
+ quickElement ( 'span' , warning_footer , ' (click to clear)' , 'class' , 'list-footer-display__clear' ) ;
119
+
99
120
const clear_all = quickElement ( 'a' , selector_chosen , gettext ( 'Remove all' ) , 'title' , interpolate ( gettext ( 'Click to remove all chosen %s at once.' ) , [ field_name ] ) , 'href' , '#' , 'id' , field_id + '_remove_all_link' ) ;
100
121
clear_all . className = 'selector-clearall' ;
101
122
@@ -106,6 +127,8 @@ Requires core.js and SelectBox.js.
106
127
if ( elem . classList . contains ( 'active' ) ) {
107
128
move_func ( from , to ) ;
108
129
SelectFilter . refresh_icons ( field_id ) ;
130
+ SelectFilter . refresh_filtered_selects ( field_id ) ;
131
+ SelectFilter . refresh_filtered_warning ( field_id ) ;
109
132
}
110
133
e . preventDefault ( ) ;
111
134
} ;
@@ -121,14 +144,29 @@ Requires core.js and SelectBox.js.
121
144
clear_all . addEventListener ( 'click' , function ( e ) {
122
145
move_selection ( e , this , SelectBox . move_all , field_id + '_to' , field_id + '_from' ) ;
123
146
} ) ;
147
+ warning_footer . addEventListener ( 'click' , function ( e ) {
148
+ filter_selected_input . value = '' ;
149
+ SelectBox . filter ( field_id + '_to' , '' ) ;
150
+ SelectFilter . refresh_filtered_warning ( field_id ) ;
151
+ SelectFilter . refresh_icons ( field_id ) ;
152
+ } ) ;
124
153
filter_input . addEventListener ( 'keypress' , function ( e ) {
125
- SelectFilter . filter_key_press ( e , field_id ) ;
154
+ SelectFilter . filter_key_press ( e , field_id , '_from' , '_to' ) ;
126
155
} ) ;
127
156
filter_input . addEventListener ( 'keyup' , function ( e ) {
128
- SelectFilter . filter_key_up ( e , field_id ) ;
157
+ SelectFilter . filter_key_up ( e , field_id , '_from' ) ;
129
158
} ) ;
130
159
filter_input . addEventListener ( 'keydown' , function ( e ) {
131
- SelectFilter . filter_key_down ( e , field_id ) ;
160
+ SelectFilter . filter_key_down ( e , field_id , '_from' , '_to' ) ;
161
+ } ) ;
162
+ filter_selected_input . addEventListener ( 'keypress' , function ( e ) {
163
+ SelectFilter . filter_key_press ( e , field_id , '_to' , '_from' ) ;
164
+ } ) ;
165
+ filter_selected_input . addEventListener ( 'keyup' , function ( e ) {
166
+ SelectFilter . filter_key_up ( e , field_id , '_to' , '_selected_input' ) ;
167
+ } ) ;
168
+ filter_selected_input . addEventListener ( 'keydown' , function ( e ) {
169
+ SelectFilter . filter_key_down ( e , field_id , '_to' , '_from' ) ;
132
170
} ) ;
133
171
selector_div . addEventListener ( 'change' , function ( e ) {
134
172
if ( e . target . tagName === 'SELECT' ) {
@@ -146,6 +184,7 @@ Requires core.js and SelectBox.js.
146
184
}
147
185
} ) ;
148
186
from_box . closest ( 'form' ) . addEventListener ( 'submit' , function ( ) {
187
+ SelectBox . filter ( field_id + '_to' , '' ) ;
149
188
SelectBox . select_all ( field_id + '_to' ) ;
150
189
} ) ;
151
190
SelectBox . init ( field_id + '_from' ) ;
@@ -163,6 +202,20 @@ Requires core.js and SelectBox.js.
163
202
field . required = false ;
164
203
return any_selected ;
165
204
} ,
205
+ refresh_filtered_warning : function ( field_id ) {
206
+ const count = SelectBox . get_hidden_node_count ( field_id + '_to' ) ;
207
+ const selector = document . getElementById ( field_id + '_selector_chosen' ) ;
208
+ const warning = document . getElementById ( field_id + '_list-footer-display-text' ) ;
209
+ selector . className = selector . className . replace ( 'selector-chosen--with-filtered' , '' ) ;
210
+ warning . textContent = interpolate ( gettext ( '%s selected options not visible' ) , [ count ] ) ;
211
+ if ( count > 0 ) {
212
+ selector . className += ' selector-chosen--with-filtered' ;
213
+ }
214
+ } ,
215
+ refresh_filtered_selects : function ( field_id ) {
216
+ SelectBox . filter ( field_id + '_from' , document . getElementById ( field_id + "_input" ) . value ) ;
217
+ SelectBox . filter ( field_id + '_to' , document . getElementById ( field_id + "_selected_input" ) . value ) ;
218
+ } ,
166
219
refresh_icons : function ( field_id ) {
167
220
const from = document . getElementById ( field_id + '_from' ) ;
168
221
const to = document . getElementById ( field_id + '_to' ) ;
@@ -172,39 +225,47 @@ Requires core.js and SelectBox.js.
172
225
// Active if the corresponding box isn't empty
173
226
document . getElementById ( field_id + '_add_all_link' ) . classList . toggle ( 'active' , from . querySelector ( 'option' ) ) ;
174
227
document . getElementById ( field_id + '_remove_all_link' ) . classList . toggle ( 'active' , to . querySelector ( 'option' ) ) ;
228
+ SelectFilter . refresh_filtered_warning ( field_id ) ;
175
229
} ,
176
- filter_key_press : function ( event , field_id ) {
177
- const from = document . getElementById ( field_id + '_from' ) ;
230
+ filter_key_press : function ( event , field_id , source , target ) {
231
+ const source_box = document . getElementById ( field_id + source ) ;
178
232
// don't submit form if user pressed Enter
179
233
if ( ( event . which && event . which === 13 ) || ( event . keyCode && event . keyCode === 13 ) ) {
180
- from . selectedIndex = 0 ;
181
- SelectBox . move ( field_id + '_from' , field_id + '_to' ) ;
182
- from . selectedIndex = 0 ;
234
+ source_box . selectedIndex = 0 ;
235
+ SelectBox . move ( field_id + source , field_id + target ) ;
236
+ source_box . selectedIndex = 0 ;
183
237
event . preventDefault ( ) ;
184
238
}
185
239
} ,
186
- filter_key_up : function ( event , field_id ) {
187
- const from = document . getElementById ( field_id + '_from' ) ;
188
- const temp = from . selectedIndex ;
189
- SelectBox . filter ( field_id + '_from' , document . getElementById ( field_id + '_input' ) . value ) ;
190
- from . selectedIndex = temp ;
240
+ filter_key_up : function ( event , field_id , source , filter_input ) {
241
+ const input = filter_input || '_input' ;
242
+ const source_box = document . getElementById ( field_id + source ) ;
243
+ const temp = source_box . selectedIndex ;
244
+ SelectBox . filter ( field_id + source , document . getElementById ( field_id + input ) . value ) ;
245
+ source_box . selectedIndex = temp ;
246
+ SelectFilter . refresh_filtered_warning ( field_id ) ;
247
+ SelectFilter . refresh_icons ( field_id ) ;
191
248
} ,
192
- filter_key_down : function ( event , field_id ) {
193
- const from = document . getElementById ( field_id + '_from' ) ;
249
+ filter_key_down : function ( event , field_id , source , target ) {
250
+ const source_box = document . getElementById ( field_id + source ) ;
251
+ // right key (39) or left key (37)
252
+ const direction = source === '_from' ? 39 : 37 ;
194
253
// right arrow -- move across
195
- if ( ( event . which && event . which === 39 ) || ( event . keyCode && event . keyCode === 39 ) ) {
196
- const old_index = from . selectedIndex ;
197
- SelectBox . move ( field_id + '_from' , field_id + '_to' ) ;
198
- from . selectedIndex = ( old_index === from . length ) ? from . length - 1 : old_index ;
254
+ if ( ( event . which && event . which === direction ) || ( event . keyCode && event . keyCode === direction ) ) {
255
+ const old_index = source_box . selectedIndex ;
256
+ SelectBox . move ( field_id + source , field_id + target ) ;
257
+ SelectFilter . refresh_filtered_selects ( field_id ) ;
258
+ SelectFilter . refresh_filtered_warning ( field_id ) ;
259
+ source_box . selectedIndex = ( old_index === source_box . length ) ? source_box . length - 1 : old_index ;
199
260
return ;
200
261
}
201
262
// down arrow -- wrap around
202
263
if ( ( event . which && event . which === 40 ) || ( event . keyCode && event . keyCode === 40 ) ) {
203
- from . selectedIndex = ( from . length === from . selectedIndex + 1 ) ? 0 : from . selectedIndex + 1 ;
264
+ source_box . selectedIndex = ( source_box . length === source_box . selectedIndex + 1 ) ? 0 : source_box . selectedIndex + 1 ;
204
265
}
205
266
// up arrow -- wrap around
206
267
if ( ( event . which && event . which === 38 ) || ( event . keyCode && event . keyCode === 38 ) ) {
207
- from . selectedIndex = ( from . selectedIndex === 0 ) ? from . length - 1 : from . selectedIndex - 1 ;
268
+ source_box . selectedIndex = ( source_box . selectedIndex === 0 ) ? source_box . length - 1 : source_box . selectedIndex - 1 ;
208
269
}
209
270
}
210
271
} ;
0 commit comments