Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I'm working on a metabox helper class and everything works well, but the radio image field. The images show up, but they aren't clickable.

        // Print radio_image input.
    private function radio_image_input( $field ) {

        $selected_value = $field['value'];

        $radio_image_field = '';
        $radio_image_field .='
                <style>
                    .optionimg{border:3px solid #cecece; margin-right:4px;cursor:pointer;}
                    .optionimg.optselected{border-color:#ababab;}
                    .form-table td em{font-style:normal;color:#999999;font-size:12px;}
                </style>
                <script>
                jQuery(document).ready(function(){
                    jQuery( \'.optionimg\').click(function(){
                        jQuery(this).parent().find( \'.optionimg\').removeClass( \'optselected\' );
                        jQuery(this).addClass( \'optselected\' );
                    });
                });
                </script>
            ';
        if ( ! empty( $field['choices'] ) ) {
            foreach ( (array) $field['choices'] as $value => $label )
                $radio_image_field .= sprintf(
                    '<img src="'.$label.'" class="optionimg '.$selected_value.'" onclick="document.getElementById(\''.$field['id'].$choices.'\').checked=true" style="display:inline-block;" /><input type="radio" name="%s" id="%s" value="%s" style="display:none;"/>',
                    esc_attr( $field['id'] ),
                    esc_attr( $value ),
                    esc_attr( $value ),
                    esc_html( $label )
                );
        }

        return $radio_image_field;
    }

I think the problem is the JS, but I couldn't figure out why/where.

The full class is here:

if ( ! class_exists( 'TheUx_Metabox_API' ) ) {

    class TheUx_Metabox_API {

        // Holds options for menu page.
        var $options = array();

        // Holds settings fields data.
        var $fields = array();

        // Supported input field types to white label while saving.
        var $supported_fields = array();

        // Holds current folder path.
        var $dir_path;

        // Holds current folder URI.
        var $dir_uri;


        function __construct( $options = array(), $fields = array() ) {

            // Set directory path.
            $this->dir_path = str_replace( '\\', '/', dirname( __FILE__ ) );

            // Set directory uri.
            $this->dir_uri  = trailingslashit( home_url() ) . str_replace( str_replace( '\\', '/', ABSPATH ), '', $this->dir_path );

            // Default page options.
            $options_default = array(
                'metabox_id'    => '',
                'metabox_title' => '',
                'post_type'     => '',
                'context'       => 'normal',
                'priority'      => 'high',
            );

            $this->options = wp_parse_args( $options, $options_default );
            extract( $this->options );

            // Titles and slugs should not be empty.
            if ( empty( $metabox_id ) || empty( $metabox_title ) || empty( $post_type ) )
                return false;

            // Set input fields.
            $this->fields = (array) $fields;

            // Default field options.
            $field_default = array(
                'title'    => '',
                'type'     => '',
                'desc'     => '',
                'choices'  => array(),
                'multiple' => false,
                'sanit'    => '',
            );

            // To eliminate PHP warning we need to set default empty values.
            foreach ( $this->fields as $key => $field )
                $this->fields[ $key ] = wp_parse_args( $field, $field_default );

            // Set list of input field types. We are white labeling these field types while saving meta.
            $this->supported_fields = (array) apply_filters( 'theux_metabox_api_supported_fields', array( 
                'text', 
                'textarea', 
                'radio', 
                'radio_image', 
                'checkbox', 
                'select', 
                'multicheck', 
                'upload', 
                'color', 
                'editor' 
            ));

            add_action( 'add_meta_boxes', array( $this, 'register_metabox' ) );
            add_action( 'save_post', array( $this, 'save_metabox' ), 10, 2 );

            add_action( 'admin_head', array( $this, 'color_picker_js' ) );
            add_action( 'admin_head', array( $this, 'upload_js' ) );
        } // end of __construct


        /**
         * HTML helper functions. 
         * A simple HTML helper functions to generate the form fields.
         */

        // Print Help/descripting for field.
        private function help_text( $field ) {
            if ( empty( $field['desc'] ) )
                return '';

            return '<p class="description">' . wp_kses_data( $field['desc'] ) . '</p>';
        }

        // Returns the form table html.
        public function get_form_table( $fields, $show_help = true ) {

            $form_table = '';
            $form_table .= '<table class="form-table">';

            foreach ( (array) $fields as $field )
                $form_table .= $this->get_table_row( $field, $show_help );

            $form_table .= '</table>';

            return apply_filters( 'theux_metabox_api_form_table', $form_table, $fields, $show_help );
        }

        // Echo/display the HTML form table.
        public function display_form_table( $fields, $show_help = true ) {

            echo $this->get_form_table( $fields, $show_help );
        }


        // Returns the table row html.
        public function get_table_row( $field, $show_help ) {

            $table_row = '<tr valign="top">';
                $table_row .= sprintf( '<th><label for="%s">%s</label></th>', esc_attr( $field['id'] ), $field['title'] );
                $table_row .= sprintf( '<td>%s</td>', $this->get_field( $field, $show_help ) );
            $table_row .= '</tr>';

            return apply_filters( 'theux_metabox_api_table_row', $table_row, $field, $show_help );
        }


        // Returns a input field based on field options.
        public function get_field( $field, $show_help = true ) {

            $field_default = array(
                'title'    => '',
                'id'       => '',
                'type'     => '',
                'default'  => '',
                'choices'  => array(),
                'value'    => '',
                'desc'     => '',
                'sanit'    => '',
                'multiple' => false, // for multiselect fiield
            );

            $field = wp_parse_args( $field, $field_default );
            $input_html = '';

            switch ( $field['type'] ) {
                case 'text'       : $input_html .= $this->text_input( $field ); break;
                case 'textarea'   : $input_html .= $this->textarea_input( $field ); break;
                case 'select'     : $input_html .= $this->select_input( $field ); break;
                case 'radio'      : $input_html .= $this->radio_input( $field ); break;
                case 'radio_image': $input_html .= $this->radio_image_input( $field ); break;
                case 'checkbox'   : $input_html .= $this->checkbox_input( $field ); break;
                case 'multicheck' : $input_html .= $this->multicheck_input( $field ); break;
                case 'upload'     : $input_html .= $this->upload_input( $field ); break;
                case 'color'      : $input_html .= $this->color_input( $field ); break;
                case 'editor'     : $input_html .= $this->editor_input( $field ); break;
            }

            if ( $show_help && 'checkbox' !== $field['type'] )
                $input_html .= $this->help_text( $field );

            return apply_filters( 'theux_metabox_api_input_field', $input_html, $field, $show_help );
        }

        // Displays a input field based field options
        public function display_field( $field, $show_help = true ) {
            echo $this->get_field( $field, $show_help );
        }


        // Print text input.
        private function text_input( $field ) {
            return sprintf(
                '<input type="text" name="%s" id="%s" value="%s" class="regular-text"/>',
                esc_attr( $field['id'] ),
                esc_attr( $field['id'] ),
                esc_attr( $field['value'] )
            );
        }

        // Print textarea input.
        private function textarea_input( $field ) {
            return sprintf(
                '<textarea name="%s" id="%s" rows="5" cols="40">%s</textarea>',
                esc_attr( $field['id'] ),
                esc_attr( $field['id'] ),
                esc_textarea( $field['value'] )
            );
        }

        // Print select input.
        private function select_input( $field ) {
            $selected_value = $field['value'];
            $multiple = ( true == $field['multiple'] || 'true' == $field['multiple'] ) ? true : false ;

            if ( $multiple )
                $field['id'] = $field['id'] . '[]';

            $select_field = sprintf(
                '<select name="%s" id="%s"%s>',
                esc_attr( $field['id'] ),
                esc_attr( $field['id'] ),
                ( $multiple ? ' multiple' : '' )
            );

            if ( ! empty( $field['choices'] ) ) {
                foreach ( (array) $field['choices'] as $value => $label ) {
                    $selected = $multiple ? selected( in_array( $value, (array) $selected_value ), true, false ) : selected( $selected_value, $value, false );
                    $select_field .= sprintf(
                        '<option value="%s"%s>%s</option>',
                        esc_attr( $value ),
                        $selected,
                        esc_html( $label )
                    );
                }
            }

            $select_field .= '</select>';
            return $select_field;
        }

        // Print checkbox input.
        private function checkbox_input( $field ) {
            return sprintf(
                '<label><input type="checkbox" name="%s" id="%s"%s> %s</label>',
                esc_attr( $field['id'] ),
                esc_attr( $field['id'] ),
                checked( $field['value'], 'on', false ),
                __( $field['desc'] )
            );
        }

        // Print radio input.
        private function radio_input( $field ) {
            $selected_value = $field['value'];
            $radio_field = '';

            if ( ! empty( $field['choices'] ) ) {
                foreach ( (array) $field['choices'] as $value => $label )
                    $radio_field .= sprintf(
                        '<label><input type="radio" name="%s" id="" value="%s"%s> %s</label><br/>',
                        esc_attr( $field['id'] ),
                        esc_attr( $value ),
                        checked( $selected_value, $value, false ),
                        esc_html( $label )
                    );
            }

            return $radio_field;
        }

        // Print radio_image input.
        private function radio_image_input( $field ) {

            $selected_value = $field['value'];

            $radio_image_field = '';
            $radio_image_field .='
                    <style>
                        .optionimg{border:3px solid #cecece; margin-right:4px;cursor:pointer;}
                        .optionimg.optselected{border-color:#ababab;}
                        .form-table td em{font-style:normal;color:#999999;font-size:12px;}
                    </style>
                    <script>
                    jQuery(document).ready(function(){
                        jQuery( \'.optionimg\').click(function(){
                            jQuery(this).parent().find( \'.optionimg\').removeClass( \'optselected\' );
                            jQuery(this).addClass( \'optselected\' );
                        });
                    });
                    </script>
                ';
            if ( ! empty( $field['choices'] ) ) {
                foreach ( (array) $field['choices'] as $value => $label )
                    $radio_image_field .= sprintf(
                        '<img src="'.$label.'" class="optionimg '.$selected_value.'" onclick="document.getElementById(\''.$field['id'].$choices.'\').checked=true" style="display:inline-block;" /><input type="radio" name="%s" id="%s" value="%s" style="display:none;"/>',
                        esc_attr( $field['id'] ),
                        esc_attr( $value ),
                        esc_attr( $value ),
                        esc_html( $label )
                    );
            }

            return $radio_image_field;
        }


        // Print multi-checkbox input.
        private function multicheck_input( $field ) {
            $selected_value = (array) $field['value'];
            $multicheck_field = '';

            if ( ! empty( $field['choices'] ) ) {
                foreach ( (array) $field['choices'] as $value => $label )
                    $multicheck_field .= sprintf(
                        '<label><input type="checkbox" name="%s[]" id="" value="%s"%s> %s</label><br/>',
                        esc_attr( $field['id'] ),
                        esc_attr( $value ),
                        checked( in_array( $value, $selected_value ), true, false ),
                        esc_html( $label )
                    );
            }

            return $multicheck_field;
        }

        // Print upload input.
        private function upload_input( $field ) {

            // We require to enqueue media uploader scripts and styles.
            wp_enqueue_media();

            return sprintf(
                '<input type="text" name="%s" id="%s" value="%s" class="regular-text hd-upload-input"/>' .
                '<input type="button" value="%s" class="hd-upload-button button button-secondary" id="hd_upload_%s"/>',
                esc_attr( $field['id'] ),
                esc_attr( $field['id'] ),
                esc_attr( $field['value'] ),
                __( 'Upload', 'theux' ),
                esc_attr( $field['id'] )
            );
        }

        // Print color picker input.
        private function color_input( $field ) {

            // We require to enqueue color picker scripts and styles.
            wp_enqueue_style( 'wp-color-picker' );
            wp_enqueue_script( 'wp-color-picker' );

            $default_color = empty( $field['default'] ) ? '' : ' data-default-color="' . esc_attr( $field['default'] ) . '"';

            return sprintf(
                '<input type="text" name="%s" id="%s" value="%s" class="hd-color-picker"%s/>',
                esc_attr( $field['id'] ),
                esc_attr( $field['id'] ),
                esc_attr( $field['value'] ),
                $default_color
            );
        }

        // Print tinymce editor input.
        private function editor_input( $field ) {
            $settings = array(
                'media_buttons' => false,
                'textarea_rows' => 5,
                'textarea_cols' => 45,
            );

            $content = $field['value'];
            $content = empty( $content ) ? '' : $content;

            ob_start();
            wp_editor( $content, $field['id'], $settings );
            return ob_get_clean();
        }



        /**
         * Main functions. 
         * The follow functions will register, print, save and sanitise the metabox.
         */

        // Register metabox.
        function register_metabox() {

            extract( $this->options );
            foreach ( (array) $post_type as $type )
                if ( post_type_exists( $type ) )
                    add_meta_box( $metabox_id, esc_html( $metabox_title ), array( $this, 'display_metabox' ), $type, $context, $priority );
        }

        // Print metabox content.
        function display_metabox( $post ) {

            foreach ( (array) $this->fields as $meta_key => $meta_field ) {
                $this->fields[ $meta_key ]['id'] = $meta_key;
                $this->fields[ $meta_key ]['value'] = get_post_meta( $post->ID, $meta_key, true );
            }

            wp_nonce_field( $this->options['metabox_id'] . '_' . $post->ID, $this->options['metabox_id'] . '_' . $post->ID . '_nonce' );
            do_action( 'theux_metabox_api_metabox_before', $this->options, $this->fields );

            echo '<div class="hd-metabox-inner ' . sanitize_html_class( $this->options['metabox_id'] ) . '">';
                $this->display_form_table( $this->fields, true );
            echo '</div>';

            do_action( 'theux_metabox_api_metabox_after', $this->options, $this->fields );
        }

        // Save metabox.
        function save_metabox( $post_id, $post ) {

            extract( $this->options );

            if ( ! isset( $_POST[ $metabox_id . '_' . $post_id . '_nonce' ] ) || ! wp_verify_nonce( $_POST[ $metabox_id . '_' . $post_id . '_nonce' ], $metabox_id . '_' . $post_id ) )
                return $post_id;

            if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
                return $post_id;

            $post_type = get_post_type_object( $post->post_type );

            if ( ! current_user_can( $post_type->cap->edit_post, $post_id ) )
                return $post_id;

            foreach ( (array) $this->fields as $meta_key => $meta_field ) {

                $meta_field['id'] = $meta_key;

                // White label field types
                if ( ! in_array( $meta_field['type'], $this->supported_fields ) )
                    continue;

                $post_value = isset( $_POST[ $meta_key ] ) ? $_POST[ $meta_key ] : '';
                $new_value = $this->sanitize_value( $post_value, $meta_field );
                $old_value = get_post_meta( $post_id, $meta_key, true );

                if ( ( $new_value || 0 == $new_value ) && $new_value != $old_value )
                    update_post_meta( $post_id, $meta_key, $new_value, $old_value );
                elseif ( '' == $new_value && $old_value )
                    delete_post_meta( $post_id, $meta_key, $new_value );
            }

            do_action( 'theux_metabox_api_save_metabox', $post_id, $post );
        }

        // Sanitize metabox value.
        function sanitize_value( $new_value, $field ) {

            if ( ! isset( $field['sanit'] ) )
                $field['sanit'] = '';

            switch ( $field['sanit'] ) {

                case 'int' :
                    return is_array( $new_value ) ? array_map( 'intval', $new_value ) : intval( $new_value );
                    break;

                case 'absint' :
                    return is_array( $new_value ) ? array_map( 'absint', $new_value ) : absint( $new_value );
                    break;

                case 'email' :
                    return is_array( $new_value ) ? array_map( 'sanitize_email', $new_value ) : sanitize_email( $new_value );
                    break;

                case 'url' :
                    return is_array( $new_value ) ? array_map( 'esc_url_raw', $new_value ) : esc_url_raw( $new_value );
                    break;

                case 'bool' :
                    return (bool) $new_value;
                    break;

                case 'color' :
                    return $this->sanitize_hex_color( $new_value );
                    break;

                case 'html' :
                    if ( current_user_can( 'unfiltered_html' ) )
                        return is_array( $new_value ) ? array_map( 'wp_kses_post', $new_value ) : wp_kses_post( $new_value );
                    else
                        return is_array( $new_value ) ? array_map( 'wp_strip_all_tags', $new_value ) : wp_strip_all_tags( $new_value );
                    break;

                case 'nohtml' :
                    return is_array( $new_value ) ? array_map( 'wp_strip_all_tags', $new_value ) : wp_strip_all_tags( $new_value );
                    break;

                default :
                    return apply_filters( 'theux_metabox_api_sanitize_option', $new_value, $field, $setting );
                    break;
            }
        }

        // Sanitize hex color (taken from WP core).
        function sanitize_hex_color( $color ) {

            if ( '' === $color )
                return '';

            if ( preg_match('|^#([A-Fa-f0-9]{3}){1,2}$|', $color ) )
                return $color;

            return null;
        }


        /**
         * Enqueue helper functions. 
         * These functions will load the necessary javascript code.
         */

        // Color picker.
        public function color_picker_js() {

            echo '<script>';
            echo 'jQuery(document).ready(function($){';
            echo '$(".hd-color-picker").wpColorPicker();';
            echo '});';
            echo '</script>';

        } // End of function color_picker_js()

        // Upload image.
        public function upload_js() {
            echo '<script>';
            echo 'jQuery(document).ready(function($){';
            echo '$("body").on("click", ".hd-upload-button", function(e) {';
            echo 'e.preventDefault();';
            echo 'var upload_input = $(this).siblings(".hd-upload-input"),';
            echo 'hd_uploader;';
            echo 'if (hd_uploader) {';
            echo 'hd_uploader.open();';
            echo 'return;';
            echo '}';
            echo 'hd_uploader = wp.media.frames.file_frame = wp.media({';
            echo 'title: "Upload Media",';
            echo 'button: {';
            echo 'text: "Select",';
            echo '},';
            echo 'multiple: false';
            echo '});';
            echo 'hd_uploader.on("select", function() {';
            echo 'var media_file = hd_uploader.state().get("selection").first().toJSON();';
            echo 'upload_input.val(media_file.url);';
            echo '});';
            echo 'hd_uploader.open();';
            echo '});';
            echo '});';
            echo '</script>';
        } // End of function upload_js()


    } // TheUx_Metabox_API end
}; // class_exists check

A example how to use:

$layoutimg = array(
    'default'       => get_template_directory_uri() . '/assets/images/'.'mb-default.png',
    'one-col'       => get_template_directory_uri() . '/assets/images/'.'mb-1c.png',
    'two-col-left'  => get_template_directory_uri() . '/assets/images/'.'mb-2cl.png',
    'two-col-right' => get_template_directory_uri() . '/assets/images/'.'mb-2cr.png'
);

// ========
// = Post =
// ========

$example_options_post = array(
    'metabox_title' =>  __('Layout Options','domain'),// Metabox Title
    'metabox_id'    => 'post_metabox',   // Unique metabox id. it is alphanumeric and does not contains spaces.
    'post_type'     => 'post',       // Post Type : you can also define as array. array( 'post', 'page' )
    'context'       => 'normal',                    // Metabox Context. Should be any of these 'normal', 'advanced' or 'side'
    'priority'      => 'high',                      // Metabox Priority. Should be any of these 'high', 'core', 'default' or 'low',
);

$example_fields_post = array(
    'hd_radio_meta' => array(
        'title'   => __('Layout','domain'),
        'type'    => 'radio_image',
        'choices' => $layoutimg,
        'desc'    => '<em>'.__('Select the layout you want on this specific page.','domain').'</em>',
        'sanit'   => 'nohtml',
    )   
);

$example_metabox_post = new TheUx_Metabox_API( $example_options_post, $example_fields_post );
share|improve this question
add comment

1 Answer 1

The problem seems on the line no 279 of metabox class api definition, below is your code:

'<img src="'.$label.'" class="optionimg '.$selected_value.'" onclick="document.getElementById(\
''.$field['id'].$choices.'\').checked=true" style="display:inline-block;" /><input type="radio" 
name="%s" id="%s" value="%s" style="display:none;"/>',

$choices is not defined variable in the scope (error thrown by WAMP), I think you should replace $field['id'].$choices with $value as in below code:

'<img src="'.$label.'" class="optionimg '.$selected_value.'" onclick="document.getElementById(\
''.$value.'\').checked=true" style="display:inline-block;" /><input type="radio"
name="%s" id="%s" value="%s" style="display:none;"/>',

Hope it helps.

share|improve this answer
    
Unfortunately is not that. –  Daniel Apr 29 at 13:16
    
ok, but I actually tried your code with Testing Environment of WordPress in local, there does not seem any other problem. –  Dharmang Apr 30 at 6:30
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.