|
5 | 5 | wait: 'load', |
6 | 6 |
|
7 | 7 | events: { |
8 | | - showField: 'scrollToSelectedDashicon', |
| 8 | + showField: 'scrollToSelectedIcon', |
9 | 9 | 'input .acf-icon_url': 'onUrlChange', |
10 | | - 'click .acf-icon-picker-dashicon': 'onDashiconClick', |
11 | | - 'focus .acf-icon-picker-dashicon-radio': 'onDashiconRadioFocus', |
12 | | - 'blur .acf-icon-picker-dashicon-radio': 'onDashiconRadioBlur', |
13 | | - 'keydown .acf-icon-picker-dashicon-radio': 'onDashiconKeyDown', |
14 | | - 'input .acf-dashicons-search-input': 'onDashiconSearch', |
15 | | - 'keydown .acf-dashicons-search-input': 'onDashiconSearchKeyDown', |
| 10 | + 'click .acf-icon-picker-list-icon': 'onIconClick', |
| 11 | + 'focus .acf-icon-picker-list-icon-radio': 'onIconRadioFocus', |
| 12 | + 'blur .acf-icon-picker-list-icon-radio': 'onIconRadioBlur', |
| 13 | + 'keydown .acf-icon-picker-list-icon-radio': 'onIconKeyDown', |
| 14 | + 'input .acf-icon-list-search-input': 'onIconSearch', |
| 15 | + 'keydown .acf-icon-list-search-input': 'onIconSearchKeyDown', |
16 | 16 | 'click .acf-icon-picker-media-library-button': |
17 | 17 | 'onMediaLibraryButtonClick', |
18 | 18 | 'click .acf-icon-picker-media-library-preview': |
|
36 | 36 | }, |
37 | 37 |
|
38 | 38 | $selectedIcon() { |
39 | | - return this.$( '.acf-icon-picker-dashicon.active' ); |
| 39 | + return this.$( '.acf-icon-picker-list-icon.active' ); |
40 | 40 | }, |
41 | 41 |
|
42 | 42 | $selectedRadio() { |
43 | | - return this.$( '.acf-icon-picker-dashicon.active input' ); |
| 43 | + return this.$( '.acf-icon-picker-list-icon.active input' ); |
44 | 44 | }, |
45 | 45 |
|
46 | | - $dashiconsList() { |
47 | | - return this.$( '.acf-dashicons-list' ); |
| 46 | + $iconsList() { |
| 47 | + return this.$( '.acf-icon-list:visible' ); |
48 | 48 | }, |
49 | 49 |
|
50 | 50 | $mediaLibraryButton() { |
|
64 | 64 | // Store the type and value object. |
65 | 65 | this.set( 'typeAndValue', typeAndValue ); |
66 | 66 |
|
67 | | - // Any time any acf tab is clicked, we will re-scroll to the selected dashicon. |
| 67 | + // Any time any acf tab is clicked, we will re-scroll to the selected icon. |
68 | 68 | $( '.acf-tab-button' ).on( 'click', () => { |
69 | | - this.initializeDashiconsTab( this.get( 'typeAndValue' ) ); |
| 69 | + this.initializeIconLists( this.get( 'typeAndValue' ) ); |
70 | 70 | } ); |
71 | 71 |
|
72 | 72 | // Fire the action which lets people know the state has been updated. |
|
75 | 75 | typeAndValue |
76 | 76 | ); |
77 | 77 |
|
78 | | - this.initializeDashiconsTab( typeAndValue ); |
| 78 | + this.initializeIconLists( typeAndValue ); |
79 | 79 | this.alignMediaLibraryTabToCurrentValue( typeAndValue ); |
80 | 80 | }, |
81 | 81 |
|
|
85 | 85 | this.get( 'name' ) + '/type_and_value_change', |
86 | 86 | ( newTypeAndValue ) => { |
87 | 87 | // Align the visual state of each tab to the current value. |
88 | | - this.alignDashiconsTabToCurrentValue( newTypeAndValue ); |
| 88 | + this.alignIconListTabsToCurrentValue( newTypeAndValue ); |
89 | 89 | this.alignMediaLibraryTabToCurrentValue( newTypeAndValue ); |
90 | 90 | this.alignUrlTabToCurrentValue( newTypeAndValue ); |
91 | 91 | } |
|
112 | 112 | this.set( 'typeAndValue', typeAndValue ); |
113 | 113 | }, |
114 | 114 |
|
115 | | - scrollToSelectedDashicon() { |
| 115 | + scrollToSelectedIcon() { |
116 | 116 | const innerElement = this.$selectedIcon(); |
117 | 117 |
|
118 | 118 | // If no icon is selected, do nothing. |
119 | 119 | if ( innerElement.length === 0 ) { |
120 | 120 | return; |
121 | 121 | } |
122 | 122 |
|
123 | | - const scrollingDiv = this.$dashiconsList(); |
| 123 | + const scrollingDiv = innerElement.closest( '.acf-icon-list' ); |
124 | 124 | scrollingDiv.scrollTop( 0 ); |
125 | 125 |
|
126 | 126 | const distance = innerElement.position().top - 50; |
|
132 | 132 | scrollingDiv.scrollTop( distance ); |
133 | 133 | }, |
134 | 134 |
|
135 | | - initializeDashiconsTab( typeAndValue ) { |
136 | | - const dashicons = this.getDashiconsList() || []; |
137 | | - this.set( 'dashicons', dashicons ); |
138 | | - this.renderDashiconList(); |
139 | | - this.initializeSelectedDashicon( typeAndValue ); |
| 135 | + initializeIconLists( typeAndValue ) { |
| 136 | + const self = this; |
| 137 | + |
| 138 | + this.$( '.acf-icon-list' ).each( function( i ) { |
| 139 | + const tabName = $( this ).data( 'parent-tab' ); |
| 140 | + const icons = self.getIconsList( tabName ) || []; |
| 141 | + self.set( tabName, icons ); |
| 142 | + self.renderIconList( $( this ) ); |
| 143 | + |
| 144 | + if ( typeAndValue.type === tabName ) { |
| 145 | + // Select the correct icon. |
| 146 | + self.selectIcon( $( this ), typeAndValue.value, false ).then( () => { |
| 147 | + // Scroll to the selected icon. |
| 148 | + self.scrollToSelectedIcon(); |
| 149 | + } ); |
| 150 | + } |
| 151 | + } ); |
140 | 152 | }, |
141 | 153 |
|
142 | | - initializeSelectedDashicon( typeAndValue ) { |
143 | | - if ( typeAndValue.type !== 'dashicons' ) { |
144 | | - return; |
145 | | - } |
146 | | - // Select the correct dashicon. |
147 | | - this.selectDashicon( typeAndValue.value, false ).then( () => { |
148 | | - // Scroll to the selected dashicon. |
149 | | - this.scrollToSelectedDashicon(); |
| 154 | + alignIconListTabsToCurrentValue( typeAndValue ) { |
| 155 | + const icons = this.$( '.acf-icon-list' ).filter( |
| 156 | + function () { |
| 157 | + return ( |
| 158 | + $( this ).data( 'parent-tab' ) !== typeAndValue.type |
| 159 | + ); |
| 160 | + } |
| 161 | + ); |
| 162 | + const self = this; |
| 163 | + icons.each( function () { |
| 164 | + self.unselectIcon( $( this ) ); |
150 | 165 | } ); |
151 | 166 | }, |
152 | 167 |
|
153 | | - alignDashiconsTabToCurrentValue( typeAndValue ) { |
154 | | - if ( typeAndValue.type !== 'dashicons' ) { |
155 | | - this.unselectDashicon(); |
| 168 | + renderIconHTML( tabName, icon ) { |
| 169 | + const id = `${ this.get( 'name' ) }-${ icon.key }`; |
| 170 | + |
| 171 | + let style = ''; |
| 172 | + if ( 'dashicons' !== tabName ) { |
| 173 | + style = `background: center / contain url( ${ acf.strEscape( |
| 174 | + icon.url |
| 175 | + ) } ) no-repeat;`; |
156 | 176 | } |
157 | | - }, |
158 | 177 |
|
159 | | - renderDashiconHTML( dashicon ) { |
160 | | - const id = `${ this.get( 'name' ) }-${ dashicon.key }`; |
161 | | - return `<div class="dashicons ${ acf.strEscape( |
162 | | - dashicon.key |
163 | | - ) } acf-icon-picker-dashicon" data-icon="${ acf.strEscape( |
164 | | - dashicon.key |
| 178 | + return `<div class="${ tabName } ${ acf.strEscape( |
| 179 | + icon.key |
| 180 | + ) } acf-icon-picker-list-icon" role="radio" data-icon="${ acf.strEscape( |
| 181 | + icon.key |
| 182 | + ) }" style="${ style }" title="${ acf.strEscape( |
| 183 | + icon.label |
165 | 184 | ) }"> |
166 | 185 | <label for="${ acf.strEscape( id ) }">${ acf.strEscape( |
167 | | - dashicon.label |
| 186 | + icon.label |
168 | 187 | ) }</label> |
169 | 188 | <input id="${ acf.strEscape( |
170 | 189 | id |
171 | | - ) }" type="radio" class="acf-icon-picker-dashicon-radio" name="acf-icon-picker-dashicon-radio" value="${ acf.strEscape( |
172 | | - dashicon.key |
| 190 | + ) }" type="radio" class="acf-icon-picker-list-icon-radio" name="acf-icon-picker-list-icon-radio" value="${ acf.strEscape( |
| 191 | + icon.key |
173 | 192 | ) }"> |
174 | 193 | </div>`; |
175 | 194 | }, |
176 | 195 |
|
177 | | - renderDashiconList() { |
178 | | - const dashicons = this.get( 'dashicons' ); |
| 196 | + renderIconList( $el ) { |
| 197 | + const tabName = $el.data( 'parent-tab' ); |
| 198 | + const icons = this.get( tabName ); |
179 | 199 |
|
180 | | - this.$dashiconsList().empty(); |
181 | | - dashicons.forEach( ( dashicon ) => { |
182 | | - this.$dashiconsList().append( |
183 | | - this.renderDashiconHTML( dashicon ) |
184 | | - ); |
185 | | - } ); |
| 200 | + $el.empty(); |
| 201 | + if ( icons ) { |
| 202 | + icons.forEach( ( icon ) => { |
| 203 | + const iconHTML = this.renderIconHTML( tabName, icon ); |
| 204 | + $el.append( iconHTML ); |
| 205 | + } ); |
| 206 | + } |
186 | 207 | }, |
187 | 208 |
|
188 | | - getDashiconsList() { |
189 | | - const iconPickeri10n = acf.get( 'iconPickeri10n' ) || []; |
| 209 | + getIconsList( tabName ) { |
| 210 | + if ( 'dashicons' === tabName ) { |
| 211 | + const iconPickeri10n = acf.get( 'iconPickeri10n' ) || []; |
190 | 212 |
|
191 | | - const dashicons = Object.entries( iconPickeri10n ).map( |
192 | | - ( [ key, value ] ) => { |
193 | | - return { |
194 | | - key, |
195 | | - label: value, |
196 | | - }; |
197 | | - } |
198 | | - ); |
| 213 | + return Object.entries( iconPickeri10n ).map( |
| 214 | + ( [ key, value ] ) => { |
| 215 | + return { |
| 216 | + key, |
| 217 | + label: value, |
| 218 | + }; |
| 219 | + } |
| 220 | + ); |
| 221 | + } |
199 | 222 |
|
200 | | - return dashicons; |
| 223 | + return acf.get( `iconPickerIcons_${ tabName }` ); |
201 | 224 | }, |
202 | 225 |
|
203 | | - getDashiconsBySearch( searchTerm ) { |
| 226 | + getIconsBySearch( searchTerm, tabName ) { |
204 | 227 | const lowercaseSearchTerm = searchTerm.toLowerCase(); |
205 | | - const dashicons = this.getDashiconsList(); |
| 228 | + const icons = this.getIconsList( tabName); |
206 | 229 |
|
207 | | - const filteredDashicons = dashicons.filter( function ( icon ) { |
| 230 | + const filteredIcons = icons.filter( function ( icon ) { |
208 | 231 | const lowercaseIconLabel = icon.label.toLowerCase(); |
209 | 232 | return lowercaseIconLabel.indexOf( lowercaseSearchTerm ) > -1; |
210 | 233 | } ); |
211 | 234 |
|
212 | | - return filteredDashicons; |
| 235 | + return filteredIcons; |
213 | 236 | }, |
214 | 237 |
|
215 | | - selectDashicon( dashicon, setFocus = true ) { |
216 | | - this.set( 'selectedDashicon', dashicon ); |
| 238 | + selectIcon( $el, icon, setFocus = true ) { |
| 239 | + this.set( 'selectedIcon', icon ); |
217 | 240 |
|
218 | 241 | // Select the new one. |
219 | | - const $newIcon = this.$dashiconsList().find( |
220 | | - '.acf-icon-picker-dashicon[data-icon="' + dashicon + '"]' |
| 242 | + const $newIcon = $el.find( |
| 243 | + '.acf-icon-picker-list-icon[data-icon="' + icon + '"]' |
221 | 244 | ); |
222 | 245 | $newIcon.addClass( 'active' ); |
223 | 246 |
|
|
228 | 251 | $input.trigger( 'focus' ); |
229 | 252 | } |
230 | 253 |
|
231 | | - this.updateTypeAndValue( 'dashicons', dashicon ); |
| 254 | + this.updateTypeAndValue( $el.data( 'parent-tab' ), icon ); |
232 | 255 |
|
233 | 256 | return thePromise; |
234 | 257 | }, |
235 | 258 |
|
236 | | - unselectDashicon() { |
| 259 | + unselectIcon( $el ) { |
237 | 260 | // Remove the currently active dashicon, if any. |
238 | | - this.$dashiconsList() |
239 | | - .find( '.acf-icon-picker-dashicon' ) |
| 261 | + $el |
| 262 | + .find( '.acf-icon-picker-list-icon' ) |
240 | 263 | .removeClass( 'active' ); |
241 | | - this.set( 'selectedDashicon', false ); |
| 264 | + this.set( 'selectedIcon', false ); |
242 | 265 | }, |
243 | 266 |
|
244 | | - onDashiconRadioFocus( e ) { |
245 | | - const dashicon = e.target.value; |
| 267 | + onIconRadioFocus( e ) { |
| 268 | + const icon = e.target.value; |
| 269 | + const $tabs = this.$( e.target ).closest( |
| 270 | + '.acf-icon-picker-tabs' |
| 271 | + ); |
| 272 | + const $iconsList = $tabs.find( '.acf-icon-list' ); |
246 | 273 |
|
247 | | - const $newIcon = this.$dashiconsList().find( |
248 | | - '.acf-icon-picker-dashicon[data-icon="' + dashicon + '"]' |
| 274 | + const $newIcon = $iconsList.find( |
| 275 | + '.acf-icon-picker-list-icon[data-icon="' + icon + '"]' |
249 | 276 | ); |
250 | 277 | $newIcon.addClass( 'focus' ); |
251 | 278 |
|
252 | 279 | // If this is a different icon than previously selected, select it. |
253 | | - if ( this.get( 'selectedDashicon' ) !== dashicon ) { |
254 | | - this.unselectDashicon(); |
255 | | - this.selectDashicon( dashicon ); |
| 280 | + if ( this.get( 'selectedIcon' ) !== icon ) { |
| 281 | + this.unselectIcon( $iconsList ); |
| 282 | + this.selectIcon( $iconsList, icon ); |
256 | 283 | } |
257 | 284 | }, |
258 | 285 |
|
259 | | - onDashiconRadioBlur( e ) { |
| 286 | + onIconRadioBlur( e ) { |
260 | 287 | const icon = this.$( e.target ); |
261 | 288 | const iconParent = icon.parent(); |
262 | 289 |
|
263 | 290 | iconParent.removeClass( 'focus' ); |
264 | 291 | }, |
265 | 292 |
|
266 | | - onDashiconClick( e ) { |
| 293 | + onIconClick( e ) { |
267 | 294 | e.preventDefault(); |
| 295 | + const $iconList = this.$( e.target ).closest( |
| 296 | + '.acf-icon-list' |
| 297 | + ); |
| 298 | + const $iconElement = this.$( e.target ); |
| 299 | + const icon = $iconElement.find( 'input' ).val(); |
268 | 300 |
|
269 | | - const icon = this.$( e.target ); |
270 | | - const dashicon = icon.find( 'input' ).val(); |
271 | | - |
272 | | - const $newIcon = this.$dashiconsList().find( |
273 | | - '.acf-icon-picker-dashicon[data-icon="' + dashicon + '"]' |
| 301 | + const $newIconElement = $iconList.find( |
| 302 | + '.acf-icon-picker-list-icon[data-icon="' + icon + '"]' |
274 | 303 | ); |
275 | 304 |
|
276 | | - // By forcing focus on the input, we fire onDashiconRadioFocus. |
277 | | - $newIcon.find( 'input' ).prop( 'checked', true ).trigger( 'focus' ); |
| 305 | + // By forcing focus on the input, we fire onIconRadioFocus. |
| 306 | + $newIconElement.find( 'input' ).prop( 'checked', true ).trigger( 'focus' ); |
278 | 307 | }, |
279 | 308 |
|
280 | | - onDashiconSearch( e ) { |
| 309 | + onIconSearch( e ) { |
| 310 | + const $tabs = this.$( e.target ).closest( |
| 311 | + '.acf-icon-picker-tabs' |
| 312 | + ); |
| 313 | + const $iconList = $tabs.find( '.acf-icon-list' ); |
| 314 | + const tabName = $tabs.data( 'tab' ); |
281 | 315 | const searchTerm = e.target.value; |
282 | | - const filteredDashicons = this.getDashiconsBySearch( searchTerm ); |
| 316 | + const filteredIcons = this.getIconsBySearch( searchTerm, tabName ); |
283 | 317 |
|
284 | | - if ( filteredDashicons.length > 0 || ! searchTerm ) { |
285 | | - this.set( 'dashicons', filteredDashicons ); |
286 | | - this.$( '.acf-dashicons-list-empty' ).hide(); |
287 | | - this.$( '.acf-dashicons-list ' ).show(); |
288 | | - this.renderDashiconList(); |
| 318 | + if ( filteredIcons.length > 0 || ! searchTerm ) { |
| 319 | + this.set( tabName, filteredIcons ); |
| 320 | + $tabs.find( '.acf-icon-list-empty' ).hide(); |
| 321 | + $tabs.find( '.acf-icon-list ' ).show(); |
| 322 | + this.renderIconList( $iconList ); |
289 | 323 |
|
290 | 324 | // Announce change of data to screen readers. |
291 | 325 | wp.a11y.speak( |
|
300 | 334 | ? searchTerm.substring( 0, 30 ) + '…' |
301 | 335 | : searchTerm; |
302 | 336 |
|
303 | | - this.$( '.acf-dashicons-list ' ).hide(); |
304 | | - this.$( '.acf-dashicons-list-empty' ) |
305 | | - .find( '.acf-invalid-dashicon-search-term' ) |
| 337 | + $tabs.find( '.acf-icon-list ' ).hide(); |
| 338 | + $tabs.find( '.acf-icon-list-empty' ) |
| 339 | + .find( '.acf-invalid-icon-list-search-term' ) |
306 | 340 | .text( visualSearchTerm ); |
307 | | - this.$( '.acf-dashicons-list-empty' ).css( 'display', 'flex' ); |
308 | | - this.$( '.acf-dashicons-list-empty' ).show(); |
| 341 | + $tabs.find( '.acf-icon-list-empty' ).css( 'display', 'flex' ); |
| 342 | + $tabs.find( '.acf-icon-list-empty' ).show(); |
309 | 343 |
|
310 | 344 | // Announce change of data to screen readers. |
311 | 345 | wp.a11y.speak( |
|
315 | 349 | } |
316 | 350 | }, |
317 | 351 |
|
318 | | - onDashiconSearchKeyDown( e ) { |
| 352 | + onIconSearchKeyDown( e ) { |
319 | 353 | // Check if the pressed key is Enter (key code 13) |
320 | 354 | if ( e.which === 13 ) { |
321 | 355 | // Prevent submitting the entire form if someone presses enter after searching. |
322 | 356 | e.preventDefault(); |
323 | 357 | } |
324 | 358 | }, |
325 | 359 |
|
326 | | - onDashiconKeyDown( e ) { |
| 360 | + onIconKeyDown( e ) { |
327 | 361 | if ( e.which === 13 ) { |
328 | 362 | // If someone presses enter while an icon is focused, prevent the form from submitting. |
329 | 363 | e.preventDefault(); |
|
0 commit comments