');
}
// return
return;
}
// set more (allows pagination scroll)
this.set('more', json.more );
// get new results
var html = this.walkChoices(json.results);
var $html = $( html );
// apply .disabled to left li's
var val = this.val();
if( val && val.length ) {
val.map(function( id ){
$html.find('.acf-rel-item[data-id="' + id + '"]').addClass('disabled');
});
}
// append
$choiceslist.append( $html );
// merge together groups
var $prevLabel = false;
var $prevList = false;
$choiceslist.find('.acf-rel-label').each(function(){
var $label = $(this);
var $list = $label.siblings('ul');
if( $prevLabel && $prevLabel.text() == $label.text() ) {
$prevList.append( $list.children() );
$(this).parent().remove();
return;
}
// update vars
$prevLabel = $label;
$prevList = $list;
});
};
// get results
var xhr = $.ajax({
url: acf.get('ajaxurl'),
dataType: 'json',
type: 'post',
data: acf.prepareForAjax(ajaxData),
context: this,
success: onSuccess,
complete: onComplete
});
// set
this.set('xhr', xhr);
},
walkChoices: function( data ){
// walker
var walk = function( data ){
// vars
var html = '';
// is array
if( $.isArray(data) ) {
data.map(function(item){
html += walk( item );
});
// is item
} else if( $.isPlainObject(data) ) {
// group
if( data.children !== undefined ) {
html += '
' + data.text + '
';
html += walk( data.children );
html += '
';
// single
} else {
html += '
' + data.text + '
';
}
}
// return
return html;
};
return walk( data );
}
});
acf.registerFieldType( Field );
})(jQuery);
(function($, undefined){
var Field = acf.Field.extend({
type: 'select',
select2: false,
wait: 'load',
events: {
'removeField': 'onRemove'
},
$input: function(){
return this.$('select');
},
initialize: function(){
// vars
var $select = this.$input();
// inherit data
this.inherit( $select );
// select2
if( this.get('ui') ) {
// populate ajax_data (allowing custom attribute to already exist)
var ajaxAction = this.get('ajax_action');
if( !ajaxAction ) {
ajaxAction = 'acf/fields/' + this.get('type') + '/query';
}
// select2
this.select2 = acf.newSelect2($select, {
field: this,
ajax: this.get('ajax'),
multiple: this.get('multiple'),
placeholder: this.get('placeholder'),
allowNull: this.get('allow_null'),
ajaxAction: ajaxAction,
});
}
},
onRemove: function(){
if( this.select2 ) {
this.select2.destroy();
}
}
});
acf.registerFieldType( Field );
})(jQuery);
(function($, undefined){
// vars
var CONTEXT = 'tab';
var Field = acf.Field.extend({
type: 'tab',
wait: '',
tabs: false,
tab: false,
findFields: function(){
return this.$el.nextUntil('.acf-field-tab', '.acf-field');
},
getFields: function(){
return acf.getFields( this.findFields() );
},
findTabs: function(){
return this.$el.prevAll('.acf-tab-wrap:first');
},
findTab: function(){
return this.$('.acf-tab-button');
},
initialize: function(){
// bail early if is td
if( this.$el.is('td') ) {
this.events = {};
return false;
}
// vars
var $tabs = this.findTabs();
var $tab = this.findTab();
var settings = acf.parseArgs($tab.data(), {
endpoint: false,
placement: '',
before: this.$el
});
// create wrap
if( !$tabs.length || settings.endpoint ) {
this.tabs = new Tabs( settings );
} else {
this.tabs = $tabs.data('acf');
}
// add tab
this.tab = this.tabs.addTab($tab, this);
},
isActive: function(){
return this.tab.isActive();
},
showFields: function(){
// show fields
this.getFields().map(function( field ){
field.show( this.cid, CONTEXT );
field.hiddenByTab = false;
}, this);
},
hideFields: function(){
// hide fields
this.getFields().map(function( field ){
field.hide( this.cid, CONTEXT );
field.hiddenByTab = this.tab;
}, this);
},
show: function( lockKey ){
// show field and store result
var visible = acf.Field.prototype.show.apply(this, arguments);
// check if now visible
if( visible ) {
// show tab
this.tab.show();
// check active tabs
this.tabs.refresh();
}
// return
return visible;
},
hide: function( lockKey ){
// hide field and store result
var hidden = acf.Field.prototype.hide.apply(this, arguments);
// check if now hidden
if( hidden ) {
// hide tab
this.tab.hide();
// reset tabs if this was active
if( this.isActive() ) {
this.tabs.reset();
}
}
// return
return hidden;
},
enable: function( lockKey ){
// enable fields
this.getFields().map(function( field ){
field.enable( CONTEXT );
});
},
disable: function( lockKey ){
// disable fields
this.getFields().map(function( field ){
field.disable( CONTEXT );
});
}
});
acf.registerFieldType( Field );
/**
* tabs
*
* description
*
* @date 8/2/18
* @since 5.6.5
*
* @param type $var Description. Default.
* @return type Description.
*/
var i = 0;
var Tabs = acf.Model.extend({
tabs: [],
active: false,
actions: {
'refresh': 'onRefresh'
},
data: {
before: false,
placement: 'top',
index: 0,
initialized: false,
},
setup: function( settings ){
// data
$.extend(this.data, settings);
// define this prop to avoid scope issues
this.tabs = [];
this.active = false;
// vars
var placement = this.get('placement');
var $before = this.get('before');
var $parent = $before.parent();
// add sidebar for left placement
if( placement == 'left' && $parent.hasClass('acf-fields') ) {
$parent.addClass('-sidebar');
}
// create wrap
if( $before.is('tr') ) {
this.$el = $('
');
} else {
this.$el = $('
');
}
// append
$before.before( this.$el );
// set index
this.set('index', i, true);
i++;
},
initializeTabs: function(){
// find first visible tab
var tab = this.getVisible().shift();
// remember previous tab state
var order = acf.getPreference('this.tabs') || [];
var groupIndex = this.get('index');
var tabIndex = order[ groupIndex ];
if( this.tabs[ tabIndex ] && this.tabs[ tabIndex ].isVisible() ) {
tab = this.tabs[ tabIndex ];
}
// select
if( tab ) {
this.selectTab( tab );
} else {
this.closeTabs();
}
// set local variable used by tabsManager
this.set('initialized', true);
},
getVisible: function(){
return this.tabs.filter(function( tab ){
return tab.isVisible();
});
},
getActive: function(){
return this.active;
},
setActive: function( tab ){
return this.active = tab;
},
hasActive: function(){
return (this.active !== false);
},
isActive: function( tab ){
var active = this.getActive();
return (active && active.cid === tab.cid);
},
closeActive: function(){
if( this.hasActive() ) {
this.closeTab( this.getActive() );
}
},
openTab: function( tab ){
// close existing tab
this.closeActive();
// open
tab.open();
// set active
this.setActive( tab );
},
closeTab: function( tab ){
// close
tab.close();
// set active
this.setActive( false );
},
closeTabs: function(){
this.tabs.map( this.closeTab, this );
},
selectTab: function( tab ){
// close other tabs
this.tabs.map(function( t ){
if( tab.cid !== t.cid ) {
this.closeTab( t );
}
}, this);
// open
this.openTab( tab );
},
addTab: function( $a, field ){
// create
'
].join(''));
// reset selection (unselects all attachments)
selection.reset();
// set single (attachment displayed in sidebar)
selection.single( model );
// return and prevent 'select' form being fired
return;
}
// return
return AttachmentLibrary.prototype.toggleSelection.apply( this, arguments );
}
});
}
});
})(jQuery);
(function($, undefined){
acf.screen = new acf.Model({
active: true,
xhr: false,
timeout: false,
wait: 'load',
events: {
'change #page_template': 'onChange',
'change #parent_id': 'onChange',
'change #post-formats-select': 'onChange',
'change .categorychecklist': 'onChange',
'change .tagsdiv': 'onChange',
'change .acf-taxonomy-field[data-save="1"]': 'onChange',
'change #product-type': 'onChange'
},
initialize: function(){
/*
// disable if not active
if( !this.active ) {
this.events = {};
}
// bail early if not for post
if( acf.get('screen') !== 'post' ) {
return;
}
'check_screen_data'
'check_screen_events'
*/
},
/*
checkScreenEvents: function(){
// vars
var events = [
'change #page_template',
'change #parent_id',
'change #post-formats-select input',
'change .categorychecklist input',
'change .categorychecklist select',
'change .acf-taxonomy-field[data-save="1"] input',
'change .acf-taxonomy-field[data-save="1"] select',
'change #product-type'
];
acf.screen.on('change', '#product-type', 'fetch');
},
*/
isPost: function(){
return acf.get('screen') === 'post';
},
isUser: function(){
return acf.get('screen') === 'user';
},
isTaxonomy: function(){
return acf.get('screen') === 'taxonomy';
},
isAttachment: function(){
return acf.get('screen') === 'attachment';
},
isNavMenu: function(){
return acf.get('screen') === 'nav_menu';
},
isWidget: function(){
return acf.get('screen') === 'widget';
},
isComment: function(){
return acf.get('screen') === 'comment';
},
getPageTemplate: function(){
var $el = $('#page_template');
return $el.length ? $el.val() : null;
},
getPageParent: function( e, $el ){
var $el = $('#parent_id');
return $el.length ? $el.val() : null;
},
getPageType: function( e, $el ){
return this.getPageParent() ? 'child' : 'parent';
},
getPostFormat: function( e, $el ){
var $el = $('#post-formats-select input:checked');
if( $el.length ) {
var val = $el.val();
return (val == '0') ? 'standard' : val;
}
return null;
},
getPostTerms: function(){
// vars
var terms = {};
// serialize WP taxonomy postboxes
var data = acf.serialize( $('.categorydiv, .tagsdiv') );
// use tax_input (tag, custom-taxonomy) when possible.
// this data is already formatted in taxonomy => [terms].
if( data.tax_input ) {
terms = data.tax_input;
}
// append "category" which uses a different name
if( data.post_category ) {
terms.category = data.post_category;
}
// convert any string values (tags) into array format
for( var tax in terms ) {
if( !acf.isArray(terms[tax]) ) {
terms[tax] = terms[tax].split(', ');
}
}
// loop over taxonomy fields and add their values
acf.getFields({type: 'taxonomy'}).map(function( field ){
// ignore fields that don't save
if( !field.get('save') ) {
return;
}
// vars
var val = field.val();
var tax = field.get('taxonomy');
// check val
if( val ) {
// ensure terms exists
terms[ tax ] = terms[ tax ] || [];
// ensure val is an array
val = acf.isArray(val) ? val : [val];
// append
terms[ tax ] = terms[ tax ].concat( val );
}
});
// add WC product type
if( (productType = this.getProductType()) !== null ) {
terms.product_type = [productType];
}
// remove duplicate values
for( var tax in terms ) {
terms[tax] = acf.uniqueArray(terms[tax]);
}
// return
return terms;
},
getProductType: function(){
var $el = $('#product-type');
return $el.length ? $el.val() : null;
},
check: function(){
// bail early if not for post
if( acf.get('screen') !== 'post' ) {
return;
}
// abort XHR if is already loading AJAX data
if( this.xhr ) {
this.xhr.abort();
}
// vars
var ajaxData = acf.parseArgs(this.data, {
action: 'acf/ajax/check_screen',
screen: acf.get('screen'),
exclude: []
});
// post id
if( this.isPost() ) {
ajaxData.post_id = acf.get('post_id');
}
// page template
if( (pageTemplate = this.getPageTemplate()) !== null ) {
ajaxData.page_template = pageTemplate;
}
// page parent
if( (pageParent = this.getPageParent()) !== null ) {
ajaxData.page_parent = pageParent;
}
// page type
if( (pageType = this.getPageType()) !== null ) {
ajaxData.page_type = pageType;
}
// post format
if( (postFormat = this.getPostFormat()) !== null ) {
ajaxData.post_format = postFormat;
}
// post terms
if( (postTerms = this.getPostTerms()) !== null ) {
ajaxData.post_terms = postTerms;
}
// exclude existing postboxes
$('.acf-postbox').not('.acf-hidden').each(function(){
ajaxData.exclude.push( $(this).attr('id').substr(4) );
});
// success
var onSuccess = function( json ){
// bail early if not success
if( !acf.isAjaxSuccess(json) ) {
return;
}
// hide
$('.acf-postbox').addClass('acf-hidden');
$('.acf-postbox-toggle').addClass('acf-hidden');
// reset style
$('#acf-style').html('');
// loop
json.data.map(function( fieldGroup, i ){
// vars
var $postbox = $('#acf-' + fieldGroup.key);
var $toggle = $('#acf-' + fieldGroup.key + '-hide');
var $label = $toggle.parent();
// show
// use show() to force display when postbox has been hidden by 'Show on screen' toggle
$postbox.removeClass('acf-hidden hide-if-js').show();
$label.removeClass('acf-hidden hide-if-js').show();
$toggle.prop('checked', true);
// replace HTML if needed
var $replace = $postbox.find('.acf-replace-with-fields');
if( $replace.exists() ) {
$replace.replaceWith( fieldGroup.html );
acf.doAction('append', $postbox);
}
// update style if needed
if( i === 0 ) {
$('#acf-style').html( fieldGroup.style );
}
// enable inputs
acf.enable( $postbox, 'postbox' );
});
};
// complete
var onComplete = function( json ){
// disable inputs
$('.acf-postbox.acf-hidden').each(function(){
acf.disable( $(this), 'postbox' );
});
};
// ajax
this.xhr = $.ajax({
url: acf.get('ajaxurl'),
data: acf.prepareForAjax( ajaxData ),
type: 'post',
dataType: 'json',
context: this,
success: onSuccess,
complete: onComplete
});
},
onChange: function( e, $el ){
this.setTimeout(this.check, 1);
}
});
/*
// tests
acf.registerScreenChange('#page_template', function( e, $el ){
return $('#page_template').val();
});
acf.registerScreenData({
name: 'page_template',
change: '#page_template',
val: function(){
var $input = $(this.el);
return $input.length ? $input.val() : null;
}
});
acf.registerScreenData({
name: 'post_terms',
change: '.acf-taxonomy-field[data-save="1"]',
val: function(){
var $input = $(this.el);
return $input.length ? $input.val() : null;
}
});
acf.registerScreenData({
name: 'post_terms',
change: '#product-type',
val: function( terms ){
var $select = $('#product-type');
if( $select.length ) {
terms.push('product_cat:'+$select.val());
}
return terms;
}
});
acf.screen.get('post_terms');
acf.screen.getPostTerms();
*/
})(jQuery);
(function($, undefined){
/**
* acf.newSelect2
*
* description
*
* @date 13/1/18
* @since 5.6.5
*
* @param type $var Description. Default.
* @return type Description.
*/
acf.newSelect2 = function( $select, props ){
// defaults
props = acf.parseArgs(props, {
allowNull: false,
placeholder: '',
multiple: false,
field: false,
ajax: false,
ajaxAction: '',
ajaxData: function( data ){ return data; },
ajaxResults: function( json ){ return json; },
});
// initialize
if( getVersion() == 4 ) {
var select2 = new Select2_4( $select, props );
} else {
var select2 = new Select2_3( $select, props );
}
// actions
acf.doAction('new_select2', select2);
// return
return select2;
};
/**
* getVersion
*
* description
*
* @date 13/1/18
* @since 5.6.5
*
* @param type $var Description. Default.
* @return type Description.
*/
function getVersion() {
// v4
if( acf.isset(window, 'jQuery', 'fn', 'select2', 'amd') ) {
return 4;
}
// v3
if( acf.isset(window, 'Select2') ) {
return 3;
}
// return
return false;
}
/**
* Select2
*
* description
*
* @date 13/1/18
* @since 5.6.5
*
* @param type $var Description. Default.
* @return type Description.
*/
var Select2 = acf.Model.extend({
setup: function( $select, props ){
$.extend(this.data, props);
this.$el = $select;
},
initialize: function(){
},
selectOption: function( value ){
var $option = this.getOption( value );
if( !$option.prop('selected') ) {
$option.prop('selected', true).trigger('change');
}
},
unselectOption: function( value ){
var $option = this.getOption( value );
if( $option.prop('selected') ) {
$option.prop('selected', false).trigger('change');
}
},
getOption: function( value ){
return this.$('option[value="' + value + '"]');
},
addOption: function( option ){
// defaults
option = acf.parseArgs(option, {
id: '',
text: '',
selected: false
});
// vars
var $option = this.getOption( option.id );
// append
if( !$option.length ) {
$option = $('');
$option.html( option.text );
$option.attr('value', option.id);
$option.prop('selected', option.selected);
this.$el.append($option);
}
// chain
return $option;
},
getValue: function(){
// vars
var val = [];
var $options = this.$el.find('option:selected');
// bail early if no selected
if( !$options.exists() ) {
return val;
}
// sort by attribute
$options = $options.sort(function(a, b) {
return +a.getAttribute('data-i') - +b.getAttribute('data-i');
});
// loop
$options.each(function(){
var $el = $(this);
val.push({
$el: $el,
id: $el.attr('value'),
text: $el.text(),
});
});
// return
return val;
},
mergeOptions: function(){
},
getChoices: function(){
// callback
var crawl = function( $parent ){
// vars
var choices = [];
// loop
$parent.children().each(function(){
// vars
var $child = $(this);
// optgroup
if( $child.is('optgroup') ) {
choices.push({
text: $child.attr('label'),
children: crawl( $child )
});
// option
} else {
choices.push({
id: $child.attr('value'),
text: $child.text()
});
}
});
// return
return choices;
};
// crawl
return crawl( this.$el );
},
decodeChoices: function( choices ){
// callback
var crawl = function( items ){
items.map(function( item ){
item.text = acf.decode( item.text );
if( item.children ) {
item.children = crawl( item.children );
}
return item;
});
return items;
};
// crawl
return crawl( choices );
},
getAjaxData: function( params ){
// vars
var ajaxData = {
action: this.get('ajaxAction'),
s: params.term || '',
paged: params.page || 1
};
// field helper
var field = this.get('field');
if( field ) {
ajaxData.field_key = field.get('key');
}
// callback
var callback = this.get('ajaxData');
if( callback ) {
ajaxData = callback.apply( this, [ajaxData, params] );
}
// filter
ajaxData = acf.applyFilters( 'select2_ajax_data', ajaxData, this.data, this.$el, (field || false), this );
// return
return acf.prepareForAjax(ajaxData);
},
getAjaxResults: function( json, params ){
// defaults
json = acf.parseArgs(json, {
results: false,
more: false,
});
// decode
if( json.results ) {
json.results = this.decodeChoices(json.results);
}
// callback
var callback = this.get('ajaxResults');
if( callback ) {
json = callback.apply( this, [json, params] );
}
// filter
json = acf.applyFilters( 'select2_ajax_results', json, params, this );
// return
return json;
},
processAjaxResults: function( json, params ){
// vars
var json = this.getAjaxResults( json, params );
// change more to pagination
if( json.more ) {
json.pagination = { more: true };
}
// merge together groups
setTimeout($.proxy(this.mergeOptions, this), 1);
// return
return json;
},
destroy: function(){
// destroy via api
if( this.$el.data('select2') ) {
this.$el.select2('destroy');
}
// destory via HTML (duplicating HTML does not contain data)
this.$el.siblings('.select2-container').remove();
}
});
/**
* Select2_4
*
* description
*
* @date 13/1/18
* @since 5.6.5
*
* @param type $var Description. Default.
* @return type Description.
*/
var Select2_4 = Select2.extend({
initialize: function(){
// vars
var $select = this.$el;
var options = {
width: '100%',
allowClear: this.get('allowNull'),
placeholder: this.get('placeholder'),
multiple: this.get('multiple'),
data: [],
escapeMarkup: function( m ){ return m; }
};
// multiple
if( options.multiple ) {
// reorder options
this.getValue().map(function( item ){
item.$el.detach().appendTo( $select );
});
}
// remove conflicting atts
$select.removeData('ajax');
$select.removeAttr('data-ajax');
// ajax
if( this.get('ajax') ) {
options.ajax = {
url: acf.get('ajaxurl'),
delay: 250,
dataType: 'json',
type: 'post',
cache: false,
data: $.proxy(this.getAjaxData, this),
processResults: $.proxy(this.processAjaxResults, this),
};
}
// filter for 3rd party customization
//options = acf.applyFilters( 'select2_args', options, $select, this );
var field = this.get('field');
options = acf.applyFilters( 'select2_args', options, $select, this.data, (field || false), this );
// add select2
$select.select2( options );
// get container (Select2 v4 does not return this from constructor)
var $container = $select.next('.select2-container');
// multiple
if( options.multiple ) {
// vars
var $ul = $container.find('ul');
// sortable
$ul.sortable({
stop: function( e ) {
// loop
$ul.find('.select2-selection__choice').each(function() {
// vars
var $option = $( $(this).data('data').element );
// detach and re-append to end
$option.detach().appendTo( $select );
});
// trigger change on input (JS error if trigger on select)
$select.trigger('change');
}
});
// on select, move to end
$select.on('select2:select', this.proxy(function( e ){
this.getOption( e.params.data.id ).detach().appendTo( this.$el );
}));
}
// add class
$container.addClass('-acf');
// action for 3rd party customization
acf.doAction('select2_init', $select, options, this.data, (field || false), this);
},
mergeOptions: function(){
// vars
var $prevOptions = false;
var $prevGroup = false;
// loop
$('.select2-results__option[role="group"]').each(function(){
// vars
var $options = $(this).children('ul');
var $group = $(this).children('strong');
// compare to previous
if( $prevGroup && $prevGroup.text() === $group.text() ) {
$prevOptions.append( $options.children() );
$(this).remove();
return;
}
// update vars
$prevOptions = $options;
$prevGroup = $group;
});
},
});
/**
* Select2_3
*
* description
*
* @date 13/1/18
* @since 5.6.5
*
* @param type $var Description. Default.
* @return type Description.
*/
var Select2_3 = Select2.extend({
initialize: function(){
// vars
var $select = this.$el;
var value = this.getValue();
var multiple = this.get('multiple');
var options = {
width: '100%',
allowClear: this.get('allowNull'),
placeholder: this.get('placeholder'),
separator: '||',
multiple: this.get('multiple'),
data: this.getChoices(),
escapeMarkup: function( m ){ return m; },
dropdownCss: {
'z-index': '999999999'
},
initSelection: function( element, callback ) {
if( multiple ) {
callback( value );
} else {
callback( value.shift() );
}
}
};
// get hidden input
var $input = $select.siblings('input');
if( !$input.length ) {
$input = $('');
$select.before( $input );
}
// set input value
inputValue = value.map(function(item){ return item.id }).join('||');
$input.val( inputValue );
// multiple
if( options.multiple ) {
// reorder options
value.map(function( item ){
item.$el.detach().appendTo( $select );
});
}
// remove blank option as we have a clear all button
if( options.allowClear ) {
options.data = options.data.filter(function(item){
return item.id !== '';
});
}
// remove conflicting atts
$select.removeData('ajax');
$select.removeAttr('data-ajax');
// ajax
if( this.get('ajax') ) {
options.ajax = {
url: acf.get('ajaxurl'),
quietMillis: 250,
dataType: 'json',
type: 'post',
cache: false,
data: $.proxy(this.getAjaxData, this),
results: $.proxy(this.processAjaxResults, this),
};
}
// filter for 3rd party customization
var field = this.get('field');
options = acf.applyFilters( 'select2_args', options, $select, this.data, (field || false), this );
// add select2
$input.select2( options );
// get container
var $container = $input.select2('container');
// helper to find this select's option
var getOption = $.proxy(this.getOption, this);
// multiple
if( options.multiple ) {
// vars
var $ul = $container.find('ul');
// sortable
$ul.sortable({
stop: function() {
// loop
$ul.find('.select2-search-choice').each(function() {
// vars
var data = $(this).data('select2Data');
var $option = getOption( data.id );
// detach and re-append to end
$option.detach().appendTo( $select );
});
// trigger change on input (JS error if trigger on select)
$select.trigger('change');
}
});
}
// on select, create option and move to end
$input.on('select2-selecting', function( e ){
// vars
var item = e.choice;
var $option = getOption( item.id );
// create if doesn't exist
if( !$option.length ) {
$option = $('');
}
// detach and re-append to end
$option.detach().appendTo( $select );
});
// add class
$container.addClass('-acf');
// action for 3rd party customization
acf.doAction('select2_init', $select, options, this.data, (field || false), this);
// change
$input.on('change', function(){
var val = $input.val();
if( val.indexOf('||') ) {
val = val.split('||');
}
$select.val( val ).trigger('change');
});
// hide select
$select.hide();
},
mergeOptions: function(){
// vars
var $prevOptions = false;
var $prevGroup = false;
// loop
$('#select2-drop .select2-result-with-children').each(function(){
// vars
var $options = $(this).children('ul');
var $group = $(this).children('.select2-result-label');
// compare to previous
if( $prevGroup && $prevGroup.text() === $group.text() ) {
$prevGroup.append( $options.children() );
$(this).remove();
return;
}
// update vars
$prevOptions = $options;
$prevGroup = $group;
});
},
getAjaxData: function( term, page ){
// create Select2 v4 params
var params = {
term: term,
page: page
}
// return
return Select2.prototype.getAjaxData.apply(this, [params]);
},
});
// manager
var select2Manager = new acf.Model({
priority: 5,
wait: 'prepare',
initialize: function(){
// vars
var locale = acf.get('locale');
var rtl = acf.get('rtl');
var l10n = acf.get('select2L10n');
var version = getVersion();
// bail ealry if no l10n
if( !l10n ) {
return false;
}
// bail early if 'en'
if( locale.indexOf('en') === 0 ) {
return false;
}
// initialize
if( version == 4 ) {
this.addTranslations4();
} else if( version == 3 ) {
this.addTranslations3();
}
},
addTranslations4: function(){
// vars
var l10n = acf.get('select2L10n');
var locale = acf.get('locale');
// modify local to match html[lang] attribute (used by Select2)
locale = locale.replace('_', '-');
// select2L10n
var select2L10n = {
errorLoading: function () {
return l10n.load_fail;
},
inputTooLong: function (args) {
var overChars = args.input.length - args.maximum;
if( overChars > 1 ) {
return l10n.input_too_long_n.replace( '%d', overChars );
}
return l10n.input_too_long_1;
},
inputTooShort: function( args ){
var remainingChars = args.minimum - args.input.length;
if( remainingChars > 1 ) {
return l10n.input_too_short_n.replace( '%d', remainingChars );
}
return l10n.input_too_short_1;
},
loadingMore: function () {
return l10n.load_more;
},
maximumSelected: function( args ) {
var maximum = args.maximum;
if( maximum > 1 ) {
return l10n.selection_too_long_n.replace( '%d', maximum );
}
return l10n.selection_too_long_1;
},
noResults: function () {
return l10n.matches_0;
},
searching: function () {
return l10n.searching;
}
};
// append
jQuery.fn.select2.amd.define('select2/i18n/' + locale, [], function(){
return select2L10n;
});
},
addTranslations3: function(){
// vars
var l10n = acf.get('select2L10n');
var locale = acf.get('locale');
// modify local to match html[lang] attribute (used by Select2)
locale = locale.replace('_', '-');
// select2L10n
var select2L10n = {
formatMatches: function( matches ) {
if( matches > 1 ) {
return l10n.matches_n.replace( '%d', matches );
}
return l10n.matches_1;
},
formatNoMatches: function() {
return l10n.matches_0;
},
formatAjaxError: function() {
return l10n.load_fail;
},
formatInputTooShort: function( input, min ) {
var remainingChars = min - input.length;
if( remainingChars > 1 ) {
return l10n.input_too_short_n.replace( '%d', remainingChars );
}
return l10n.input_too_short_1;
},
formatInputTooLong: function( input, max ) {
var overChars = input.length - max;
if( overChars > 1 ) {
return l10n.input_too_long_n.replace( '%d', overChars );
}
return l10n.input_too_long_1;
},
formatSelectionTooBig: function( maximum ) {
if( maximum > 1 ) {
return l10n.selection_too_long_n.replace( '%d', maximum );
}
return l10n.selection_too_long_1;
},
formatLoadMore: function() {
return l10n.load_more;
},
formatSearching: function() {
return l10n.searching;
}
};
// ensure locales exists
$.fn.select2.locales = $.fn.select2.locales || {};
// append
$.fn.select2.locales[ locale ] = select2L10n;
$.extend($.fn.select2.defaults, select2L10n);
}
});
})(jQuery);
(function($, undefined){
acf.tinymce = {
/*
* defaults
*
* This function will return default mce and qt settings
*
* @type function
* @date 18/8/17
* @since 5.6.0
*
* @param $post_id (int)
* @return $post_id (int)
*/
defaults: function(){
// bail early if no tinyMCEPreInit
if( typeof tinyMCEPreInit === 'undefined' ) return false;
// vars
var defaults = {
tinymce: tinyMCEPreInit.mceInit.acf_content,
quicktags: tinyMCEPreInit.qtInit.acf_content
};
// return
return defaults;
},
/*
* initialize
*
* This function will initialize the tinymce and quicktags instances
*
* @type function
* @date 18/8/17
* @since 5.6.0
*
* @param $post_id (int)
* @return $post_id (int)
*/
initialize: function( id, args ){
// defaults
args = acf.parseArgs(args, {
tinymce: true,
quicktags: true,
toolbar: 'full',
mode: 'visual', // visual,text
field: false
});
// tinymce
if( args.tinymce ) {
this.initializeTinymce( id, args );
}
// quicktags
if( args.quicktags ) {
this.initializeQuicktags( id, args );
}
},
/*
* initializeTinymce
*
* This function will initialize the tinymce instance
*
* @type function
* @date 18/8/17
* @since 5.6.0
*
* @param $post_id (int)
* @return $post_id (int)
*/
initializeTinymce: function( id, args ){
// vars
var $textarea = $('#'+id);
var defaults = this.defaults();
var toolbars = acf.get('toolbars');
var field = args.field || false;
var $field = field.$el || false;
// bail early
if( typeof tinymce === 'undefined' ) return false;
if( !defaults ) return false;
// check if exists
if( tinymce.get(id) ) {
return this.enable( id );
}
// settings
var init = $.extend( {}, defaults.tinymce, args.tinymce );
init.id = id;
init.selector = '#' + id;
// toolbar
var toolbar = args.toolbar;
if( toolbar && toolbars && toolbars[toolbar] ) {
for( var i = 1; i <= 4; i++ ) {
init[ 'toolbar' + i ] = toolbars[toolbar][i] || '';
}
}
// event
init.setup = function( ed ){
ed.on('change', function(e) {
ed.save(); // save to textarea
$textarea.trigger('change');
});
$( ed.getWin() ).on('unload', function() {
acf.tinymce.remove( id );
});
};
// disable wp_autoresize_on (no solution yet for fixed toolbar)
init.wp_autoresize_on = false;
// hook for 3rd party customization
init = acf.applyFilters('wysiwyg_tinymce_settings', init, id, field);
// z-index fix (caused too many conflicts)
//if( acf.isset(tinymce,'ui','FloatPanel') ) {
// tinymce.ui.FloatPanel.zIndex = 900000;
//}
// store settings
tinyMCEPreInit.mceInit[ id ] = init;
// visual tab is active
if( args.mode == 'visual' ) {
// init
var result = tinymce.init( init );
// get editor
var ed = tinymce.get( id );
// validate
if( !ed ) {
return false;
}
// add reference
ed.acf = args.field;
// action
acf.doAction('wysiwyg_tinymce_init', ed, ed.id, init, field);
}
},
/*
* initializeQuicktags
*
* This function will initialize the quicktags instance
*
* @type function
* @date 18/8/17
* @since 5.6.0
*
* @param $post_id (int)
* @return $post_id (int)
*/
initializeQuicktags: function( id, args ){
// vars
var defaults = this.defaults();
// bail early
if( typeof quicktags === 'undefined' ) return false;
if( !defaults ) return false;
// settings
var init = $.extend( {}, defaults.quicktags, args.quicktags );
init.id = id;
// filter
var field = args.field || false;
var $field = field.$el || false;
init = acf.applyFilters('wysiwyg_quicktags_settings', init, init.id, field);
// store settings
tinyMCEPreInit.qtInit[ id ] = init;
// init
var ed = quicktags( init );
// validate
if( !ed ) {
return false;
}
// generate HTML
this.buildQuicktags( ed );
// action for 3rd party customization
acf.doAction('wysiwyg_quicktags_init', ed, ed.id, init, field);
},
/*
* buildQuicktags
*
* This function will build the quicktags HTML
*
* @type function
* @date 18/8/17
* @since 5.6.0
*
* @param $post_id (int)
* @return $post_id (int)
*/
buildQuicktags: function( ed ){
var canvas, name, settings, theButtons, html, ed, id, i, use, instanceId,
defaults = ',strong,em,link,block,del,ins,img,ul,ol,li,code,more,close,';
canvas = ed.canvas;
name = ed.name;
settings = ed.settings;
html = '';
theButtons = {};
use = '';
instanceId = ed.id;
// set buttons
if ( settings.buttons ) {
use = ','+settings.buttons+',';
}
for ( i in edButtons ) {
if ( ! edButtons[i] ) {
continue;
}
id = edButtons[i].id;
if ( use && defaults.indexOf( ',' + id + ',' ) !== -1 && use.indexOf( ',' + id + ',' ) === -1 ) {
continue;
}
if ( ! edButtons[i].instance || edButtons[i].instance === instanceId ) {
theButtons[id] = edButtons[i];
if ( edButtons[i].html ) {
html += edButtons[i].html( name + '_' );
}
}
}
if ( use && use.indexOf(',dfw,') !== -1 ) {
theButtons.dfw = new QTags.DFWButton();
html += theButtons.dfw.html( name + '_' );
}
if ( 'rtl' === document.getElementsByTagName( 'html' )[0].dir ) {
theButtons.textdirection = new QTags.TextDirectionButton();
html += theButtons.textdirection.html( name + '_' );
}
ed.toolbar.innerHTML = html;
ed.theButtons = theButtons;
if ( typeof jQuery !== 'undefined' ) {
jQuery( document ).triggerHandler( 'quicktags-init', [ ed ] );
}
},
disable: function( id ){
this.destroyTinymce( id );
},
remove: function( id ){
this.destroyTinymce( id );
},
destroy: function( id ){
this.destroyTinymce( id );
},
destroyTinymce: function( id ){
// bail early
if( typeof tinymce === 'undefined' ) return false;
// get editor
var ed = tinymce.get( id );
// bail early if no editor
if( !ed ) return false;
// save
ed.save();
// destroy editor
ed.destroy();
// return
return true;
},
enable: function( id ){
this.enableTinymce( id );
},
enableTinymce: function( id ){
// bail early
if( typeof switchEditors === 'undefined' ) return false;
// bail ealry if not initialized
if( typeof tinyMCEPreInit.mceInit[ id ] === 'undefined' ) return false;
// toggle
switchEditors.go( id, 'tmce');
// return
return true;
}
};
var editorManager = new acf.Model({
// hook in before fieldsEventManager, conditions, etc
priority: 5,
actions: {
'prepare': 'onPrepare',
'ready': 'onReady',
},
onPrepare: function(){
// find hidden editor which may exist within a field
var $div = $('#acf-hidden-wp-editor');
// move to footer
if( $div.exists() ) {
$div.appendTo('body');
}
},
onReady: function(){
// bail early if no tinymce
if( !acf.isset(window,'tinymce','on') ) return;
// restore default activeEditor
tinymce.on('AddEditor', function( data ){
// vars
var editor = data.editor;
// bail early if not 'acf'
if( editor.id.substr(0, 3) !== 'acf' ) return;
// override if 'content' exists
editor = tinymce.editors.content || editor;
// update vars
tinymce.activeEditor = editor;
wpActiveEditor = editor.id;
});
}
});
})(jQuery);
(function($, undefined){
/**
* Validator
*
* The model for validating forms
*
* @date 4/9/18
* @since 5.7.5
*
* @param void
* @return void
*/
var Validator = acf.Model.extend({
/** @var string The model identifier. */
id: 'Validator',
/** @var object The model data. */
data: {
/** @var array The form errors. */
errors: [],
/** @var object The form notice. */
notice: null,
/** @var string The form status. loading, invalid, valid */
status: ''
},
/** @var object The model events. */
events: {
'changed:status': 'onChangeStatus'
},
/**
* addErrors
*
* Adds errors to the form.
*
* @date 4/9/18
* @since 5.7.5
*
* @param array errors An array of errors.
* @return void
*/
addErrors: function( errors ){
errors.map( this.addError, this );
},
/**
* addError
*
* Adds and error to the form.
*
* @date 4/9/18
* @since 5.7.5
*
* @param object error An error object containing input and message.
* @return void
*/
addError: function( error ){
this.data.errors.push( error );
},
/**
* hasErrors
*
* Returns true if the form has errors.
*
* @date 4/9/18
* @since 5.7.5
*
* @param void
* @return bool
*/
hasErrors: function(){
return this.data.errors.length;
},
/**
* clearErrors
*
* Removes any errors.
*
* @date 4/9/18
* @since 5.7.5
*
* @param void
* @return void
*/
clearErrors: function(){
return this.data.errors = [];
},
/**
* getErrors
*
* Returns the forms errors.
*
* @date 4/9/18
* @since 5.7.5
*
* @param void
* @return array
*/
getErrors: function(){
return this.data.errors;
},
/**
* getFieldErrors
*
* Returns the forms field errors.
*
* @date 4/9/18
* @since 5.7.5
*
* @param void
* @return array
*/
getFieldErrors: function(){
// vars
var errors = [];
var inputs = [];
// loop
this.getErrors().map(function(error){
// bail early if global
if( !error.input ) return;
// update if exists
var i = inputs.indexOf(error.input);
if( i > -1 ) {
errors[ i ] = error;
// update
} else {
errors.push( error );
inputs.push( error.input );
}
});
// return
return errors;
},
/**
* getGlobalErrors
*
* Returns the forms global errors (errors without a specific input).
*
* @date 4/9/18
* @since 5.7.5
*
* @param void
* @return array
*/
getGlobalErrors: function(){
// return array of errors that contain no input
return this.getErrors().filter(function(error){
return !error.input;
});
},
/**
* showErrors
*
* Displays all errors for this form.
*
* @date 4/9/18
* @since 5.7.5
*
* @param void
* @return void
*/
showErrors: function(){
// bail early if no errors
if( !this.hasErrors() ) {
return;
}
// vars
var fieldErrors = this.getFieldErrors();
var globalErrors = this.getGlobalErrors();
// vars
var errorCount = 0;
var $scrollTo = false;
// loop
fieldErrors.map(function( error ){
// get input
var $input = this.$('[name="' + error.input + '"]').first();
// if $_POST value was an array, this $input may not exist
if( !$input.length ) {
$input = this.$('[name^="' + error.input + '"]').first();
}
// bail early if input doesn't exist
if( !$input.length ) {
return;
}
// increase
errorCount++;
// get field
var field = acf.getClosestField( $input );
// show error
field.showError( error.message );
// set $scrollTo
if( !$scrollTo ) {
$scrollTo = field.$el;
}
}, this);
// errorMessage
var errorMessage = acf.__('Validation failed');
globalErrors.map(function( error ){
errorMessage += '. ' + error.message;
});
if( errorCount == 1 ) {
errorMessage += '. ' + acf.__('1 field requires attention');
} else if( errorCount > 1 ) {
errorMessage += '. ' + acf.__('%d fields require attention').replace('%d', errorCount);
}
// notice
if( this.has('notice') ) {
this.get('notice').update({
type: 'error',
text: errorMessage
});
} else {
var notice = acf.newNotice({
type: 'error',
text: errorMessage,
target: this.$el
});
this.set('notice', notice);
}
// if no $scrollTo, set to message
if( !$scrollTo ) {
$scrollTo = this.get('notice').$el;
}
// timeout
setTimeout(function(){
$("html, body").animate({ scrollTop: $scrollTo.offset().top - ( $(window).height() / 2 ) }, 500);
}, 10);
},
/**
* onChangeStatus
*
* Update the form class when changing the 'status' data
*
* @date 4/9/18
* @since 5.7.5
*
* @param object e The event object.
* @param jQuery $el The form element.
* @param string value The new status.
* @param string prevValue The old status.
* @return void
*/
onChangeStatus: function( e, $el, value, prevValue ){
this.$el.removeClass('is-'+prevValue).addClass('is-'+value);
},
/**
* validate
*
* Vaildates the form via AJAX.
*
* @date 4/9/18
* @since 5.7.5
*
* @param object args A list of settings to customize the validation process.
* @return bool True if the form is valid.
*/
validate: function( args ){
// default args
args = acf.parseArgs(args, {
// trigger event
event: false,
// reset the form after submit
reset: false,
// loading callback
loading: function(){},
// complete callback
complete: function(){},
// failure callback
failure: function(){},
// success callback
success: function( $form ){
$form.submit();
}
});
// return true if is valid - allows form submit
if( this.get('status') == 'valid' ) {
return true;
}
// return false if is currently validating - prevents form submit
if( this.get('status') == 'validating' ) {
return false;
}
// return true if no ACF fields exist (no need to validate)
if( !this.$('.acf-field').length ) {
return true;
}
// if event is provided, create a new success callback.
if( args.event ) {
var event = $.Event(null, args.event);
args.success = function(){
acf.enableSubmit( $(event.target) ).trigger( event );
}
}
// action for 3rd party
acf.doAction('validation_begin', this.$el);
// lock form
acf.lockForm( this.$el );
// loading callback
args.loading( this.$el );
// update status
this.set('status', 'validating');
// success callback
var onSuccess = function( json ){
// validate
if( !acf.isAjaxSuccess(json) ) {
return;
}
// filter
var data = acf.applyFilters('validation_complete', json.data, this.$el);
// add errors
if( !data.valid ) {
this.addErrors( data.errors );
}
};
// complete
var onComplete = function(){
// unlock form
acf.unlockForm( this.$el );
// failure
if( this.hasErrors() ) {
// update status
this.set('status', 'invalid');
// action
acf.doAction('validation_failure', this.$el);
// display errors
this.showErrors();
// failure callback
args.failure( this.$el );
// success
} else {
// update status
this.set('status', 'valid');
// remove previous error message
if( this.has('notice') ) {
this.get('notice').update({
type: 'success',
text: acf.__('Validation successful'),
timeout: 1000
});
}
// action
acf.doAction('validation_success', this.$el);
acf.doAction('submit', this.$el);
// success callback (submit form)
args.success( this.$el );
// lock form
acf.lockForm( this.$el );
// reset
if( args.reset ) {
this.reset();
}
}
// complete callback
args.complete( this.$el );
// clear errors
this.clearErrors();
};
// serialize form data
var data = acf.serialize( this.$el );
data.action = 'acf/validate_save_post';
// ajax
$.ajax({
url: acf.get('ajaxurl'),
data: acf.prepareForAjax(data),
type: 'post',
dataType: 'json',
context: this,
success: onSuccess,
complete: onComplete
});
},
/**
* setup
*
* Called during the constructor function to setup this instance
*
* @date 4/9/18
* @since 5.7.5
*
* @param jQuery $form The form element.
* @return void
*/
setup: function( $form ){
// set $el
this.$el = $form;
},
/**
* reset
*
* Rests the validation to be used again.
*
* @date 6/9/18
* @since 5.7.5
*
* @param void
* @return void
*/
reset: function(){
// reset data
this.set('errors', []);
this.set('notice', null);
this.set('status', '');
// unlock form
acf.unlockForm( this.$el );
}
});
/**
* getValidator
*
* Returns the instance for a given form element.
*
* @date 4/9/18
* @since 5.7.5
*
* @param jQuery $el The form element.
* @return object
*/
var getValidator = function( $el ){
// instantiate
var validator = $el.data('acf');
if( !validator ) {
validator = new Validator( $el );
}
// return
return validator;
};
/**
* acf.validateForm
*
* A helper function for the Validator.validate() function.
* Returns true if form is valid, or fetches a validation request and returns false.
*
* @date 4/4/18
* @since 5.6.9
*
* @param object args A list of settings to customize the validation process.
* @return bool
*/
acf.validateForm = function( args ){
return getValidator( args.form ).validate( args );
};
/**
* acf.enableSubmit
*
* Enables a submit button and returns the element.
*
* @date 30/8/18
* @since 5.7.4
*
* @param jQuery $submit The submit button.
* @return jQuery
*/
acf.enableSubmit = function( $submit ){
return $submit.removeClass('disabled');
};
/**
* acf.disableSubmit
*
* Disables a submit button and returns the element.
*
* @date 30/8/18
* @since 5.7.4
*
* @param jQuery $submit The submit button.
* @return jQuery
*/
acf.disableSubmit = function( $submit ){
return $submit.addClass('disabled');
};
/**
* acf.showSpinner
*
* Shows the spinner element.
*
* @date 4/9/18
* @since 5.7.5
*
* @param jQuery $spinner The spinner element.
* @return jQuery
*/
acf.showSpinner = function( $spinner ){
$spinner.addClass('is-active'); // add class (WP > 4.2)
$spinner.css('display', 'inline-block'); // css (WP < 4.2)
return $spinner;
};
/**
* acf.hideSpinner
*
* Hides the spinner element.
*
* @date 4/9/18
* @since 5.7.5
*
* @param jQuery $spinner The spinner element.
* @return jQuery
*/
acf.hideSpinner = function( $spinner ){
$spinner.removeClass('is-active'); // add class (WP > 4.2)
$spinner.css('display', 'none'); // css (WP < 4.2)
return $spinner;
};
/**
* acf.lockForm
*
* Locks a form by disabeling its primary inputs and showing a spinner.
*
* @date 4/9/18
* @since 5.7.5
*
* @param jQuery $form The form element.
* @return jQuery
*/
acf.lockForm = function( $form ){
// vars
var $wrap = findSubmitWrap( $form );
var $submit = $wrap.find('.button, [type="submit"]');
var $spinner = $wrap.find('.spinner, .acf-spinner');
// hide all spinners (hides the preview spinner)
acf.hideSpinner( $spinner );
// lock
acf.disableSubmit( $submit );
acf.showSpinner( $spinner.last() );
return $form;
};
/**
* acf.unlockForm
*
* Unlocks a form by enabeling its primary inputs and hiding all spinners.
*
* @date 4/9/18
* @since 5.7.5
*
* @param jQuery $form The form element.
* @return jQuery
*/
acf.unlockForm = function( $form ){
// vars
var $wrap = findSubmitWrap( $form );
var $submit = $wrap.find('.button, [type="submit"]');
var $spinner = $wrap.find('.spinner, .acf-spinner');
// unlock
acf.enableSubmit( $submit );
acf.hideSpinner( $spinner );
return $form;
};
/**
* findSubmitWrap
*
* An internal function to find the 'primary' form submit wrapping element.
*
* @date 4/9/18
* @since 5.7.5
*
* @param jQuery $form The form element.
* @return jQuery
*/
var findSubmitWrap = function( $form ){
// default post submit div
var $wrap = $form.find('#submitdiv');
if( $wrap.length ) {
return $wrap;
}
// 3rd party publish box
var $wrap = $form.find('#submitpost');
if( $wrap.length ) {
return $wrap;
}
// term, user
var $wrap = $form.find('p.submit').last();
if( $wrap.length ) {
return $wrap;
}
// front end form
var $wrap = $form.find('.acf-form-submit');
if( $wrap.length ) {
return $wrap;
}
// default
return $form;
};
/**
* acf.validation
*
* Global validation logic
*
* @date 4/4/18
* @since 5.6.9
*
* @param void
* @return void
*/
acf.validation = new acf.Model({
/** @var string The model identifier. */
id: 'validation',
/** @var bool The active state. Set to false before 'prepare' to prevent validation. */
active: true,
/** @var string The model initialize time. */
wait: 'prepare',
/** @var object The model actions. */
actions: {
'ready': 'addInputEvents',
'append': 'addInputEvents'
},
/** @var object The model events. */
events: {
'click input[type="submit"]': 'onClickSubmit',
'click button[type="submit"]': 'onClickSubmit',
'click #save-post': 'onClickSave',
'mousedown #post-preview': 'onClickPreview', // use mousedown to hook in before WP click event
'submit form': 'onSubmit',
},
/**
* initialize
*
* Called when initializing the model.
*
* @date 4/9/18
* @since 5.7.5
*
* @param void
* @return void
*/
initialize: function(){
// check 'validation' setting
if( !acf.get('validation') ) {
this.active = false;
this.actions = {};
this.events = {};
}
},
/**
* enable
*
* Enables validation.
*
* @date 4/9/18
* @since 5.7.5
*
* @param void
* @return void
*/
enable: function(){
this.active = true;
},
/**
* disable
*
* Disables validation.
*
* @date 4/9/18
* @since 5.7.5
*
* @param void
* @return void
*/
disable: function(){
this.active = false;
},
/**
* reset
*
* Rests the form validation to be used again
*
* @date 6/9/18
* @since 5.7.5
*
* @param jQuery $form The form element.
* @return void
*/
reset: function( $form ){
getValidator( $form ).reset();
},
/**
* addInputEvents
*
* Adds 'invalid' event listeners to HTML inputs.
*
* @date 4/9/18
* @since 5.7.5
*
* @param jQuery $el The element being added / readied.
* @return void
*/
addInputEvents: function( $el ){
// vars
var $inputs = $('.acf-field [name]', $el);
// check
if( $inputs.length ) {
this.on( $inputs, 'invalid', 'onInvalid' );
}
},
/**
* onInvalid
*
* Callback for the 'invalid' event.
*
* @date 4/9/18
* @since 5.7.5
*
* @param object e The event object.
* @param jQuery $el The input element.
* @return void
*/
onInvalid: function( e, $el ){
// prevent default
// - prevents browser error message
// - also fixes chrome bug where 'hidden-by-tab' field throws focus error
e.preventDefault();
// vars
var $form = $el.closest('form');
// check form exists
if( $form.length ) {
// add error to validator
getValidator( $form ).addError({
input: $el.attr('name'),
message: e.target.validationMessage
});
// trigger submit on $form
// - allows for "save", "preview" and "publish" to work
$form.submit();
}
},
/**
* onClickSubmit
*
* Callback when clicking submit.
*
* @date 4/9/18
* @since 5.7.5
*
* @param object e The event object.
* @param jQuery $el The input element.
* @return void
*/
onClickSubmit: function( e, $el ){
// store the "click event" for later use in this.onSubmit()
this.set('originalEvent', e);
},
/**
* onClickSave
*
* Set ignore to true when saving a draft.
*
* @date 4/9/18
* @since 5.7.5
*
* @param object e The event object.
* @param jQuery $el The input element.
* @return void
*/
onClickSave: function( e, $el ) {
this.set('ignore', true);
},
/**
* onClickPreview
*
* Set ignore to true when previewing a post.
*
* @date 4/9/18
* @since 5.7.5
*
* @param object e The event object.
* @param jQuery $el The input element.
* @return void
*/
onClickPreview: function( e, $el ) {
this.set('ignore', true);
// if post has previously been published but prevented by an error, WP core has
// added a custom 'submit.edit-post' event which causes the input buttons to become disabled.
// remove this event to prevent UX issues.
$('form#post').off('submit.edit-post');
},
/**
* onSubmit
*
* Callback when the form is submit.
*
* @date 4/9/18
* @since 5.7.5
*
* @param object e The event object.
* @param jQuery $el The input element.
* @return void
*/
onSubmit: function( e, $el ){
// bail early if is disabled
if( !this.active ) {
return;
}
// bail early if is ignore
if( this.get('ignore') ) {
this.set('ignore', false);
return;
}
// validate
var valid = acf.validateForm({
form: $el,
event: this.get('originalEvent')
});
// if not valid, stop event and allow validation to continue
if( !valid ) {
e.preventDefault();
}
}
});
})(jQuery);
(function($, undefined){
/**
* refreshHelper
*
* description
*
* @date 1/7/18
* @since 5.6.9
*
* @param type $var Description. Default.
* @return type Description.
*/
var refreshHelper = new acf.Model({
priority: 90,
timeout: 0,
actions: {
'new_field': 'refresh',
'show_field': 'refresh',
'hide_field': 'refresh',
'remove_field': 'refresh'
},
refresh: function(){
clearTimeout( this.timeout );
this.timeout = setTimeout(function(){
acf.doAction('refresh');
}, 0);
}
});
/**
* sortableHelper
*
* Adds compatibility for sorting a
element
*
* @date 6/3/18
* @since 5.6.9
*
* @param void
* @return void
*/
var sortableHelper = new acf.Model({
actions: {
'sortstart': 'onSortstart'
},
onSortstart: function( $item, $placeholder ){
// if $item is a tr, apply some css to the elements
if( $item.is('tr') ) {
// temp set as relative to find widths
$item.css('position', 'relative');
// set widths for td children
$item.children().each(function(){
$(this).width($(this).width());
});
// revert position css
$item.css('position', 'absolute');
// add markup to the placeholder
$placeholder.html('
');
}
}
});
/**
* duplicateHelper
*
* Fixes browser bugs when duplicating an element
*
* @date 6/3/18
* @since 5.6.9
*
* @param void
* @return void
*/
var duplicateHelper = new acf.Model({
actions: {
'after_duplicate': 'onAfterDuplicate'
},
onAfterDuplicate: function( $el, $el2 ){
// get original values
var vals = [];
$el.find('select').each(function(i){
vals.push( $(this).val() );
});
// set duplicate values
$el2.find('select').each(function(i){
$(this).val( vals[i] );
});
}
});
/**
* tableHelper
*
* description
*
* @date 6/3/18
* @since 5.6.9
*
* @param type $var Description. Default.
* @return type Description.
*/
var tableHelper = new acf.Model({
id: 'tableHelper',
priority: 20,
actions: {
'refresh': 'renderTables'
},
renderTables: function( $el ){
// loop
var self = this;
$('.acf-table:visible').each(function(){
self.renderTable( $(this) );
});
},
renderTable: function( $table ){
// vars
var $ths = $table.find('> thead > tr:visible > th[data-key]');
var $tds = $table.find('> tbody > tr:visible > td[data-key]');
// bail early if no thead
if( !$ths.length || !$tds.length ) {
return false;
}
// visiblity
$ths.each(function( i ){
// vars
var $th = $(this);
var key = $th.data('key');
var $cells = $tds.filter('[data-key="' + key + '"]');
var $hidden = $cells.filter('.acf-hidden');
// always remove empty and allow cells to be hidden
$cells.removeClass('acf-empty');
// hide $th if all cells are hidden
if( $cells.length === $hidden.length ) {
acf.hide( $th );
// force all hidden cells to appear empty
} else {
acf.show( $th );
$hidden.addClass('acf-empty');
}
});
// clear width
$ths.css('width', 'auto');
// get visible
$ths = $ths.not('.acf-hidden');
// vars
var availableWidth = 100;
var colspan = $ths.length;
// set custom widths first
var $fixedWidths = $ths.filter('[data-width]');
$fixedWidths.each(function(){
var width = $(this).data('width');
$(this).css('width', width + '%');
availableWidth -= width;
});
// set auto widths
var $auoWidths = $ths.not('[data-width]');
if( $auoWidths.length ) {
var width = availableWidth / $auoWidths.length;
$auoWidths.css('width', width + '%');
availableWidth = 0;
}
// avoid stretching issue
if( availableWidth > 0 ) {
$ths.last().css('width', 'auto');
}
// update colspan on collapsed
$tds.filter('.-collapsed-target').each(function(){
// vars
var $td = $(this);
// check if collapsed
if( $td.parent().hasClass('-collapsed') ) {
$td.attr('colspan', $ths.length);
} else {
$td.removeAttr('colspan');
}
});
}
});
/**
* fieldsHelper
*
* description
*
* @date 6/3/18
* @since 5.6.9
*
* @param type $var Description. Default.
* @return type Description.
*/
var fieldsHelper = new acf.Model({
id: 'fieldsHelper',
priority: 30,
actions: {
'refresh': 'renderGroups'
},
renderGroups: function(){
// loop
var self = this;
$('.acf-fields:visible').each(function(){
self.renderGroup( $(this) );
});
},
renderGroup: function( $el ){
// vars
var top = 0;
var height = 0;
var $row = $();
// get fields
var $fields = $el.children('.acf-field[data-width]:visible');
// bail early if no fields
if( !$fields.length ) {
return false;
}
// bail ealry if is .-left
if( $el.hasClass('-left') ) {
$fields.removeAttr('data-width');
$fields.css('width', 'auto');
return false;
}
// reset fields
$fields.removeClass('-r0 -c0').css({'min-height': 0});
// loop
$fields.each(function( i ){
// vars
var $field = $(this);
var position = $field.position();
var thisTop = Math.ceil( position.top );
var thisLeft = Math.ceil( position.left );
// detect change in row
if( $row.length && thisTop > top ) {
// set previous heights
$row.css({'min-height': height+'px'});
// update position due to change in row above
position = $field.position();
thisTop = Math.ceil( position.top );
thisLeft = Math.ceil( position.left );
// reset vars
top = 0;
height = 0;
$row = $();
}
// rtl
if( acf.get('rtl') ) {
thisLeft = Math.ceil( $field.parent().width() - (position.left + $field.outerWidth()) );
}
// add classes
if( thisTop == 0 ) {
$field.addClass('-r0');
} else if( thisLeft == 0 ) {
$field.addClass('-c0');
}
// get height after class change
// - add 1 for subpixel rendering
var thisHeight = Math.ceil( $field.outerHeight() ) + 1;
// set height
height = Math.max( height, thisHeight );
// set y
top = Math.max( top, thisTop );
// append
$row = $row.add( $field );
});
// clean up
if( $row.length ) {
$row.css({'min-height': height+'px'});
}
}
});
})(jQuery);
(function($, undefined){
/**
* acf.newCompatibility
*
* Inserts a new __proto__ object compatibility layer
*
* @date 15/2/18
* @since 5.6.9
*
* @param object instance The object to modify.
* @param object compatibilty Optional. The compatibilty layer.
* @return object compatibilty
*/
acf.newCompatibility = function( instance, compatibilty ){
// defaults
compatibilty = compatibilty || {};
// inherit __proto_-
compatibilty.__proto__ = instance.__proto__;
// inject
instance.__proto__ = compatibilty;
// reference
instance.compatibility = compatibilty;
// return
return compatibilty;
};
/**
* acf.getCompatibility
*
* Returns the compatibility layer for a given instance
*
* @date 13/3/18
* @since 5.6.9
*
* @param object instance The object to look in.
* @return object|null compatibility The compatibility object or null on failure.
*/
acf.getCompatibility = function( instance ) {
return instance.compatibility || null;
};
/**
* acf (compatibility)
*
* Compatibility layer for the acf object
*
* @date 15/2/18
* @since 5.6.9
*
* @param void
* @return void
*/
var _acf = acf.newCompatibility(acf, {
// storage
l10n: {},
o: {},
fields: {},
// changed function names
update: acf.set,
add_action: acf.addAction,
remove_action: acf.removeAction,
do_action: acf.doAction,
add_filter: acf.addFilter,
remove_filter: acf.removeFilter,
apply_filters: acf.applyFilters,
parse_args: acf.parseArgs,
disable_el: acf.disable,
disable_form: acf.disable,
enable_el: acf.enable,
enable_form: acf.enable,
update_user_setting: acf.updateUserSetting,
prepare_for_ajax: acf.prepareForAjax,
is_ajax_success: acf.isAjaxSuccess,
remove_el: acf.remove,
remove_tr: acf.remove,
str_replace: acf.strReplace,
render_select: acf.renderSelect,
get_uniqid: acf.uniqid,
serialize_form: acf.serialize,
esc_html: acf.strEscape,
str_sanitize: acf.strSanitize,
});
_acf._e = function( k1, k2 ){
// defaults
k1 = k1 || '';
k2 = k2 || '';
// compability
var compatKey = k2 ? k1 + '.' + k2 : k1;
var compats = {
'image.select': 'Select Image',
'image.edit': 'Edit Image',
'image.update': 'Update Image'
};
if( compats[compatKey] ) {
return acf.__(compats[compatKey]);
}
// try k1
var string = this.l10n[ k1 ] || '';
// try k2
if( k2 ) {
string = string[ k2 ] || '';
}
// return
return string;
};
_acf.get_selector = function( s ) {
// vars
var selector = '.acf-field';
// bail early if no search
if( !s ) {
return selector;
}
// compatibility with object
if( $.isPlainObject(s) ) {
if( $.isEmptyObject(s) ) {
return selector;
} else {
for( var k in s ) { s = s[k]; break; }
}
}
// append
selector += '-' + s;
// replace underscores (split/join replaces all and is faster than regex!)
selector = acf.strReplace('_', '-', selector);
// remove potential double up
selector = acf.strReplace('field-field-', 'field-', selector);
// return
return selector;
};
_acf.get_fields = function( s, $el, all ){
// args
var args = {
is: s || '',
parent: $el || false,
suppressFilters: all || false,
};
// change 'field_123' to '.acf-field-123'
if( args.is ) {
args.is = this.get_selector( args.is );
}
// return
return acf.findFields(args);
};
_acf.get_field = function( s, $el ){
// get fields
var $fields = this.get_fields.apply(this, arguments);
// return
if( $fields.length ) {
return $fields.first();
} else {
return false;
}
};
_acf.get_closest_field = function( $el, s ){
return $el.closest( this.get_selector(s) );
};
_acf.get_field_wrap = function( $el ){
return $el.closest( this.get_selector() );
};
_acf.get_field_key = function( $field ){
return $field.data('key');
};
_acf.get_field_type = function( $field ){
return $field.data('type');
};
_acf.get_data = function( $el, defaults ){
return acf.parseArgs( $el.data(), defaults );
};
_acf.maybe_get = function( obj, key, value ){
// default
if( value === undefined ) {
value = null;
}
// get keys
keys = String(key).split('.');
// acf.isget
for( var i = 0; i < keys.length; i++ ) {
if( !obj.hasOwnProperty(keys[i]) ) {
return value;
}
obj = obj[ keys[i] ];
}
return obj;
};
/**
* hooks
*
* Modify add_action and add_filter functions to add compatibility with changed $field parameter
* Using the acf.add_action() or acf.add_filter() functions will interpret new field parameters as jQuery $field
*
* @date 12/5/18
* @since 5.6.9
*
* @param void
* @return void
*/
var compatibleArgument = function( arg ){
return ( arg instanceof acf.Field ) ? arg.$el : arg;
};
var compatibleArguments = function( args ){
return acf.arrayArgs( args ).map( compatibleArgument );
}
var compatibleCallback = function( origCallback ){
return function(){
// convert to compatible arguments
if( arguments.length ) {
var args = compatibleArguments(arguments);
// add default argument for 'ready', 'append' and 'load' events
} else {
var args = [ $(document) ];
}
// return
return origCallback.apply(this, args);
}
}
_acf.add_action = function( action, callback, priority, context ){
// handle multiple actions
var actions = action.split(' ');
var length = actions.length;
if( length > 1 ) {
for( var i = 0; i < length; i++) {
action = actions[i];
_acf.add_action.apply(this, arguments);
}
return this;
}
// single
var callback = compatibleCallback(callback);
return acf.addAction.apply(this, arguments);
};
_acf.add_filter = function( action, callback, priority, context ){
var callback = compatibleCallback(callback);
return acf.addFilter.apply(this, arguments);
};
/*
* acf.model
*
* This model acts as a scafold for action.event driven modules
*
* @type object
* @date 8/09/2014
* @since 5.0.0
*
* @param (object)
* @return (object)
*/
_acf.model = {
actions: {},
filters: {},
events: {},
extend: function( args ){
// extend
var model = $.extend( {}, this, args );
// setup actions
$.each(model.actions, function( name, callback ){
model._add_action( name, callback );
});
// setup filters
$.each(model.filters, function( name, callback ){
model._add_filter( name, callback );
});
// setup events
$.each(model.events, function( name, callback ){
model._add_event( name, callback );
});
// return
return model;
},
_add_action: function( name, callback ) {
// split
var model = this,
data = name.split(' ');
// add missing priority
var name = data[0] || '',
priority = data[1] || 10;
// add action
acf.add_action(name, model[ callback ], priority, model);
},
_add_filter: function( name, callback ) {
// split
var model = this,
data = name.split(' ');
// add missing priority
var name = data[0] || '',
priority = data[1] || 10;
// add action
acf.add_filter(name, model[ callback ], priority, model);
},
_add_event: function( name, callback ) {
// vars
var model = this,
i = name.indexOf(' '),
event = (i > 0) ? name.substr(0,i) : name,
selector = (i > 0) ? name.substr(i+1) : '';
// event
var fn = function( e ){
// append $el to event object
e.$el = $(this);
// append $field to event object (used in field group)
if( acf.field_group ) {
e.$field = e.$el.closest('.acf-field-object');
}
// event
if( typeof model.event === 'function' ) {
e = model.event( e );
}
// callback
model[ callback ].apply(model, arguments);
};
// add event
if( selector ) {
$(document).on(event, selector, fn);
} else {
$(document).on(event, fn);
}
},
get: function( name, value ){
// defaults
value = value || null;
// get
if( typeof this[ name ] !== 'undefined' ) {
value = this[ name ];
}
// return
return value;
},
set: function( name, value ){
// set
this[ name ] = value;
// function for 3rd party
if( typeof this[ '_set_' + name ] === 'function' ) {
this[ '_set_' + name ].apply(this);
}
// return for chaining
return this;
}
};
/*
* field
*
* This model sets up many of the field's interactions
*
* @type function
* @date 21/02/2014
* @since 3.5.1
*
* @param n/a
* @return n/a
*/
_acf.field = acf.model.extend({
type: '',
o: {},
$field: null,
_add_action: function( name, callback ) {
// vars
var model = this;
// update name
name = name + '_field/type=' + model.type;
// add action
acf.add_action(name, function( $field ){
// focus
model.set('$field', $field);
// callback
model[ callback ].apply(model, arguments);
});
},
_add_filter: function( name, callback ) {
// vars
var model = this;
// update name
name = name + '_field/type=' + model.type;
// add action
acf.add_filter(name, function( $field ){
// focus
model.set('$field', $field);
// callback
model[ callback ].apply(model, arguments);
});
},
_add_event: function( name, callback ) {
// vars
var model = this,
event = name.substr(0,name.indexOf(' ')),
selector = name.substr(name.indexOf(' ')+1),
context = acf.get_selector(model.type);
// add event
$(document).on(event, context + ' ' + selector, function( e ){
// vars
var $el = $(this);
var $field = acf.get_closest_field( $el, model.type );
// bail early if no field
if( !$field.length ) return;
// focus
if( !$field.is(model.$field) ) {
model.set('$field', $field);
}
// append to event
e.$el = $el;
e.$field = $field;
// callback
model[ callback ].apply(model, [e]);
});
},
_set_$field: function(){
// callback
if( typeof this.focus === 'function' ) {
this.focus();
}
},
// depreciated
doFocus: function( $field ){
return this.set('$field', $field);
}
});
/**
* validation
*
* description
*
* @date 15/2/18
* @since 5.6.9
*
* @param type $var Description. Default.
* @return type Description.
*/
var _validation = acf.newCompatibility(acf.validation, {
remove_error: function( $field ){
acf.getField( $field ).removeError();
},
add_warning: function( $field, message ){
acf.getField( $field ).showNotice({
text: message,
type: 'warning',
timeout: 1000
});
},
fetch: acf.validateForm,
enableSubmit: acf.enableSubmit,
disableSubmit: acf.disableSubmit,
showSpinner: acf.showSpinner,
hideSpinner: acf.hideSpinner,
unlockForm: acf.unlockForm,
lockForm: acf.lockForm
});
/**
* tooltip
*
* description
*
* @date 15/2/18
* @since 5.6.9
*
* @param type $var Description. Default.
* @return type Description.
*/
_acf.tooltip = {
tooltip: function( text, $el ){
var tooltip = acf.newTooltip({
text: text,
target: $el
});
// return
return tooltip.$el;
},
temp: function( text, $el ){
var tooltip = acf.newTooltip({
text: text,
target: $el,
timeout: 250
});
},
confirm: function( $el, callback, text, button_y, button_n ){
var tooltip = acf.newTooltip({
confirm: true,
text: text,
target: $el,
confirm: function(){
callback(true);
},
cancel: function(){
callback(false);
}
});
},
confirm_remove: function( $el, callback ){
var tooltip = acf.newTooltip({
confirmRemove: true,
target: $el,
confirm: function(){
callback(true);
},
cancel: function(){
callback(false);
}
});
},
};
/**
* tooltip
*
* description
*
* @date 15/2/18
* @since 5.6.9
*
* @param type $var Description. Default.
* @return type Description.
*/
_acf.media = new acf.Model({
activeFrame: false,
actions: {
'new_media_popup': 'onNewMediaPopup'
},
frame: function(){
return this.activeFrame;
},
onNewMediaPopup: function( popup ){
this.activeFrame = popup.frame;
},
popup: function( props ){
// update props
if( props.mime_types ) {
props.allowedTypes = props.mime_types;
}
if( props.id ) {
props.attachment = props.id;
}
// new
var popup = acf.newMediaPopup( props );
// append
/*
if( props.selected ) {
popup.selected = props.selected;
}
*/
// return
return popup.frame;
}
});
/**
* Select2
*
* description
*
* @date 11/6/18
* @since 5.6.9
*
* @param type $var Description. Default.
* @return type Description.
*/
_acf.select2 = {
init: function( $select, args, $field ){
// compatible args
if( args.allow_null ) {
args.allowNull = args.allow_null;
}
if( args.ajax_action ) {
args.ajaxAction = args.ajax_action;
}
if( $field ) {
args.field = acf.getField($field);
}
// return
return acf.newSelect2( $select, args );
},
destroy: function( $select ){
return acf.getInstance( $select ).destroy();
},
};
/**
* postbox
*
* description
*
* @date 11/6/18
* @since 5.6.9
*
* @param type $var Description. Default.
* @return type Description.
*/
_acf.postbox = {
render: function( args ){
// compatible args
if( args.edit_url ) {
args.editLink = args.edit_url;
}
if( args.edit_title ) {
args.editTitle = args.edit_title;
}
// return
return acf.newPostbox( args );
}
};
/**
* acf.screen
*
* description
*
* @date 11/6/18
* @since 5.6.9
*
* @param type $var Description. Default.
* @return type Description.
*/
acf.newCompatibility(acf.screen, {
update: function(){
return this.set.apply(this, arguments);
},
fetch: acf.screen.check
});
_acf.ajax = acf.screen;
})(jQuery);
// @codekit-prepend "../js/acf.js";
// @codekit-prepend "../js/acf-hooks.js";
// @codekit-prepend "../js/acf-model.js";
// @codekit-prepend "../js/acf-popup.js";
// @codekit-prepend "../js/acf-unload.js";
// @codekit-prepend "../js/acf-panel.js";
// @codekit-prepend "../js/acf-notice.js";
// @codekit-prepend "../js/acf-postbox.js";
// @codekit-prepend "../js/acf-tooltip.js";
// @codekit-prepend "../js/acf-field.js";
// @codekit-prepend "../js/acf-fields.js";
// @codekit-prepend "../js/acf-field-accordion.js";
// @codekit-prepend "../js/acf-field-button-group.js";
// @codekit-prepend "../js/acf-field-checkbox.js";
// @codekit-prepend "../js/acf-field-color-picker.js";
// @codekit-prepend "../js/acf-field-date-picker.js";
// @codekit-prepend "../js/acf-field-date-time-picker.js";
// @codekit-prepend "../js/acf-field-google-map.js";
// @codekit-prepend "../js/acf-field-image.js";
// @codekit-prepend "../js/acf-field-file.js";
// @codekit-prepend "../js/acf-field-link.js";
// @codekit-prepend "../js/acf-field-oembed.js";
// @codekit-prepend "../js/acf-field-radio.js";
// @codekit-prepend "../js/acf-field-range.js";
// @codekit-prepend "../js/acf-field-relationship.js";
// @codekit-prepend "../js/acf-field-select.js";
// @codekit-prepend "../js/acf-field-tab.js";
// @codekit-prepend "../js/acf-field-post-object.js";
// @codekit-prepend "../js/acf-field-page-link.js";
// @codekit-prepend "../js/acf-field-user.js";
// @codekit-prepend "../js/acf-field-taxonomy.js";
// @codekit-prepend "../js/acf-field-time-picker.js";
// @codekit-prepend "../js/acf-field-true-false.js";
// @codekit-prepend "../js/acf-field-url.js";
// @codekit-prepend "../js/acf-field-wysiwyg.js";
// @codekit-prepend "../js/acf-condition.js";
// @codekit-prepend "../js/acf-conditions.js";
// @codekit-prepend "../js/acf-condition-types.js";
// @codekit-prepend "../js/acf-media.js";
// @codekit-prepend "../js/acf-screen.js";
// @codekit-prepend "../js/acf-select2.js";
// @codekit-prepend "../js/acf-tinymce.js";
// @codekit-prepend "../js/acf-validation.js";
// @codekit-prepend "../js/acf-helpers.js";
// @codekit-prepend "../js/acf-compatibility";