PluginProbe ʕ •ᴥ•ʔ
Secure Custom Fields / 6.4.2
Secure Custom Fields v6.4.2
6.9.1 6.9.0 6.8.9 6.8.7 6.8.8 6.8.6 6.8.4 6.8.5 trunk 6.4.0-beta1 6.4.0-beta2 6.4.1 6.4.1-beta3 6.4.1-beta4 6.4.1-beta5 6.4.1-beta6 6.4.1-beta7 6.4.2 6.5.0 6.5.1 6.5.2 6.5.3 6.5.4 6.5.5 6.5.6 6.5.7 6.6.0 6.7.0 6.7.1 6.8.0 6.8.1 6.8.2 6.8.3
secure-custom-fields / assets / src / js / _acf-field-tab.js
secure-custom-fields / assets / src / js Last commit date
pro 1 year ago _acf-compatibility.js 1 year ago _acf-condition-types.js 1 year ago _acf-condition.js 1 year ago _acf-conditions.js 1 year ago _acf-field-accordion.js 1 year ago _acf-field-button-group.js 1 year ago _acf-field-checkbox.js 1 year ago _acf-field-color-picker.js 1 year ago _acf-field-date-picker.js 1 year ago _acf-field-date-time-picker.js 1 year ago _acf-field-file.js 1 year ago _acf-field-google-map.js 1 year ago _acf-field-icon-picker.js 1 year ago _acf-field-image.js 1 year ago _acf-field-link.js 1 year ago _acf-field-oembed.js 1 year ago _acf-field-page-link.js 1 year ago _acf-field-post-object.js 1 year ago _acf-field-radio.js 1 year ago _acf-field-range.js 1 year ago _acf-field-relationship.js 1 year ago _acf-field-select.js 1 year ago _acf-field-tab.js 1 year ago _acf-field-taxonomy.js 1 year ago _acf-field-time-picker.js 1 year ago _acf-field-true-false.js 1 year ago _acf-field-url.js 1 year ago _acf-field-user.js 1 year ago _acf-field-wysiwyg.js 1 year ago _acf-field.js 1 year ago _acf-fields.js 1 year ago _acf-helpers.js 1 year ago _acf-hooks.js 1 year ago _acf-internal-post-type.js 1 year ago _acf-media.js 1 year ago _acf-modal.js 1 year ago _acf-model.js 1 year ago _acf-notice.js 1 year ago _acf-panel.js 1 year ago _acf-popup.js 1 year ago _acf-postbox.js 1 year ago _acf-screen.js 1 year ago _acf-select2.js 1 year ago _acf-tinymce.js 1 year ago _acf-tooltip.js 1 year ago _acf-unload.js 1 year ago _acf-validation.js 1 year ago _acf.js 1 year ago _browse-fields-modal.js 1 year ago _field-group-compatibility.js 1 year ago _field-group-conditions.js 1 year ago _field-group-field.js 1 year ago _field-group-fields.js 1 year ago _field-group-locations.js 1 year ago _field-group-settings.js 1 year ago _field-group.js 1 year ago acf-escaped-html-notice.js 1 year ago acf-field-group.js 1 year ago acf-input.js 1 year ago acf-internal-post-type.js 1 year ago acf.js 1 year ago
_acf-field-tab.js
586 lines
1 ( function ( $, undefined ) {
2 // vars
3 var CONTEXT = 'tab';
4
5 var Field = acf.Field.extend( {
6 type: 'tab',
7
8 wait: '',
9
10 tabs: false,
11
12 tab: false,
13
14 events: {
15 duplicateField: 'onDuplicate',
16 },
17
18 findFields: function () {
19 let filter;
20
21 /**
22 * Tabs in the admin UI that can be extended by third
23 * parties have the child settings wrapped inside an extra div,
24 * so we need to look for that instead of an adjacent .acf-field.
25 */
26 switch ( this.get( 'key' ) ) {
27 case 'acf_field_settings_tabs':
28 filter = '.acf-field-settings-main';
29 break;
30 case 'acf_field_group_settings_tabs':
31 filter = '.field-group-settings-tab';
32 break;
33 case 'acf_browse_fields_tabs':
34 filter = '.acf-field-types-tab';
35 break;
36 case 'acf_icon_picker_tabs':
37 filter = '.acf-icon-picker-tabs';
38 break;
39 case 'acf_post_type_tabs':
40 filter = '.acf-post-type-advanced-settings';
41 break;
42 case 'acf_taxonomy_tabs':
43 filter = '.acf-taxonomy-advanced-settings';
44 break;
45 case 'acf_ui_options_page_tabs':
46 filter = '.acf-ui-options-page-advanced-settings';
47 break;
48 default:
49 filter = '.acf-field';
50 }
51
52 return this.$el.nextUntil( '.acf-field-tab', filter );
53 },
54
55 getFields: function () {
56 return acf.getFields( this.findFields() );
57 },
58
59 findTabs: function () {
60 return this.$el.prevAll( '.acf-tab-wrap:first' );
61 },
62
63 findTab: function () {
64 return this.$( '.acf-tab-button' );
65 },
66
67 initialize: function () {
68 // bail early if is td
69 if ( this.$el.is( 'td' ) ) {
70 this.events = {};
71 return false;
72 }
73
74 // vars
75 var $tabs = this.findTabs();
76 var $tab = this.findTab();
77 var settings = acf.parseArgs( $tab.data(), {
78 endpoint: false,
79 placement: '',
80 before: this.$el,
81 } );
82
83 // create wrap
84 if ( ! $tabs.length || settings.endpoint ) {
85 this.tabs = new Tabs( settings );
86 } else {
87 this.tabs = $tabs.data( 'acf' );
88 }
89
90 // add tab
91 this.tab = this.tabs.addTab( $tab, this );
92 },
93
94 isActive: function () {
95 return this.tab.isActive();
96 },
97
98 showFields: function () {
99 // show fields
100 this.getFields().map( function ( field ) {
101 field.show( this.cid, CONTEXT );
102 field.hiddenByTab = false;
103 }, this );
104 },
105
106 hideFields: function () {
107 // hide fields
108 this.getFields().map( function ( field ) {
109 field.hide( this.cid, CONTEXT );
110 field.hiddenByTab = this.tab;
111 }, this );
112 },
113
114 show: function ( lockKey ) {
115 // show field and store result
116 var visible = acf.Field.prototype.show.apply( this, arguments );
117
118 // check if now visible
119 if ( visible ) {
120 // show tab
121 this.tab.show();
122
123 // check active tabs
124 this.tabs.refresh();
125 }
126
127 // return
128 return visible;
129 },
130
131 hide: function ( lockKey ) {
132 // hide field and store result
133 var hidden = acf.Field.prototype.hide.apply( this, arguments );
134
135 // check if now hidden
136 if ( hidden ) {
137 // hide tab
138 this.tab.hide();
139
140 // reset tabs if this was active
141 if ( this.isActive() ) {
142 this.tabs.reset();
143 }
144 }
145
146 // return
147 return hidden;
148 },
149
150 enable: function ( lockKey ) {
151 // enable fields
152 this.getFields().map( function ( field ) {
153 field.enable( CONTEXT );
154 } );
155 },
156
157 disable: function ( lockKey ) {
158 // disable fields
159 this.getFields().map( function ( field ) {
160 field.disable( CONTEXT );
161 } );
162 },
163
164 onDuplicate: function ( e, $el, $duplicate ) {
165 if ( this.isActive() ) {
166 $duplicate.prevAll( '.acf-tab-wrap:first' ).remove();
167 }
168 },
169 } );
170
171 acf.registerFieldType( Field );
172
173 /**
174 * tabs
175 *
176 * description
177 *
178 * @date 8/2/18
179 * @since ACF 5.6.5
180 *
181 * @param type $var Description. Default.
182 * @return type Description.
183 */
184
185 var i = 0;
186 var Tabs = acf.Model.extend( {
187 tabs: [],
188
189 active: false,
190
191 actions: {
192 refresh: 'onRefresh',
193 close_field_object: 'onCloseFieldObject',
194 },
195
196 data: {
197 before: false,
198 placement: 'top',
199 index: 0,
200 initialized: false,
201 },
202
203 setup: function ( settings ) {
204 // data
205 $.extend( this.data, settings );
206
207 // define this prop to avoid scope issues
208 this.tabs = [];
209 this.active = false;
210
211 // vars
212 var placement = this.get( 'placement' );
213 var $before = this.get( 'before' );
214 var $parent = $before.parent();
215
216 // add sidebar for left placement
217 if ( placement == 'left' && $parent.hasClass( 'acf-fields' ) ) {
218 $parent.addClass( '-sidebar' );
219 }
220
221 // create wrap
222 if ( $before.is( 'tr' ) ) {
223 this.$el = $(
224 '<tr class="acf-tab-wrap"><td colspan="2"><ul class="acf-hl acf-tab-group"></ul></td></tr>'
225 );
226 } else {
227 let ulClass = 'acf-hl acf-tab-group';
228
229 if ( this.get( 'key' ) === 'acf_field_settings_tabs' ) {
230 ulClass = 'acf-field-settings-tab-bar';
231 }
232
233 this.$el = $(
234 '<div class="acf-tab-wrap -' +
235 placement +
236 '"><ul class="' +
237 ulClass +
238 '"></ul></div>'
239 );
240 }
241
242 // append
243 $before.before( this.$el );
244
245 // set index
246 this.set( 'index', i, true );
247 i++;
248 },
249
250 initializeTabs: function () {
251 // Bail if tabs are disabled.
252 if (
253 'acf_field_settings_tabs' === this.get( 'key' ) &&
254 $( '#acf-field-group-fields' ).hasClass( 'hide-tabs' )
255 ) {
256 return;
257 }
258
259 var tab = false;
260
261 // check if we've got a saved default tab.
262 var order = acf.getPreference( 'this.tabs' ) || false;
263 if ( order ) {
264 var groupIndex = this.get( 'index' );
265 var tabIndex = order[ groupIndex ];
266 if (
267 this.tabs[ tabIndex ] &&
268 this.tabs[ tabIndex ].isVisible()
269 ) {
270 tab = this.tabs[ tabIndex ];
271 }
272 }
273
274 // If we've got a defaultTab provided by configuration, use that.
275 if (
276 ! tab &&
277 this.data.defaultTab &&
278 this.data.defaultTab.isVisible()
279 ) {
280 tab = this.data.defaultTab;
281 }
282
283 // find first visible tab as our default.
284 if ( ! tab ) {
285 tab = this.getVisible().shift();
286 }
287
288 if ( tab ) {
289 this.selectTab( tab );
290 } else {
291 this.closeTabs();
292 }
293
294 // set local variable used by tabsManager
295 this.set( 'initialized', true );
296 },
297
298 getVisible: function () {
299 return this.tabs.filter( function ( tab ) {
300 return tab.isVisible();
301 } );
302 },
303
304 getActive: function () {
305 return this.active;
306 },
307
308 setActive: function ( tab ) {
309 return ( this.active = tab );
310 },
311
312 hasActive: function () {
313 return this.active !== false;
314 },
315
316 isActive: function ( tab ) {
317 var active = this.getActive();
318 return active && active.cid === tab.cid;
319 },
320
321 closeActive: function () {
322 if ( this.hasActive() ) {
323 this.closeTab( this.getActive() );
324 }
325 },
326
327 openTab: function ( tab ) {
328 // close existing tab
329 this.closeActive();
330
331 // open
332 tab.open();
333
334 // set active
335 this.setActive( tab );
336 },
337
338 closeTab: function ( tab ) {
339 // close
340 tab.close();
341
342 // set active
343 this.setActive( false );
344 },
345
346 closeTabs: function () {
347 this.tabs.map( this.closeTab, this );
348 },
349
350 selectTab: function ( tab ) {
351 // close other tabs
352 this.tabs.map( function ( t ) {
353 if ( tab.cid !== t.cid ) {
354 this.closeTab( t );
355 }
356 }, this );
357
358 // open
359 this.openTab( tab );
360 },
361
362 addTab: function ( $a, field ) {
363 // create <li>
364 var $li = $( '<li>' + $a.outerHTML() + '</li>' );
365
366 // add settings type class.
367 var settingsType = $a.data( 'settings-type' );
368 if ( settingsType ) {
369 $li.addClass( 'acf-settings-type-' + settingsType );
370 }
371
372
373 // append
374 this.$( 'ul' ).append( $li );
375
376 // initialize
377 var tab = new Tab( {
378 $el: $li,
379 field: field,
380 group: this,
381 } );
382
383 // store
384 this.tabs.push( tab );
385
386 if ( $a.data( 'selected' ) ) {
387 this.data.defaultTab = tab;
388 }
389
390 // return
391 return tab;
392 },
393
394 reset: function () {
395 // close existing tab
396 this.closeActive();
397
398 // find and active a tab
399 return this.refresh();
400 },
401
402 refresh: function () {
403 // bail early if active already exists
404 if ( this.hasActive() ) {
405 return false;
406 }
407 // find next active tab
408 var tab = this.getVisible().shift();
409 // open tab
410 if ( tab ) {
411 this.openTab( tab );
412 }
413
414 // return
415 return tab;
416 },
417
418 onRefresh: function () {
419 // only for left placements
420 if ( this.get( 'placement' ) !== 'left' ) {
421 return;
422 }
423
424 // vars
425 var $parent = this.$el.parent();
426 var $list = this.$el.children( 'ul' );
427 var attribute = $parent.is( 'td' ) ? 'height' : 'min-height';
428
429 // find height (minus 1 for border-bottom)
430 var height = $list.position().top + $list.outerHeight( true ) - 1;
431
432 // add css
433 $parent.css( attribute, height );
434 },
435
436 onCloseFieldObject: function ( fieldObject ) {
437 const tab = this.getVisible().find( ( item ) => {
438 const id = item.$el.closest( 'div[data-id]' ).data( 'id' );
439 if ( fieldObject.data.id === id ) {
440 return item;
441 }
442 } );
443
444 if ( tab ) {
445 // Wait for field group drawer to close
446 setTimeout( () => {
447 this.openTab( tab );
448 }, 300 );
449 }
450 },
451 } );
452
453 var Tab = acf.Model.extend( {
454 group: false,
455
456 field: false,
457
458 events: {
459 'click a': 'onClick',
460 },
461
462 index: function () {
463 return this.$el.index();
464 },
465
466 isVisible: function () {
467 return acf.isVisible( this.$el );
468 },
469
470 isActive: function () {
471 return this.$el.hasClass( 'active' );
472 },
473
474 open: function () {
475 // add class
476 this.$el.addClass( 'active' );
477
478 // show field
479 this.field.showFields();
480 },
481
482 close: function () {
483 // remove class
484 this.$el.removeClass( 'active' );
485
486 // hide field
487 this.field.hideFields();
488 },
489
490 onClick: function ( e, $el ) {
491 // prevent default
492 e.preventDefault();
493
494 // toggle
495 this.toggle();
496 },
497
498 toggle: function () {
499 // bail early if already active
500 if ( this.isActive() ) {
501 return;
502 }
503
504 // toggle this tab
505 this.group.openTab( this );
506 },
507 } );
508
509 var tabsManager = new acf.Model( {
510 priority: 50,
511
512 actions: {
513 prepare: 'render',
514 append: 'render',
515 unload: 'onUnload',
516 show: 'render',
517 invalid_field: 'onInvalidField',
518 },
519
520 findTabs: function () {
521 return $( '.acf-tab-wrap' );
522 },
523
524 getTabs: function () {
525 return acf.getInstances( this.findTabs() );
526 },
527
528 render: function ( $el ) {
529 this.getTabs().map( function ( tabs ) {
530 if ( ! tabs.get( 'initialized' ) ) {
531 tabs.initializeTabs();
532 }
533 } );
534 },
535
536 onInvalidField: function ( field ) {
537 // bail early if busy
538 if ( this.busy ) {
539 return;
540 }
541
542 // ignore if not hidden by tab
543 if ( ! field.hiddenByTab ) {
544 return;
545 }
546
547 // toggle tab
548 field.hiddenByTab.toggle();
549
550 // ignore other invalid fields
551 this.busy = true;
552 this.setTimeout( function () {
553 this.busy = false;
554 }, 100 );
555 },
556
557 onUnload: function () {
558 // vars
559 var order = [];
560
561 // loop
562 this.getTabs().map( function ( group ) {
563 // Do not save selected tab on field settings, or an acf-advanced-settings when unloading
564 if (
565 group.$el.children( '.acf-field-settings-tab-bar' )
566 .length ||
567 group.$el.parents( '#acf-advanced-settings.postbox' ).length
568 ) {
569 return true;
570 }
571
572 var active = group.hasActive() ? group.getActive().index() : 0;
573 order.push( active );
574 } );
575
576 // bail if no tabs
577 if ( ! order.length ) {
578 return;
579 }
580
581 // update
582 acf.setPreference( 'this.tabs', order );
583 },
584 } );
585 } )( jQuery );
586