2406 lines
41 KiB
JavaScript
2406 lines
41 KiB
JavaScript
(function($){
|
|
|
|
// comon
|
|
acf.pro = acf.model.extend({
|
|
|
|
actions: {
|
|
'refresh': 'refresh',
|
|
},
|
|
|
|
filters: {
|
|
'get_fields' : 'get_fields',
|
|
},
|
|
|
|
get_fields: function( $fields ){
|
|
|
|
// remove clone fields
|
|
$fields = $fields.not('.acf-clone .acf-field');
|
|
|
|
// return
|
|
return $fields;
|
|
|
|
},
|
|
|
|
|
|
/*
|
|
* refresh
|
|
*
|
|
* This function will run when acf detects a refresh is needed on the UI
|
|
* Most commonly after ready / conditional logic change
|
|
*
|
|
* @type function
|
|
* @date 10/11/2014
|
|
* @since 5.0.9
|
|
*
|
|
* @param n/a
|
|
* @return n/a
|
|
*/
|
|
|
|
refresh: function( $el ){
|
|
|
|
// reference
|
|
var self = this;
|
|
|
|
|
|
// defaults
|
|
$el = $el || false;
|
|
|
|
|
|
// if is row
|
|
if( $el && $el.is('tr') ) {
|
|
|
|
self.render_table( $el.closest('table') );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
// find and rener all tables
|
|
$('.acf-table', $el).each(function(){
|
|
|
|
self.render_table( $(this) );
|
|
|
|
});
|
|
|
|
},
|
|
|
|
render_table: function( $table ){
|
|
|
|
// vars
|
|
var $ths = $table.find('> thead th.acf-th'),
|
|
colspan = 1,
|
|
available_width = 100;
|
|
|
|
|
|
// bail early if no $ths
|
|
if( !$ths.exists() ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
// render th/td visibility
|
|
$ths.each(function(){
|
|
|
|
// vars
|
|
var $th = $(this),
|
|
key = $th.attr('data-key'),
|
|
$td = $table.find('td[data-key="' + key + '"]');
|
|
|
|
|
|
// clear class
|
|
$td.removeClass('appear-empty');
|
|
$th.removeClass('hidden-by-conditional-logic');
|
|
|
|
|
|
// no td
|
|
if( !$td.exists() ) {
|
|
|
|
// do nothing
|
|
|
|
// if all td are hidden
|
|
} else if( $td.not('.hidden-by-conditional-logic').length == 0 ) {
|
|
|
|
$th.addClass('hidden-by-conditional-logic');
|
|
|
|
// if 1 or more td are visible
|
|
} else {
|
|
|
|
$td.filter('.hidden-by-conditional-logic').addClass('appear-empty');
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// clear widths
|
|
$ths.css('width', 'auto');
|
|
|
|
|
|
// update $ths
|
|
$ths = $ths.not('.hidden-by-conditional-logic');
|
|
|
|
|
|
// set colspan
|
|
colspan = $ths.length;
|
|
|
|
|
|
// set custom widths first
|
|
$ths.filter('[data-width]').each(function(){
|
|
|
|
// vars
|
|
var width = parseInt( $(this).attr('data-width') );
|
|
|
|
|
|
// remove from available
|
|
available_width -= width;
|
|
|
|
|
|
// set width
|
|
$(this).css('width', width + '%');
|
|
|
|
});
|
|
|
|
|
|
// update $ths
|
|
$ths = $ths.not('[data-width]');
|
|
|
|
|
|
// set custom widths first
|
|
$ths.each(function(){
|
|
|
|
// cal width
|
|
var width = available_width / $ths.length;
|
|
|
|
|
|
// set width
|
|
$(this).css('width', width + '%');
|
|
|
|
});
|
|
|
|
|
|
// update colspan
|
|
$table.find('.acf-row .acf-field.-collapsed-target').removeAttr('colspan');
|
|
$table.find('.acf-row.-collapsed .acf-field.-collapsed-target').attr('colspan', colspan);
|
|
|
|
},
|
|
|
|
|
|
});
|
|
|
|
})(jQuery);
|
|
|
|
(function($){
|
|
|
|
acf.fields.repeater = acf.field.extend({
|
|
|
|
type: 'repeater',
|
|
$el: null,
|
|
$input: null,
|
|
$table: null,
|
|
$tbody: null,
|
|
$clone: null,
|
|
|
|
actions: {
|
|
'ready': 'initialize',
|
|
'append': 'initialize',
|
|
'show': 'show'
|
|
},
|
|
|
|
events: {
|
|
'click a[data-event="add-row"]': '_add',
|
|
'click a[data-event="remove-row"]': '_remove',
|
|
'click a[data-event="collapse-row"]': '_collapse',
|
|
'mouseenter td.order': '_mouseenter'
|
|
},
|
|
|
|
focus: function(){
|
|
|
|
// vars
|
|
this.$el = this.$field.find('.acf-repeater:first');
|
|
this.$input = this.$field.find('input:first');
|
|
this.$table = this.$field.find('table:first');
|
|
this.$tbody = this.$table.children('tbody');
|
|
this.$clone = this.$tbody.children('tr.acf-clone');
|
|
|
|
|
|
// get options
|
|
this.o = acf.get_data( this.$el );
|
|
|
|
|
|
// min / max
|
|
this.o.min = this.o.min || 0;
|
|
this.o.max = this.o.max || 0;
|
|
|
|
},
|
|
|
|
initialize: function(){
|
|
|
|
// disable clone inputs
|
|
this.$clone.find('input, textarea, select').attr('disabled', 'disabled');
|
|
|
|
|
|
// render
|
|
this.render();
|
|
|
|
},
|
|
|
|
show: function(){
|
|
|
|
this.$tbody.find('.acf-field:visible').each(function(){
|
|
|
|
acf.do_action('show_field', $(this));
|
|
|
|
});
|
|
|
|
},
|
|
|
|
count: function(){
|
|
|
|
return this.$tbody.children().length - 1;
|
|
|
|
},
|
|
|
|
render: function(){
|
|
|
|
// update order numbers
|
|
this.$tbody.children().each(function(i){
|
|
|
|
$(this).find('> td.order > span').html( i+1 );
|
|
|
|
});
|
|
|
|
|
|
// empty?
|
|
if( this.count() == 0 ) {
|
|
|
|
this.$el.addClass('-empty');
|
|
|
|
} else {
|
|
|
|
this.$el.removeClass('-empty');
|
|
|
|
}
|
|
|
|
|
|
// row limit reached
|
|
if( this.o.max > 0 && this.count() >= this.o.max ) {
|
|
|
|
this.$el.find('> .acf-actions .button').addClass('disabled');
|
|
|
|
} else {
|
|
|
|
this.$el.find('> .acf-actions .button').removeClass('disabled');
|
|
|
|
}
|
|
|
|
},
|
|
|
|
add: function( $tr ){
|
|
|
|
// defaults
|
|
$tr = $tr || this.$clone;
|
|
|
|
|
|
// validate
|
|
if( this.o.max > 0 && this.count() >= this.o.max ) {
|
|
|
|
alert( acf._e('repeater','max').replace('{max}', this.o.max) );
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
// reference
|
|
var $field = this.$field;
|
|
|
|
|
|
// duplicate
|
|
$el = acf.duplicate( this.$clone );
|
|
|
|
|
|
// remove clone class
|
|
$el.removeClass('acf-clone');
|
|
|
|
|
|
// enable inputs (ignore inputs disabled for life)
|
|
$el.find('input, textarea, select').not('.acf-disabled').removeAttr('disabled');
|
|
|
|
|
|
// move row
|
|
$tr.before( $el );
|
|
|
|
|
|
// focus (may have added sub repeater)
|
|
this.doFocus($field);
|
|
|
|
|
|
// update order
|
|
this.render();
|
|
|
|
|
|
// validation
|
|
acf.validation.remove_error( this.$field );
|
|
|
|
|
|
// sync collapsed order
|
|
this.sync();
|
|
|
|
|
|
// return
|
|
return $el;
|
|
|
|
},
|
|
|
|
remove: function( $tr ){
|
|
|
|
// reference
|
|
var self = this;
|
|
|
|
|
|
// validate
|
|
if( this.count() <= this.o.min ) {
|
|
|
|
alert( acf._e('repeater','min').replace('{min}', this.o.min) );
|
|
return false;
|
|
}
|
|
|
|
|
|
// action for 3rd party customization
|
|
acf.do_action('remove', $tr);
|
|
|
|
|
|
// animate out tr
|
|
acf.remove_tr( $tr, function(){
|
|
|
|
// trigger change to allow attachment save
|
|
self.$input.trigger('change');
|
|
|
|
|
|
// render
|
|
self.render();
|
|
|
|
|
|
// sync collapsed order
|
|
self.sync();
|
|
|
|
|
|
// refersh field (hide/show columns)
|
|
acf.do_action('refresh', self.$field);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
sync: function(){
|
|
|
|
// vars
|
|
var name = 'collapsed_' + this.$field.data('key'),
|
|
collapsed = [];
|
|
|
|
|
|
// populate collapsed value
|
|
this.$tbody.children().each(function( i ){
|
|
|
|
if( $(this).hasClass('-collapsed') ) {
|
|
|
|
collapsed.push( i );
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
// update
|
|
acf.update_user_setting( name, collapsed.join(',') );
|
|
|
|
},
|
|
|
|
|
|
/*
|
|
* events
|
|
*
|
|
* these functions are fired for this fields events
|
|
*
|
|
* @type function
|
|
* @date 17/09/2015
|
|
* @since 5.2.3
|
|
*
|
|
* @param e
|
|
* @return n/a
|
|
*/
|
|
|
|
_mouseenter: function( e ){ //console.log('_mouseenter');
|
|
|
|
// bail early if already sortable
|
|
if( this.$tbody.hasClass('ui-sortable') ) return;
|
|
|
|
|
|
// bail early if max 1 row
|
|
if( this.o.max == 1 ) return;
|
|
|
|
|
|
// reference
|
|
var self = this;
|
|
|
|
|
|
// add sortable
|
|
this.$tbody.sortable({
|
|
items: '> tr',
|
|
handle: '> td.order',
|
|
forceHelperSize: true,
|
|
forcePlaceholderSize: true,
|
|
scroll: true,
|
|
start: function(event, ui) {
|
|
|
|
acf.do_action('sortstart', ui.item, ui.placeholder);
|
|
|
|
},
|
|
stop: function(event, ui) {
|
|
|
|
// render
|
|
self.render();
|
|
|
|
acf.do_action('sortstop', ui.item, ui.placeholder);
|
|
|
|
},
|
|
update: function(event, ui) {
|
|
|
|
// trigger change
|
|
self.$input.trigger('change');
|
|
|
|
}
|
|
|
|
});
|
|
|
|
},
|
|
|
|
_add: function( e ){ //console.log('_add');
|
|
|
|
// vars
|
|
$row = false;
|
|
|
|
|
|
// row add
|
|
if( e.$el.hasClass('acf-icon') ) {
|
|
|
|
$row = e.$el.closest('.acf-row');
|
|
|
|
}
|
|
|
|
|
|
// add
|
|
this.add( $row );
|
|
|
|
},
|
|
|
|
_remove: function( e ){ //console.log('_remove');
|
|
|
|
this.remove( e.$el.closest('.acf-row') );
|
|
|
|
},
|
|
|
|
_collapse: function( e ){ //console.log('_collapse');
|
|
|
|
// vars
|
|
var $tr = e.$el.closest('.acf-row');
|
|
|
|
|
|
// reference
|
|
var $field = this.$field;
|
|
|
|
|
|
// open row
|
|
if( $tr.hasClass('-collapsed') ) {
|
|
|
|
$tr.removeClass('-collapsed');
|
|
|
|
acf.do_action('show', $tr, 'collapse');
|
|
|
|
} else {
|
|
|
|
$tr.addClass('-collapsed');
|
|
|
|
acf.do_action('hide', $tr, 'collapse');
|
|
|
|
}
|
|
|
|
|
|
// sync
|
|
this.set('$field', $field).sync();
|
|
|
|
|
|
// refersh field (hide/show columns)
|
|
acf.do_action('refresh', this.$field);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
})(jQuery);
|
|
|
|
(function($){
|
|
|
|
acf.fields.flexible_content = acf.field.extend({
|
|
|
|
type: 'flexible_content',
|
|
$el: null,
|
|
$input: null,
|
|
$values: null,
|
|
$clones: null,
|
|
|
|
actions: {
|
|
'ready': 'initialize',
|
|
'append': 'initialize',
|
|
'show': 'show'
|
|
},
|
|
|
|
events: {
|
|
'click [data-event="add-layout"]': '_open',
|
|
'click [data-event="remove-layout"]': '_remove',
|
|
'click [data-event="collapse-layout"]': '_collapse',
|
|
'click .acf-fc-layout-handle': '_collapse',
|
|
'click .acf-fc-popup a': '_add',
|
|
'blur .acf-fc-popup .focus': '_close',
|
|
'mouseenter .acf-fc-layout-handle': '_mouseenter'
|
|
},
|
|
|
|
focus: function(){
|
|
|
|
// vars
|
|
this.$el = this.$field.find('.acf-flexible-content:first');
|
|
this.$input = this.$el.siblings('input');
|
|
this.$values = this.$el.children('.values');
|
|
this.$clones = this.$el.children('.clones');
|
|
|
|
|
|
// get options
|
|
this.o = acf.get_data( this.$el );
|
|
|
|
|
|
// min / max
|
|
this.o.min = this.o.min || 0;
|
|
this.o.max = this.o.max || 0;
|
|
|
|
},
|
|
|
|
count: function(){
|
|
|
|
return this.$values.children('.layout').length;
|
|
|
|
},
|
|
|
|
initialize: function(){
|
|
|
|
// disable clone inputs
|
|
this.$clones.find('input, textarea, select').attr('disabled', 'disabled');
|
|
|
|
|
|
// render
|
|
this.render();
|
|
|
|
},
|
|
|
|
show: function(){
|
|
|
|
this.$values.find('.acf-field:visible').each(function(){
|
|
|
|
acf.do_action('show_field', $(this));
|
|
|
|
});
|
|
|
|
},
|
|
|
|
render: function(){
|
|
|
|
// vars
|
|
var self = this;
|
|
|
|
|
|
// update order numbers
|
|
this.$values.children('.layout').each(function( i ){
|
|
|
|
$(this).find('> .acf-fc-layout-handle .acf-fc-layout-order').html( i+1 );
|
|
|
|
});
|
|
|
|
|
|
// empty?
|
|
if( this.count() == 0 ) {
|
|
|
|
this.$el.addClass('empty');
|
|
|
|
} else {
|
|
|
|
this.$el.removeClass('empty');
|
|
|
|
}
|
|
|
|
|
|
// row limit reached
|
|
if( this.o.max > 0 && this.count() >= this.o.max ) {
|
|
|
|
this.$el.find('> .acf-actions .button').addClass('disabled');
|
|
|
|
} else {
|
|
|
|
this.$el.find('> .acf-actions .button').removeClass('disabled');
|
|
|
|
}
|
|
|
|
},
|
|
|
|
render_layout_title: function( $layout ){
|
|
|
|
// vars
|
|
var ajax_data = acf.serialize( $layout );
|
|
|
|
|
|
// append
|
|
ajax_data = acf.parse_args( ajax_data, {
|
|
action: 'acf/fields/flexible_content/layout_title',
|
|
field_key: this.$field.data('key'),
|
|
i: $layout.index(),
|
|
layout: $layout.data('layout'),
|
|
});
|
|
|
|
|
|
// prepare
|
|
ajax_data = acf.prepare_for_ajax(ajax_data);
|
|
|
|
|
|
// ajax get title HTML
|
|
$.ajax({
|
|
url : acf.get('ajaxurl'),
|
|
dataType : 'html',
|
|
type : 'post',
|
|
data : ajax_data,
|
|
success: function( html ){
|
|
|
|
// bail early if no html
|
|
if( !html ) return;
|
|
|
|
|
|
// update html
|
|
$layout.find('> .acf-fc-layout-handle').html( html );
|
|
|
|
}
|
|
});
|
|
|
|
},
|
|
|
|
validate_add: function( layout ){
|
|
|
|
// vadiate max
|
|
if( this.o.max > 0 && this.count() >= this.o.max ) {
|
|
|
|
// vars
|
|
var identifier = ( this.o.max == 1 ) ? 'layout' : 'layouts',
|
|
s = acf._e('flexible_content', 'max');
|
|
|
|
|
|
// translate
|
|
s = s.replace('{max}', this.o.max);
|
|
s = s.replace('{identifier}', acf._e('flexible_content', identifier));
|
|
|
|
|
|
// alert
|
|
alert( s );
|
|
|
|
|
|
// return
|
|
return false;
|
|
}
|
|
|
|
|
|
// vadiate max layout
|
|
var $popup = $( this.$el.children('.tmpl-popup').html() ),
|
|
$a = $popup.find('[data-layout="' + layout + '"]'),
|
|
layout_max = parseInt( $a.attr('data-max') ),
|
|
layout_count = this.$values.children('.layout[data-layout="' + layout + '"]').length;
|
|
|
|
|
|
if( layout_max > 0 && layout_count >= layout_max ) {
|
|
|
|
// vars
|
|
var identifier = ( layout_max == 1 ) ? 'layout' : 'layouts',
|
|
s = acf._e('flexible_content', 'max_layout');
|
|
|
|
|
|
// translate
|
|
s = s.replace('{max}', layout_count);
|
|
s = s.replace('{label}', '"' + $a.text() + '"');
|
|
s = s.replace('{identifier}', acf._e('flexible_content', identifier));
|
|
|
|
|
|
// alert
|
|
alert( s );
|
|
|
|
|
|
// return
|
|
return false;
|
|
}
|
|
|
|
|
|
// return
|
|
return true;
|
|
|
|
},
|
|
|
|
validate_remove: function( layout ){
|
|
|
|
// vadiate min
|
|
if( this.o.min > 0 && this.count() <= this.o.min ) {
|
|
|
|
// vars
|
|
var identifier = ( this.o.min == 1 ) ? 'layout' : 'layouts',
|
|
s = acf._e('flexible_content', 'min') + ', ' + acf._e('flexible_content', 'remove');
|
|
|
|
|
|
// translate
|
|
s = s.replace('{min}', this.o.min);
|
|
s = s.replace('{identifier}', acf._e('flexible_content', identifier));
|
|
s = s.replace('{layout}', acf._e('flexible_content', 'layout'));
|
|
|
|
|
|
// return
|
|
return confirm( s );
|
|
|
|
}
|
|
|
|
|
|
// vadiate max layout
|
|
var $popup = $( this.$el.children('.tmpl-popup').html() ),
|
|
$a = $popup.find('[data-layout="' + layout + '"]'),
|
|
layout_min = parseInt( $a.attr('data-min') ),
|
|
layout_count = this.$values.children('.layout[data-layout="' + layout + '"]').length;
|
|
|
|
|
|
if( layout_min > 0 && layout_count <= layout_min ) {
|
|
|
|
// vars
|
|
var identifier = ( layout_min == 1 ) ? 'layout' : 'layouts',
|
|
s = acf._e('flexible_content', 'min_layout') + ', ' + acf._e('flexible_content', 'remove');
|
|
|
|
|
|
// translate
|
|
s = s.replace('{min}', layout_count);
|
|
s = s.replace('{label}', '"' + $a.text() + '"');
|
|
s = s.replace('{identifier}', acf._e('flexible_content', identifier));
|
|
s = s.replace('{layout}', acf._e('flexible_content', 'layout'));
|
|
|
|
|
|
// return
|
|
return confirm( s );
|
|
}
|
|
|
|
|
|
// return
|
|
return true;
|
|
|
|
},
|
|
|
|
sync: function(){
|
|
|
|
// vars
|
|
var name = 'collapsed_' + this.$field.data('key'),
|
|
collapsed = [];
|
|
|
|
|
|
// populate collapsed value
|
|
this.$values.children('.layout').each(function( i ){
|
|
|
|
if( $(this).hasClass('-collapsed') ) {
|
|
|
|
collapsed.push( i );
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
// update
|
|
acf.update_user_setting( name, collapsed.join(',') );
|
|
|
|
},
|
|
|
|
add: function( layout, $before ){
|
|
|
|
// defaults
|
|
$before = $before || false;
|
|
|
|
|
|
// bail early if validation fails
|
|
if( !this.validate_add(layout) ) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
// reference
|
|
var $field = this.$field;
|
|
|
|
|
|
// vars
|
|
var $clone = this.$clones.children('.layout[data-layout="' + layout + '"]');
|
|
|
|
|
|
// duplicate
|
|
$el = acf.duplicate( $clone );
|
|
|
|
|
|
// enable inputs (ignore inputs disabled for life)
|
|
$el.find('input, textarea, select').not('.acf-disabled').removeAttr('disabled');
|
|
|
|
|
|
// hide no values message
|
|
this.$el.children('.no-value-message').hide();
|
|
|
|
|
|
// add row
|
|
if( $before ) {
|
|
|
|
$before.before( $el );
|
|
|
|
} else {
|
|
|
|
this.$values.append( $el );
|
|
|
|
}
|
|
|
|
|
|
// focus (may have added sub flexible content)
|
|
this.doFocus($field);
|
|
|
|
|
|
// update order
|
|
this.render();
|
|
|
|
|
|
// validation
|
|
acf.validation.remove_error( this.$field );
|
|
|
|
|
|
// sync collapsed order
|
|
this.sync();
|
|
|
|
},
|
|
|
|
|
|
/*
|
|
* events
|
|
*
|
|
* these functions are fired for this fields events
|
|
*
|
|
* @type function
|
|
* @date 17/09/2015
|
|
* @since 5.2.3
|
|
*
|
|
* @param e
|
|
* @return n/a
|
|
*/
|
|
|
|
_mouseenter: function( e ){ //console.log('_mouseenter');
|
|
|
|
// bail early if already sortable
|
|
if( this.$values.hasClass('ui-sortable') ) return;
|
|
|
|
|
|
// bail early if max 1 row
|
|
if( this.o.max == 1 ) return;
|
|
|
|
|
|
// reference
|
|
var self = this;
|
|
|
|
|
|
// sortable
|
|
this.$values.sortable({
|
|
items: '> .layout',
|
|
handle: '> .acf-fc-layout-handle',
|
|
forceHelperSize: true,
|
|
forcePlaceholderSize: true,
|
|
scroll: true,
|
|
start: function(event, ui) {
|
|
|
|
acf.do_action('sortstart', ui.item, ui.placeholder);
|
|
|
|
},
|
|
stop: function(event, ui) {
|
|
|
|
// render
|
|
self.render();
|
|
|
|
acf.do_action('sortstop', ui.item, ui.placeholder);
|
|
|
|
},
|
|
update: function(event, ui) {
|
|
|
|
// trigger change
|
|
self.$input.trigger('change');
|
|
|
|
}
|
|
});
|
|
|
|
},
|
|
|
|
_open: function( e ){ //console.log('_open');
|
|
|
|
// reference
|
|
var $values = this.$values;
|
|
|
|
|
|
// vars
|
|
var $popup = $( this.$el.children('.tmpl-popup').html() );
|
|
|
|
|
|
// modify popup
|
|
$popup.find('a').each(function(){
|
|
|
|
// vars
|
|
var min = parseInt( $(this).attr('data-min') ),
|
|
max = parseInt( $(this).attr('data-max') ),
|
|
name = $(this).attr('data-layout'),
|
|
label = $(this).text(),
|
|
count = $values.children('.layout[data-layout="' + name + '"]').length,
|
|
$status = $(this).children('.status');
|
|
|
|
|
|
if( max > 0 ) {
|
|
|
|
// find diff
|
|
var available = max - count,
|
|
s = acf._e('flexible_content', 'available'),
|
|
identifier = ( available == 1 ) ? 'layout' : 'layouts',
|
|
|
|
|
|
// translate
|
|
s = s.replace('{available}', available);
|
|
s = s.replace('{max}', max);
|
|
s = s.replace('{label}', '"' + label + '"');
|
|
s = s.replace('{identifier}', acf._e('flexible_content', identifier));
|
|
|
|
|
|
// show status
|
|
$status.show().text( available ).attr('title', s);
|
|
|
|
|
|
// limit reached?
|
|
if( available == 0 ) {
|
|
|
|
$status.addClass('warning');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
if( min > 0 ) {
|
|
|
|
// find diff
|
|
var required = min - count,
|
|
s = acf._e('flexible_content', 'required'),
|
|
identifier = ( required == 1 ) ? 'layout' : 'layouts',
|
|
|
|
|
|
// translate
|
|
s = s.replace('{required}', required);
|
|
s = s.replace('{min}', min);
|
|
s = s.replace('{label}', '"' + label + '"');
|
|
s = s.replace('{identifier}', acf._e('flexible_content', identifier));
|
|
|
|
|
|
// limit reached?
|
|
if( required > 0 ) {
|
|
|
|
$status.addClass('warning').show().text( required ).attr('title', s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
// add popup
|
|
e.$el.after( $popup );
|
|
|
|
|
|
// within layout?
|
|
if( e.$el.closest('.acf-fc-layout-controlls').exists() ) {
|
|
|
|
$popup.closest('.layout').addClass('-open');
|
|
|
|
}
|
|
|
|
|
|
// vars
|
|
$popup.css({
|
|
'margin-top' : 0 - $popup.height() - e.$el.outerHeight() - 14,
|
|
'margin-left' : ( e.$el.outerWidth() - $popup.width() ) / 2,
|
|
});
|
|
|
|
|
|
// check distance to top
|
|
var offset = $popup.offset().top;
|
|
|
|
if( offset < 30 ) {
|
|
|
|
$popup.css({
|
|
'margin-top' : 15
|
|
});
|
|
|
|
$popup.find('.bit').addClass('top');
|
|
}
|
|
|
|
|
|
// focus
|
|
$popup.children('.focus').trigger('focus');
|
|
|
|
},
|
|
|
|
_close: function( e ){ //console.log('_close');
|
|
|
|
var $popup = e.$el.parent(),
|
|
$layout = $popup.closest('.layout');
|
|
|
|
|
|
// hide controlls?
|
|
$layout.removeClass('-open');
|
|
|
|
|
|
// remove popup
|
|
setTimeout(function(){
|
|
|
|
$popup.remove();
|
|
|
|
}, 200);
|
|
|
|
},
|
|
|
|
_add: function( e ){ //console.log('_add');
|
|
|
|
// vars
|
|
var $popup = e.$el.closest('.acf-fc-popup'),
|
|
layout = e.$el.attr('data-layout'),
|
|
$before = false;
|
|
|
|
|
|
// move row
|
|
if( $popup.closest('.acf-fc-layout-controlls').exists() ) {
|
|
|
|
$before = $popup.closest('.layout');
|
|
|
|
}
|
|
|
|
|
|
// add row
|
|
this.add( layout, $before );
|
|
|
|
},
|
|
|
|
_remove: function( e ){ //console.log('_remove');
|
|
|
|
// reference
|
|
var self = this;
|
|
|
|
|
|
// vars
|
|
var $layout = e.$el.closest('.layout');
|
|
|
|
|
|
// bail early if validation fails
|
|
if( !this.validate_remove( $layout.attr('data-layout') ) ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
// close field
|
|
var end_height = 0,
|
|
$message = this.$el.children('.no-value-message');
|
|
|
|
if( $layout.siblings('.layout').length == 0 ) {
|
|
|
|
end_height = $message.outerHeight();
|
|
|
|
}
|
|
|
|
|
|
// action for 3rd party customization
|
|
acf.do_action('remove', $layout);
|
|
|
|
|
|
// remove
|
|
acf.remove_el( $layout, function(){
|
|
|
|
// update order
|
|
self.render();
|
|
|
|
|
|
// trigger change to allow attachment save
|
|
self.$input.trigger('change');
|
|
|
|
|
|
if( end_height > 0 ) {
|
|
|
|
$message.show();
|
|
|
|
}
|
|
|
|
|
|
// sync collapsed order
|
|
self.sync();
|
|
|
|
}, end_height);
|
|
|
|
},
|
|
|
|
_collapse: function( e ){ //console.log('_collapse');
|
|
|
|
// vars
|
|
var $layout = e.$el.closest('.layout');
|
|
|
|
|
|
// render
|
|
// - do this before calling actions to avoif focusing on the wrong field
|
|
this.render_layout_title( $layout );
|
|
|
|
|
|
// open
|
|
if( $layout.hasClass('-collapsed') ) {
|
|
|
|
$layout.removeClass('-collapsed');
|
|
|
|
acf.do_action('show', $layout, 'collapse');
|
|
|
|
// close
|
|
} else {
|
|
|
|
$layout.addClass('-collapsed');
|
|
|
|
acf.do_action('hide', $layout, 'collapse');
|
|
|
|
}
|
|
|
|
|
|
// sync collapsed order
|
|
this.sync();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
})(jQuery);
|
|
|
|
(function($){
|
|
|
|
acf.fields.gallery = acf.field.extend({
|
|
|
|
type: 'gallery',
|
|
$el: null,
|
|
$main: null,
|
|
$side: null,
|
|
$attachments: null,
|
|
$input: null,
|
|
//$attachment: null,
|
|
|
|
actions: {
|
|
'ready': 'initialize',
|
|
'append': 'initialize',
|
|
'show': 'resize'
|
|
},
|
|
|
|
events: {
|
|
'click .acf-gallery-attachment': '_select',
|
|
'click .acf-gallery-add': '_add',
|
|
'click .acf-gallery-remove': '_remove',
|
|
'click .acf-gallery-close': '_close',
|
|
'change .acf-gallery-sort': '_sort',
|
|
'click .acf-gallery-edit': '_edit',
|
|
'click .acf-gallery-update': '_update',
|
|
|
|
'change .acf-gallery-side input': '_update',
|
|
'change .acf-gallery-side textarea': '_update',
|
|
'change .acf-gallery-side select': '_update'
|
|
},
|
|
|
|
|
|
/*
|
|
* focus
|
|
*
|
|
* This function will setup variables when focused on a field
|
|
*
|
|
* @type function
|
|
* @date 12/04/2016
|
|
* @since 5.3.8
|
|
*
|
|
* @param n/a
|
|
* @return n/a
|
|
*/
|
|
|
|
focus: function(){
|
|
|
|
// el
|
|
this.$el = this.$field.find('.acf-gallery:first');
|
|
this.$main = this.$el.children('.acf-gallery-main');
|
|
this.$side = this.$el.children('.acf-gallery-side');
|
|
this.$attachments = this.$main.children('.acf-gallery-attachments');
|
|
this.$input = this.$el.find('input:first');
|
|
|
|
|
|
// get options
|
|
this.o = acf.get_data( this.$el );
|
|
|
|
|
|
// min / max
|
|
this.o.min = this.o.min || 0;
|
|
this.o.max = this.o.max || 0;
|
|
|
|
},
|
|
|
|
|
|
/*
|
|
* initialize
|
|
*
|
|
* This function will initialize the field
|
|
*
|
|
* @type function
|
|
* @date 12/04/2016
|
|
* @since 5.3.8
|
|
*
|
|
* @param n/a
|
|
* @return n/a
|
|
*/
|
|
|
|
initialize: function(){
|
|
|
|
// reference
|
|
var self = this,
|
|
$field = this.$field;
|
|
|
|
|
|
// sortable
|
|
this.$attachments.unbind('sortable').sortable({
|
|
|
|
items : '.acf-gallery-attachment',
|
|
forceHelperSize : true,
|
|
forcePlaceholderSize : true,
|
|
scroll : true,
|
|
|
|
start: function (event, ui) {
|
|
|
|
ui.placeholder.html( ui.item.html() );
|
|
ui.placeholder.removeAttr('style');
|
|
|
|
acf.do_action('sortstart', ui.item, ui.placeholder);
|
|
|
|
},
|
|
|
|
stop: function (event, ui) {
|
|
|
|
acf.do_action('sortstop', ui.item, ui.placeholder);
|
|
|
|
}
|
|
});
|
|
|
|
|
|
// resizable
|
|
this.$el.unbind('resizable').resizable({
|
|
handles: 's',
|
|
minHeight: 200,
|
|
stop: function(event, ui){
|
|
|
|
acf.update_user_setting('gallery_height', ui.size.height);
|
|
|
|
}
|
|
});
|
|
|
|
|
|
// resize
|
|
$(window).on('resize', function(){
|
|
|
|
self.set('$field', $field).resize();
|
|
|
|
});
|
|
|
|
|
|
// render
|
|
this.render();
|
|
|
|
|
|
// resize
|
|
this.resize();
|
|
|
|
},
|
|
|
|
|
|
/*
|
|
* resize
|
|
*
|
|
* This function will resize the columns
|
|
*
|
|
* @type function
|
|
* @date 20/04/2016
|
|
* @since 5.3.8
|
|
*
|
|
* @param $post_id (int)
|
|
* @return $post_id (int)
|
|
*/
|
|
|
|
resize: function(){
|
|
|
|
// vars
|
|
var min = 100,
|
|
max = 175,
|
|
columns = 4,
|
|
width = this.$el.width();
|
|
|
|
|
|
// get width
|
|
for( var i = 4; i < 20; i++ ) {
|
|
|
|
var w = width/i;
|
|
|
|
if( min < w && w < max ) {
|
|
|
|
columns = i;
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
// max columns css is 8
|
|
columns = Math.min(columns, 8);
|
|
|
|
|
|
// update data
|
|
this.$el.attr('data-columns', columns);
|
|
|
|
},
|
|
|
|
|
|
/*
|
|
* render
|
|
*
|
|
* This function will render classes etc
|
|
*
|
|
* @type function
|
|
* @date 19/04/2016
|
|
* @since 5.3.8
|
|
*
|
|
* @param n/a
|
|
* @return n/a
|
|
*/
|
|
|
|
render: function() {
|
|
|
|
// vars
|
|
var $select = this.$main.find('.acf-gallery-sort'),
|
|
$a = this.$main.find('.acf-gallery-add');
|
|
|
|
|
|
// disable a
|
|
if( this.o.max > 0 && this.count() >= this.o.max ) {
|
|
|
|
$a.addClass('disabled');
|
|
|
|
} else {
|
|
|
|
$a.removeClass('disabled');
|
|
|
|
}
|
|
|
|
|
|
// disable select
|
|
if( !this.count() ) {
|
|
|
|
$select.addClass('disabled');
|
|
|
|
} else {
|
|
|
|
$select.removeClass('disabled');
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
/*
|
|
* open_sidebar
|
|
*
|
|
* This function will open the gallery sidebar
|
|
*
|
|
* @type function
|
|
* @date 19/04/2016
|
|
* @since 5.3.8
|
|
*
|
|
* @param n/a
|
|
* @return n/a
|
|
*/
|
|
|
|
open_sidebar: function(){
|
|
|
|
// add class
|
|
this.$el.addClass('sidebar-open');
|
|
|
|
|
|
// hide bulk actions
|
|
this.$main.find('.acf-gallery-sort').hide();
|
|
|
|
|
|
// vars
|
|
var width = this.$el.width() / 3;
|
|
|
|
|
|
// set minimum width
|
|
width = parseInt( width );
|
|
width = Math.max( width, 350 );
|
|
|
|
|
|
// animate
|
|
this.$side.children('.acf-gallery-side-inner').css({ 'width' : width-1 });
|
|
this.$side.animate({ 'width' : width-1 }, 250);
|
|
this.$main.animate({ 'right' : width }, 250);
|
|
|
|
},
|
|
|
|
|
|
/*
|
|
* _close
|
|
*
|
|
* event listener
|
|
*
|
|
* @type function
|
|
* @date 12/04/2016
|
|
* @since 5.3.8
|
|
*
|
|
* @param e (event)
|
|
* @return n/a
|
|
*/
|
|
|
|
_close: function( e ){
|
|
|
|
this.close_sidebar();
|
|
|
|
},
|
|
|
|
|
|
/*
|
|
* close_sidebar
|
|
*
|
|
* This function will open the gallery sidebar
|
|
*
|
|
* @type function
|
|
* @date 19/04/2016
|
|
* @since 5.3.8
|
|
*
|
|
* @param n/a
|
|
* @return n/a
|
|
*/
|
|
|
|
close_sidebar: function(){
|
|
|
|
// remove class
|
|
this.$el.removeClass('sidebar-open');
|
|
|
|
|
|
// vars
|
|
var $select = this.$el.find('.acf-gallery-sort');
|
|
|
|
|
|
// clear selection
|
|
this.get_attachment('active').removeClass('active');
|
|
|
|
|
|
// disable sidebar
|
|
this.$side.find('input, textarea, select').attr('disabled', 'disabled');
|
|
|
|
|
|
// animate
|
|
this.$main.animate({ right: 0 }, 250);
|
|
this.$side.animate({ width: 0 }, 250, function(){
|
|
|
|
$select.show();
|
|
|
|
$(this).find('.acf-gallery-side-data').html('');
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
/*
|
|
* count
|
|
*
|
|
* This function will return the number of attachemnts
|
|
*
|
|
* @type function
|
|
* @date 12/04/2016
|
|
* @since 5.3.8
|
|
*
|
|
* @param n/a
|
|
* @return n/a
|
|
*/
|
|
|
|
count: function(){
|
|
|
|
return this.get_attachments().length;
|
|
|
|
},
|
|
|
|
|
|
/*
|
|
* get_attachments
|
|
*
|
|
* description
|
|
*
|
|
* @type function
|
|
* @date 19/04/2016
|
|
* @since 5.3.8
|
|
*
|
|
* @param $post_id (int)
|
|
* @return $post_id (int)
|
|
*/
|
|
|
|
get_attachments: function(){
|
|
|
|
return this.$attachments.children('.acf-gallery-attachment');
|
|
|
|
},
|
|
|
|
|
|
/*
|
|
* get_attachment
|
|
*
|
|
* This function will return an attachment
|
|
*
|
|
* @type function
|
|
* @date 19/04/2016
|
|
* @since 5.3.8
|
|
*
|
|
* @param id (string)
|
|
* @return $el
|
|
*/
|
|
|
|
get_attachment: function( s ){
|
|
|
|
// defaults
|
|
s = s || 0;
|
|
|
|
|
|
// update selector
|
|
if( s === 'active' ) {
|
|
|
|
s = '.active';
|
|
|
|
} else {
|
|
|
|
s = '[data-id="' + s + '"]';
|
|
|
|
}
|
|
|
|
|
|
// return
|
|
return this.$attachments.children( '.acf-gallery-attachment'+s );
|
|
|
|
},
|
|
|
|
|
|
/*
|
|
* render_attachment
|
|
*
|
|
* This functin will render an attachemnt
|
|
*
|
|
* @type function
|
|
* @date 20/04/2016
|
|
* @since 5.3.8
|
|
*
|
|
* @param $post_id (int)
|
|
* @return $post_id (int)
|
|
*/
|
|
|
|
render_attachment: function( data ){
|
|
|
|
// prepare
|
|
data = this.prepare(data);
|
|
|
|
|
|
// vars
|
|
var $attachment = this.get_attachment(data.id),
|
|
$margin = $attachment.find('.margin'),
|
|
$img = $attachment.find('img'),
|
|
$filename = $attachment.find('.filename'),
|
|
$input = $attachment.find('input[type="hidden"]');
|
|
|
|
|
|
// thumbnail
|
|
var thumbnail = data.url;
|
|
|
|
|
|
// image
|
|
if( data.type == 'image' ) {
|
|
|
|
// remove filename
|
|
$filename.remove();
|
|
|
|
// other (video)
|
|
} else {
|
|
|
|
// attempt to find attachment thumbnail
|
|
thumbnail = acf.maybe_get(data, 'thumb.src');
|
|
|
|
|
|
// update filenmae text
|
|
$filename.text( data.filename );
|
|
|
|
}
|
|
|
|
|
|
// default icon
|
|
if( !thumbnail ) {
|
|
|
|
thumbnail = acf._e('media', 'default_icon');
|
|
$attachment.addClass('-icon');
|
|
|
|
}
|
|
|
|
|
|
// update els
|
|
$img.attr({
|
|
'src': thumbnail,
|
|
'alt': data.alt,
|
|
'title': data.title
|
|
});
|
|
|
|
|
|
// update val
|
|
acf.val( $input, data.id );
|
|
|
|
},
|
|
|
|
|
|
_add: function( e ){
|
|
|
|
// validate
|
|
if( this.o.max > 0 && this.count() >= this.o.max ) {
|
|
|
|
acf.validation.add_warning( this.$field, acf._e('gallery', 'max'));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
// reference
|
|
var self = this,
|
|
$field = this.$field;
|
|
|
|
|
|
// popup
|
|
var frame = acf.media.popup({
|
|
|
|
title: acf._e('gallery', 'select'),
|
|
mode: 'select',
|
|
type: '',
|
|
field: this.$field.data('key'),
|
|
multiple: 'add',
|
|
library: this.o.library,
|
|
mime_types: this.o.mime_types,
|
|
select: function( attachment, i ) {
|
|
|
|
// add
|
|
self.set('$field', $field).add_attachment( attachment, i );
|
|
|
|
}
|
|
});
|
|
|
|
|
|
// modify DOM
|
|
frame.on('content:activate:browse', function(){
|
|
|
|
self.render_collection( frame );
|
|
|
|
frame.content.get().collection.on( 'reset add', function(){
|
|
|
|
self.render_collection( frame );
|
|
|
|
});
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
/*
|
|
* add_attachment
|
|
*
|
|
* This function will add an attachment
|
|
*
|
|
* @type function
|
|
* @date 20/04/2016
|
|
* @since 5.3.8
|
|
*
|
|
* @param $post_id (int)
|
|
* @return $post_id (int)
|
|
*/
|
|
|
|
add_attachment: function( data, i ){
|
|
|
|
// defaults
|
|
i = i || 0;
|
|
|
|
|
|
// prepare
|
|
data = this.prepare(data);
|
|
|
|
|
|
// validate
|
|
if( this.o.max > 0 && this.count() >= this.o.max ) return;
|
|
|
|
|
|
// is image already in gallery?
|
|
if( this.get_attachment(data.id).exists() ) return;
|
|
|
|
|
|
// vars
|
|
var name = this.$el.find('input[type="hidden"]:first').attr('name');
|
|
|
|
|
|
// html
|
|
var html = [
|
|
'<div class="acf-gallery-attachment acf-soh" data-id="' + data.id + '">',
|
|
'<input type="hidden" value="' + data.id + '" name="' + name + '[]">',
|
|
'<div class="margin" title="">',
|
|
'<div class="thumbnail">',
|
|
'<img src="" alt="">',
|
|
'</div>',
|
|
'<div class="filename"></div>',
|
|
'</div>',
|
|
'<div class="actions acf-soh-target">',
|
|
'<a href="#" class="acf-icon -cancel dark acf-gallery-remove" data-id="' + data.id + '"></a>',
|
|
'</div>',
|
|
'</div>'].join('');
|
|
|
|
var $html = $(html);
|
|
|
|
|
|
// append
|
|
this.$attachments.append( $html );
|
|
|
|
|
|
// more to beginning
|
|
if( this.o.insert === 'prepend' ) {
|
|
|
|
// vars
|
|
var $before = this.$attachments.children(':eq('+i+')');
|
|
|
|
|
|
// move
|
|
if( $before.exists() ) {
|
|
|
|
$before.before( $html );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
// render data
|
|
this.render_attachment( data );
|
|
|
|
|
|
// render
|
|
this.render();
|
|
|
|
|
|
// trigger change
|
|
this.$input.trigger('change');
|
|
|
|
},
|
|
|
|
|
|
/*
|
|
* _select
|
|
*
|
|
* event listener
|
|
*
|
|
* @type function
|
|
* @date 12/04/2016
|
|
* @since 5.3.8
|
|
*
|
|
* @param e (event)
|
|
* @return n/a
|
|
*/
|
|
|
|
_select: function( e ){
|
|
|
|
// vars
|
|
var id = e.$el.data('id');
|
|
|
|
|
|
// select
|
|
this.select_attachment(id);
|
|
|
|
},
|
|
|
|
|
|
/*
|
|
* select_attachment
|
|
*
|
|
* This function will select an attachment for editing
|
|
*
|
|
* @type function
|
|
* @date 20/04/2016
|
|
* @since 5.3.8
|
|
*
|
|
* @param $post_id (int)
|
|
* @return $post_id (int)
|
|
*/
|
|
|
|
select_attachment: function( id ){
|
|
|
|
// vars
|
|
var $attachment = this.get_attachment(id);
|
|
|
|
|
|
// bail early if already active
|
|
if( $attachment.hasClass('active') ) return;
|
|
|
|
|
|
// clear selection
|
|
this.get_attachment('active').removeClass('active');
|
|
|
|
|
|
// add selection
|
|
$attachment.addClass('active');
|
|
|
|
|
|
// fetch
|
|
this.fetch( id );
|
|
|
|
|
|
// open sidebar
|
|
this.open_sidebar();
|
|
|
|
},
|
|
|
|
|
|
/*
|
|
* prepare
|
|
*
|
|
* This function will prepare an object of attachment data
|
|
* selecting a library image vs embed an image via url return different data
|
|
* this function will keep the 2 consistent
|
|
*
|
|
* @type function
|
|
* @date 12/04/2016
|
|
* @since 5.3.8
|
|
*
|
|
* @param attachment (object)
|
|
* @return data (object)
|
|
*/
|
|
|
|
prepare: function( attachment ) {
|
|
|
|
// defaults
|
|
attachment = attachment || {};
|
|
|
|
|
|
// bail ealry if already valid
|
|
if( attachment._valid ) return attachment;
|
|
|
|
|
|
// vars
|
|
var data = {
|
|
id: '',
|
|
url: '',
|
|
alt: '',
|
|
title: '',
|
|
filename: ''
|
|
};
|
|
|
|
|
|
// wp image
|
|
if( attachment.id ) {
|
|
|
|
// update data
|
|
data = attachment.attributes;
|
|
|
|
|
|
// maybe get preview size
|
|
data.url = acf.maybe_get(data, 'sizes.medium.url', data.url);
|
|
|
|
}
|
|
|
|
|
|
// valid
|
|
data._valid = true;
|
|
|
|
|
|
// return
|
|
return data;
|
|
|
|
},
|
|
|
|
|
|
/*
|
|
* fetch
|
|
*
|
|
* This function will fetch the sidebar html to edit an attachment
|
|
*
|
|
* @type function
|
|
* @date 19/04/2016
|
|
* @since 5.3.8
|
|
*
|
|
* @param n/a
|
|
* @return n/a
|
|
*/
|
|
|
|
fetch: function( id ){
|
|
|
|
// vars
|
|
var data = acf.prepare_for_ajax({
|
|
action : 'acf/fields/gallery/get_attachment',
|
|
field_key : this.$field.data('key'),
|
|
id : id
|
|
});
|
|
|
|
|
|
// abort XHR if this field is already loading AJAX data
|
|
if( this.$el.data('xhr') ) {
|
|
|
|
this.$el.data('xhr').abort();
|
|
|
|
}
|
|
|
|
|
|
// add custom attachment
|
|
if( typeof id === 'string' && id.indexOf('_') === 0 ) {
|
|
|
|
// vars
|
|
var val = this.get_attachment(id).find('input[type="hidden"]').val();
|
|
|
|
|
|
// parse json
|
|
val = $.parseJSON(val);
|
|
|
|
|
|
// append
|
|
data.attachment = val;
|
|
|
|
}
|
|
|
|
|
|
// get results
|
|
var xhr = $.ajax({
|
|
url : acf.get('ajaxurl'),
|
|
dataType : 'html',
|
|
type : 'post',
|
|
cache : false,
|
|
data : data,
|
|
context : this,
|
|
success : this.fetch_success
|
|
});
|
|
|
|
|
|
// update el data
|
|
this.$el.data('xhr', xhr);
|
|
|
|
},
|
|
|
|
fetch_success: function( html ){
|
|
|
|
// bail early if no html
|
|
if( !html ) return;
|
|
|
|
|
|
// vars
|
|
var $side = this.$side.find('.acf-gallery-side-data');
|
|
|
|
|
|
// render
|
|
$side.html( html );
|
|
|
|
|
|
// remove acf form data
|
|
$side.find('.compat-field-acf-form-data').remove();
|
|
|
|
|
|
// detach meta tr
|
|
var $tr = $side.find('> .compat-attachment-fields > tbody > tr').detach();
|
|
|
|
|
|
// add tr
|
|
$side.find('> table.form-table > tbody').append( $tr );
|
|
|
|
|
|
// remove origional meta table
|
|
$side.find('> .compat-attachment-fields').remove();
|
|
|
|
|
|
// setup fields
|
|
acf.do_action('append', $side);
|
|
|
|
},
|
|
|
|
|
|
/*
|
|
* _sort
|
|
*
|
|
* event listener
|
|
*
|
|
* @type function
|
|
* @date 12/04/2016
|
|
* @since 5.3.8
|
|
*
|
|
* @param e (event)
|
|
* @return n/a
|
|
*/
|
|
|
|
_sort: function( e ){
|
|
|
|
// vars
|
|
var sort = e.$el.val();
|
|
|
|
|
|
// validate
|
|
if( !sort ) return;
|
|
|
|
|
|
// vars
|
|
var data = acf.prepare_for_ajax({
|
|
action : 'acf/fields/gallery/get_sort_order',
|
|
field_key : this.$field.data('key'),
|
|
ids : [],
|
|
sort : sort
|
|
});
|
|
|
|
|
|
// find and add attachment ids
|
|
this.get_attachments().each(function(){
|
|
|
|
// vars
|
|
var id = $(this).attr('data-id');
|
|
|
|
|
|
// bail early if no id (insert from url)
|
|
if( !id ) return;
|
|
|
|
|
|
// append
|
|
data.ids.push(id);
|
|
|
|
});
|
|
|
|
|
|
// get results
|
|
var xhr = $.ajax({
|
|
url: acf.get('ajaxurl'),
|
|
dataType: 'json',
|
|
type: 'post',
|
|
cache: false,
|
|
data: data,
|
|
context: this,
|
|
success: this._sort_success
|
|
});
|
|
},
|
|
|
|
_sort_success: function( json ) {
|
|
|
|
// validate
|
|
if( !acf.is_ajax_success(json) ) return;
|
|
|
|
|
|
// reverse order
|
|
json.data.reverse();
|
|
|
|
|
|
// loop over json
|
|
for( i in json.data ) {
|
|
|
|
var id = json.data[ i ],
|
|
$attachment = this.get_attachment(id);
|
|
|
|
|
|
// prepend attachment
|
|
this.$attachments.prepend( $attachment );
|
|
|
|
}
|
|
},
|
|
|
|
|
|
/*
|
|
* _update
|
|
*
|
|
* event listener
|
|
*
|
|
* @type function
|
|
* @date 12/04/2016
|
|
* @since 5.3.8
|
|
*
|
|
* @param e (event)
|
|
* @return n/a
|
|
*/
|
|
|
|
_update: function(){
|
|
|
|
// vars
|
|
var $submit = this.$side.find('.acf-gallery-update'),
|
|
$edit = this.$side.find('.acf-gallery-edit'),
|
|
$form = this.$side.find('.acf-gallery-side-data'),
|
|
id = $edit.data('id'),
|
|
data = acf.serialize_form( $form );
|
|
|
|
|
|
// validate
|
|
if( $submit.attr('disabled') ) return false;
|
|
|
|
|
|
// add attr
|
|
$submit.attr('disabled', 'disabled');
|
|
$submit.before('<i class="acf-loading"></i>');
|
|
|
|
|
|
// append AJAX action
|
|
data.action = 'acf/fields/gallery/update_attachment';
|
|
|
|
|
|
// prepare for ajax
|
|
acf.prepare_for_ajax(data);
|
|
|
|
|
|
// ajax
|
|
$.ajax({
|
|
url : acf.get('ajaxurl'),
|
|
data : data,
|
|
type : 'post',
|
|
dataType : 'json',
|
|
complete : function( json ){
|
|
|
|
$submit.removeAttr('disabled');
|
|
$submit.prev('.acf-loading').remove();
|
|
|
|
}
|
|
});
|
|
|
|
},
|
|
|
|
|
|
/*
|
|
* _remove
|
|
*
|
|
* event listener
|
|
*
|
|
* @type function
|
|
* @date 12/04/2016
|
|
* @since 5.3.8
|
|
*
|
|
* @param e (event)
|
|
* @return n/a
|
|
*/
|
|
|
|
_remove: function( e ){
|
|
|
|
// prevent event from triggering click on attachment
|
|
e.stopPropagation();
|
|
|
|
|
|
// vars
|
|
var id = e.$el.data('id');
|
|
|
|
|
|
// select
|
|
this.remove_attachment(id);
|
|
|
|
},
|
|
|
|
|
|
/*
|
|
* remove_attachment
|
|
*
|
|
* This function will remove an attachment
|
|
*
|
|
* @type function
|
|
* @date 20/04/2016
|
|
* @since 5.3.8
|
|
*
|
|
* @param $post_id (int)
|
|
* @return $post_id (int)
|
|
*/
|
|
|
|
remove_attachment: function( id ){
|
|
|
|
// close sidebar (if open)
|
|
this.close_sidebar();
|
|
|
|
|
|
// remove attachment
|
|
this.get_attachment(id).remove();
|
|
|
|
|
|
// render (update classes)
|
|
this.render();
|
|
|
|
|
|
// trigger change
|
|
this.$input.trigger('change');
|
|
|
|
},
|
|
|
|
|
|
/*
|
|
* _edit
|
|
*
|
|
* event listener
|
|
*
|
|
* @type function
|
|
* @date 12/04/2016
|
|
* @since 5.3.8
|
|
*
|
|
* @param e (event)
|
|
* @return n/a
|
|
*/
|
|
|
|
_edit:function( e ){
|
|
|
|
// vars
|
|
var id = e.$el.data('id');
|
|
|
|
|
|
// select
|
|
this.edit_attachment(id);
|
|
|
|
},
|
|
|
|
|
|
/*
|
|
* edit_attachment
|
|
*
|
|
* This function will create a WP popup to edit an attachment
|
|
*
|
|
* @type function
|
|
* @date 20/04/2016
|
|
* @since 5.3.8
|
|
*
|
|
* @param $post_id (int)
|
|
* @return $post_id (int)
|
|
*/
|
|
|
|
edit_attachment: function( id ){
|
|
|
|
// reference
|
|
var self = this,
|
|
$field = this.$field;
|
|
|
|
|
|
// popup
|
|
var frame = acf.media.popup({
|
|
mode: 'edit',
|
|
title: acf._e('image', 'edit'),
|
|
button: acf._e('image', 'update'),
|
|
attachment: id,
|
|
select: function( attachment ){
|
|
|
|
// render attachment
|
|
self.set('$field', $field).render_attachment( attachment );
|
|
|
|
|
|
// render sidebar
|
|
self.fetch( id );
|
|
|
|
}
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
render_collection: function( frame ){
|
|
|
|
var self = this;
|
|
|
|
|
|
// Note: Need to find a differen 'on' event. Now that attachments load custom fields, this function can't rely on a timeout. Instead, hook into a render function foreach item
|
|
|
|
// set timeout for 0, then it will always run last after the add event
|
|
setTimeout(function(){
|
|
|
|
|
|
// vars
|
|
var $content = frame.content.get().$el
|
|
collection = frame.content.get().collection || null;
|
|
|
|
|
|
|
|
if( collection ) {
|
|
|
|
var i = -1;
|
|
|
|
collection.each(function( item ){
|
|
|
|
i++;
|
|
|
|
var $li = $content.find('.attachments > .attachment:eq(' + i + ')');
|
|
|
|
|
|
// if image is already inside the gallery, disable it!
|
|
if( self.get_attachment(item.id).exists() ) {
|
|
|
|
item.off('selection:single');
|
|
$li.addClass('acf-selected');
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}, 10);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
/*
|
|
* acf_gallery_manager
|
|
*
|
|
* Priveds some global functionality for the gallery field
|
|
*
|
|
* @type function
|
|
* @date 25/11/2015
|
|
* @since 5.3.2
|
|
*
|
|
* @param n/a
|
|
* @return n/a
|
|
*/
|
|
|
|
var acf_gallery_manager = acf.model.extend({
|
|
|
|
actions: {
|
|
'validation_begin': 'validation_begin',
|
|
'validation_failure': 'validation_failure'
|
|
},
|
|
|
|
validation_begin: function(){
|
|
|
|
// lock all gallery forms
|
|
$('.acf-gallery-side-data').each(function(){
|
|
|
|
acf.disable_form( $(this), 'gallery' );
|
|
|
|
});
|
|
|
|
},
|
|
|
|
validation_failure: function(){
|
|
|
|
// lock all gallery forms
|
|
$('.acf-gallery-side-data').each(function(){
|
|
|
|
acf.enable_form( $(this), 'gallery' );
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
})(jQuery);
|
|
|
|
// @codekit-prepend "../js/acf-pro.js";
|
|
// @codekit-prepend "../js/acf-repeater.js";
|
|
// @codekit-prepend "../js/acf-flexible-content.js";
|
|
// @codekit-prepend "../js/acf-gallery.js";
|
|
|