我发现@scottfennell this post关于向WP Customizer添加可排序/可拖动的多重复选框控件。 他的帖子受到@JustinTadlock的previous work的启发,这是为多重复选框添加定制器控件。
我想在我的自定义程序中使用可排序/可拖动的多重复选框控件,但我在实现它时遇到了问题。非常欢迎您的帮助,非常感谢。我认为这个插件对其他人也有用,所以我希望这会遇到一些积极的兴趣。
编辑:查找以下示例代码
在我的主题中加入文件“customizer.php”并添加以下代码:
function customizer_setup( $wp_customize ) {
// Include the class
require_once( get_template_directory() . '/inc/functions/admin/myclass.php' );
// Add a section
$wp_customize->add_section( 'example_section', array(
'title' => __( 'Example Section', 'mytheme' ),
'priority' => 35,
) );
// Add settings
$wp_customize->add_setting(
'example_settings',
array(
'default' => array( 'apple', 'orange' )
)
);
// Add control
$wp_customize->add_control(
new LXB_AF_Checkbox(
$wp_customize,
'example_settings',
array(
'section' => 'example_section',
'label' => __( 'My new Control', 'mytheme' ),
'choices' => array(
'apple' => __( 'Apple', 'mytheme' ),
'banana' => __( 'Banana', 'mytheme' ),
'date' => __( 'Date', 'mytheme' ),
'orange' => __( 'Orange', 'mytheme' ),
'watermelon' => __( 'Watermelon', 'mytheme' )
)
)
)
);
}
add_action( 'customize_register', 'customizer_setup' );
在public $type = 'checkbox_group';
public function enqueue() {
wp_enqueue_script( 'customizer-drag-boxes-control', get_template_directory_uri() . '/inc/js/customizer-drag-boxes.js', array( 'jquery' ) );
}
我这样做是因为我认为jquery文件尚未入队。
我改变了myclass.php
$class = LXB_AF . '-checkbox_group-hidden';
到$class = 'LXB_AF' . '-checkbox_group-hidden';
。由于缺少''
,我这样做是因为错误。
自定义程序屏幕显示我的部分和测试字段,其中包含默认值。可拖动列表没有出现,我没有wordpress错误。在我的控制台中,我收到以下错误消息:
Uncaught SyntaxError:位于0的JSON中的意外标记u
- create @ customizer-drag-boxes.js?ver = 4.5.2:197
(匿名函数)@ customizer-drag-boxes.js?ver = 4.5.2:327
n.extend.each @ load-scripts.php?c = 0& load [] = jquery-core,jquery-migrate,jquery-ui-core,jquery-ui-widget,jquery-ui-莫...:2
n.fn.n.each @ load-scripts.php?c = 0& load [] = jquery-core,jquery-migrate,jquery-ui-core,jquery-ui-widget,jquery- UI谟...:2
$。fn.lxbAfCheckboxGroup @ customizer-drag-boxes.js?ver = 4.5.2:316
(匿名函数)@ customizer-drag-boxes.js?ver = 4.5.2:9
n.event.dispatch @ load-scripts.php?c = 0& load [] = jquery-core,jquery-migrate,jquery-ui-core,jquery-ui-widget,jquery-ui-莫...:3
- r.handle @ load-scripts.php?c = 0&amp; load [] = jquery-core,jquery-migrate,jquery-ui-core,jquery-ui-widget,jquery-ui-mo ...:3 < / LI>
你能帮我实施吗?你看到代码中有任何缺陷吗?提前致谢! :)
课程
class LXB_AF_Checkbox extends WP_Customize_Control {
// I'm not sure where this gets used but it's in the codex.
public $type = 'checkbox_group';
/**
* This method must be named, exactly, 'render_content', as that's
* expected by the WP core cusotmization class, which it extends. It
* outputs the HTML for our custom input.
*
* In this case, all it does is output a hidden input with some
* important data attributes. Our JS reads the data attributes and
* creates the markup. The reason for this is because the customizer
* only updates via JS, so we might as well create it via JS, since the
* logic for creating and updating is very similar.
*/
public function render_content() {
$out = '';
$class = LXB_AF . '-checkbox_group-hidden';
$class = " class='$class' ";
$id = esc_attr( $this -> id );
$name = " name='$id' ";
$label = esc_html( $this -> label );
$value = '';
if( isset( $this -> value ) ) {
$value = $this -> value;
}
// WP uses this to create the value of the input.
$link = 'data-customize-setting-link="' . $id . '"';
/**
* Store the choices for this setting in a data attr. In our JS,
* we'll use these to make the checkboxes.
*/
$choices = $this -> choices;
$choices_data = esc_attr( json_encode( $choices ) );
$choices_data = " data-choices='$choices_data' ";
// The type of input. Text for debugging purposes. Switch to hidden for production.
$type = " 'type='text' ";
$out .= "<span class='customize-control-title'>$label</span>";
$out .= "<input $choices_data $link $type $name $class>";
echo $out;
}
}
jQuery插件
/**
* A jQuery plugin for making a sortable/draggable multi-checkbox.
*/
jQuery( window ).load(function() {
// The li that wraps this whole section of the customizer. Sort of like a fieldset.
var el = jQuery( '.customize-control-checkbox_group' );
jQuery( el ).lxbAfCheckboxGroup();
});
(function ( $ ) {
$.fn.lxbAfCheckboxGroup = function( options ) {
/**
* Create an HTML <select> menu for choosing some value related to this checkbox.
*
* @param {string} type What type of options we want: linkCategories, customMenu, etc...
* @param {boolean} visible Should the menu be visible? If the checkbox is not checked, the select menu should not be visible.
* @param {string} hiddenValArr The JSON currently being stored for this fieldset.
* @return {string} The HTML for a <select> menu.
*/
function dropdown( type, visible, hiddenValArr ) {
// Create a select menu.
var select = jQuery( '<select>' ).addClass( 'lxbAfCheckboxGroup-select' ).attr( 'data-type', type );
// Maybe hide it.
if( ! visible ) {
jQuery( select ).hide();
}
// Start it with an empty option.
var emptyOpt = jQuery( '<option>' ).val( '' ).appendTo( select );
// Grab our php variables.
var localize = lxbAfCustomizeLocalize;
// Grab the current value for this menu.
var current = '';
if( hiddenValArr != null ) {
//Is the checkbox for this item checked?
if( hiddenValArr[ '###' + type + '###' ] != null ) {
// If so, determine which option is selected.
var current = hiddenValArr[ '###' + type + '###' ];
}
}
// Get a list of <option>'s for the <select>.
var choices = localize[type];
// For each <option>...
jQuery( choices ).each( function( index, value ) {
// The value.
var slug = value.slug;
// The label.
var name = value.name;
// Build the <option>.
var option = jQuery( '<option/>', {
html: name,
'value' : slug
});
// Maybe make it sticky.
if( slug == current ) {
jQuery( option ).attr( 'selected', 'selected' );
}
// Add it to the select menu.
jQuery( option ).appendTo( select );
});
var out = jQuery( select );
return out;
}
/**
* A function to make a draggable checkbox input.
*
* @param {string} key The name of the option controlled by this checkbox.
* @param {string} hiddenValArr The JSON currently being stored in this fieldset.
* @param {string} fieldsetID The HTML ID for this fieldset.
* @param {boolean} checked Whether or not this checkbox hould be checked.
* @return {string} The HTML for a draggable checkbox input.
*/
function checkboxListItem( key, hiddenValArr, fieldsetID, checked ) {
var out = '';
// If the key is empty, skip it.
if( key === '' ) { return out; }
// If we are doing an empty checkbox, make sure it's not already on the list.
if( ! checked ) {
// If there is actually some value in the hidden input...
if( hiddenValArr !== null ) {
// If the checkbox for this item is already checked, skip it.
if( hiddenValArr[key] == true ) {
return out;
// Else, if it's a non empty string, skip it.
} else if( ( typeof hiddenValArr[key] == 'string' ) && hiddenValArr[key] != '' ){
return out;
}
}
}
// This might end up holding an HTML <select> menu.
var select = '';
// The might hold the current value of the select menu.
var selected = false;
// Does this key contain a magic hash code?
if( key.indexOf( '###' ) != -1 ) {
// If so, remove the magic hash codes in order to arrive at what type of <select> it is.
var type = key.replace( new RegExp( '#', 'g' ), '' );
// Grab the select menu. We'll append it later.
select = dropdown( type, checked, hiddenValArr );
// Grab the current value of the select menu.
selected = jQuery( select ).val();
}
// Create the checkbox.
var input = jQuery( '<input/>', {
'id' : fieldsetID + key,
'name' : key,
'type' : 'checkbox',
'value' : key
});
// If the checkbox is checked and has a select menu, record the value of the select menu in a data attribute.
if( checked && selected ) {
jQuery( input ).attr( 'data-which', selected );
}
// Wrap a label around the input.
var label = jQuery( '<label/>', {
html : key,
'for' : fieldsetID + key
});
jQuery( input ).prependTo( label );
// Make a list item to wrap the whole darn thing.
var out = jQuery( '<li/>' );
// Add the label to the list item.
jQuery( label ).appendTo( out );
// Add the select menu to the list item.
jQuery( select ).appendTo( out );
return out;
}
/**
* Create the list of checkboxes.
*
* @param {string} fieldsetID The ID for this fieldset.
* @param {object} hidden The input that stores the value of the checkboxes.
*/
function create( fieldsetID, hidden ) {
// The JSON string in the hidden value.
var hiddenVal = hidden.val();
// Grab the hidden value as an object.
if( typeof hiddenVal !== 'object' ) {
var hiddenValArr = jQuery.parseJSON( hiddenVal );
} else {
var hiddenValArr = hiddenVal;
}
/**
* The availabe options for this fieldset, stored in the DOM as a
* data attribute on the input that stores the JSON.
*/
var choices = hidden.data( 'choices' );
choices = JSON.stringify( choices );
var choicesArr = JSON.parse( choices );
// Start a list to hold the checkboxes, which we'll draw shortly.
var sortable = jQuery( '<ul>' ).addClass( 'ui-sortable' ).insertBefore( hidden );
// Make the checkboxes sortable.
jQuery( sortable ).sortable({
// Once an item is dragged and sorted, update the preview and save the JSON.
stop: function( event, ui ) {
update( hidden );
}
});
// Loop through the current values and output checked checkboxes.
if( ! jQuery.isEmptyObject( hiddenValArr ) ) {
// For each of the current values...
jQuery.each( hiddenValArr, function( key, value ) {
// Draw a checkbox with the dropdown menu visible.
var listItem = checkboxListItem( key, hiddenValArr, fieldsetID, true );
// Add it to the DOM and check the box.
jQuery( listItem ).appendTo( sortable ).find( 'input' ).prop( 'checked', true );
});
}
// For all the available choices on this fieldset...
jQuery.each( choicesArr, function( key, value ) {
// Draw a checkbox with the dropdown menu hidden.
var listItem = checkboxListItem( key, hiddenValArr, fieldsetID, false );
// Add it to the DOM.
jQuery( listItem ).appendTo( sortable ).find( 'input' );
});
}
/**
* Update the value for this fieldset, perhaps when a checkbox is checked or sorted.
*
* @param {object} hidden The hidden form field that stores the values for this fieldset.
*/
function update( hidden ) {
var out = {};
// Grab the name of the hidden field.
var hiddenName = jQuery( hidden ).attr( 'name' );
// Grab all the checkboxes in this fieldset.
var checkboxes = jQuery( hidden ).closest( 'li' ).find( '[type="checkbox"]:checked' );
// Grab all the select menus in this fieldset.
var selects = jQuery( hidden ).closest( 'li' ).find( 'select' );
// For each checkbox...
jQuery( checkboxes ).each( function( index, value ) {
// Grab the value.
var val = jQuery( value ).val();
// Let's see if this checkbox carries a select menu as well.
var which = jQuery( value ).attr( 'data-which' );
// If it has a select menu, that acts as the value for the checkbox.
if( typeof which != 'undefined' ) {
out[val] = which;
// If not, the checkbox is just boolean true.
} else {
out[val] = true;
}
});
// Turn the output into JSON.
var outStr = JSON.stringify( out );
var outJSON = JSON.parse( outStr );
// Update the hidden field.
jQuery( hidden ).val( outStr );
// Grab the core WP customization object and update it.
var api = wp.customize;
api.instance( hiddenName ).set( outStr );
// Show or hide the select menus based on whether the parent menu item is checked.
jQuery( selects ).each( function( index, value ) {
// Find out if the checkbox is checked. If so, reveal the select menu.
var checkbox = jQuery( value ).closest( 'li' ).find( '[type="checkbox"]' );
if( jQuery( checkbox ).is( ':checked' ) ) {
jQuery( value ).slideDown();
// Else, hide the select menu.
} else {
jQuery( value ).slideUp();
}
});
}
/**
* The main part of the jQuery plugin that actually returns the selected items.
*
* @return {object} The items that this plugin applies to.
*/
return this.each(function() {
var that = this;
// The ID for this section of the customizer.
var fieldsetID = jQuery( that ).attr( 'id' );
// The input that stores JSON as the checkboxes toggle and move.
var hidden = jQuery( that ).find( '[type="text"]' );
// Okay! Create the list of checkboxes!
create( fieldsetID, hidden );
// Whenever the checkboxes are checked, update the json and redraw the preview.
jQuery( that ).on( 'change', '[type="checkbox"]', function( event ) {
update( hidden );
});
/**
* Whenever the dropdowns are selected, trigger a change on the
* corresponding checkbox.
*/
jQuery( that ).on( 'change', 'select', function( event ) {
/**
* What type of dropdown is this? Maybe to get links by category, or get a custom menu?
*/
var type = jQuery( this ).attr( 'data-type' );
// Find the corresponding checkbox.
var checkbox = jQuery( this ).closest( 'li' ).find( '[type="checkbox"]:checked' );
// Find out which <option> is selected.
var selected = jQuery( this ).val();
// Trigger a change on that checkbox.
jQuery( checkbox ).attr( 'data-which', selected ).trigger( 'change' );
});
return that;
});
}
}( jQuery ));