简体   繁体   中英

How to add wp_editor in custom widget

I an trying to create a image widget with wp editor. I see the editor but i cant the text like make it bold or bigger nither i see the tab switch from visual to text. Following is my code: Thanks in advance.

<input type="hidden" id="<?php echo esc_attr($this->get_field_id('description')); ?>" name="<?php echo esc_attr($this->get_field_name('description')); ?>" value="<?php echo esc_attr($instance['description']); ?>" />
        <?php  
            $edi_name =  esc_attr($this->get_field_name('description'));
            $content = $instance['description'];
            $editor_id_new = esc_attr($this->get_field_id('description'));
            $settings = array( 'media_buttons' => false,
              'textarea_rows' => 6,
              'textarea_name' => $edi_name,
              'teeny'         => false, 
              'menubar'     => false,
              'default_editor'   => 'tinymce',
              'quicktags' => false
              );  
            wp_editor( $content, $editor_id_new, $settings );
        ?>
        <script>
        (function($){
            tinyMCE.execCommand('mceAddEditor', false, '<?php echo $this->get_field_id('description'); ?>');
        })(jQuery);
        </script>

Short answer: Because there is a hidden widget where the TinyMCE appears first.

Long answer (sorry, a very long answer):

Go to the Codex and copy the example widget Foo_Widget to make sure we are talking about the same code. Now open your IDE (not an editor) and write a short testing widget as plugin. Starting with a minimal plugin header...

<?php
/*
Plugin Name: Widget Test Plugin
Description: Testing plugincode
*/

... adding the widget code from the codex and registering the widget with the add_action() call. Now modify the form method within the widget class as shown here:

public function form( $instance ) {
    if ( isset( $instance[ 'title' ] ) ) {
        $title = $instance[ 'title' ];
    }
    else {
        $title = __( 'New title', 'text_domain' );
    }
    ?>
    <p>
    <label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e( 'Title:' ); ?></label>
    <input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>" />
    </p>
    <?php

/*** add this code ***/
    $content   = 'Hello World!';
    $editor_id = 'widget_editor';

    $settings = array(
        'media_buttons' => false,
        'textarea_rows' => 3,
        'teeny'         => true,
    );

    wp_editor( $content, $editor_id, $settings );
/*** end editing ***/
}

Go to your blog, activate the plugin, go to the widget page and drag the Foo Widget into a sidebar. You will see it will fail.

Do you see the Foo Widget description on the left side? Do a right click on the description and choose 'Inspect' from your developer tools (you have some developer tools like FireBug or Chrome DevTools, huh? In FireFox you can also choose the build in 'Inspect Element'). Browse through the HTML code and you will see there is an editor wrap inside the 'hidden' widget. 隐藏小部件中的wp_editor

You can see one editor in the sidebar on the right and there is an editor in the 'hidden' widget on the left. This cannot work properly because TinyMCE don't know which editor should be used.

What do we need?

We need a unique ID for our editor.

/*** add this code ***/
    $rand    = rand( 0, 999 );
    $ed_id   = $this->get_field_id( 'wp_editor_' . $rand );
    $ed_name = $this->get_field_name( 'wp_editor_' . $rand );

    $content   = 'Hello World!';
    $editor_id = $ed_id;

      $settings = array(
      'media_buttons' => false,
      'textarea_rows' => 3,
      'textarea_name' => $ed_name,
      'teeny'         => true,
    );

    wp_editor( $content, $editor_id, $settings );
/*** end edit ***/

Modify the code within the form method again with the code above. We create a unique number with rand() and append this number to the id and name attributes. But stop, what about saving the values???

Go to the update method and add die(var_dump($new_instance)); in the first line. If you press Save on the widget, the script will die and print out the submitted values. You will see there is a value like wp_editor_528 . If you reload the page and save the widget again, the number will be changed to something else because it is a random number.

How will I know which random number was set in the widget? Simply send the random number with the widget data. Add this to the form method

printf(
  '<input type="hidden" id="%s" name="%s" value="%d" />',
  $this->get_field_id( 'the_random_number' ),
  $this->get_field_name( 'the_random_number' ),
  $rand
);

In the update routine, we can now access the random number with $new_instance['the_random_number']; and so we can access the editor content with

$rand = (int) $new_instance['the_random_number'];
$editor_content = $new_instance[ 'wp_editor_' . $rand ];
die(var_dump($editor_content));

As you can see, the editor content will be submitted and you can save it or do anything else with it.

Caveat

The editor content is only submitted correctly if the TinyMCE is not in visual mode (WYSIWYG mode). You have to switch to the text mode befor press 'Save'. Otherwise the predefined content (in this case $content = 'Hello World!'; ) is submitted. I don't now why, but there is a simple workaround for this.

Write a small jQuery script that triggers the click on the 'text' tab before saving the widget content.

JavaScript (saved as widget_script.js somewhere in your theme/plugin folders):

jQuery(document).ready(
    function($) {
        $( '.widget-control-save' ).click(
            function() {
                // grab the ID of the save button
                var saveID   = $( this ).attr( 'id' );

                // grab the 'global' ID
                var ID       = saveID.replace( /-savewidget/, '' );

                // create the ID for the random-number-input with global ID and input-ID
                var numberID = ID + '-the_random_number';

                // grab the value from input field
                var randNum  = $( '#'+numberID ).val();

                // create the ID for the text tab
                var textTab  = ID + '-wp_editor_' + randNum + '-html';

                // trigger a click
                $( '#'+textTab ).trigger( 'click' );

            }
        );
    }
);

And enqueue it

function widget_script(){

    global $pagenow;

    if ( 'widgets.php' === $pagenow )
        wp_enqueue_script( 'widget-script', plugins_url( 'widget_script.js', __FILE__ ), array( 'jquery' ), false, true );

}

add_action( 'admin_init', 'widget_script' );

That's it. Easy, isn't it? ;)

Actual Credit Goes To The Author Of Writting This Test Plugin @Ralf912

Reference URL : Why Can't wp_editor Be Used in a Custom Widget?

I made some improvements to this code in case somebody needs it:

on the form function of the widget I updated the code:

$rand = !empty( $instance['the_random_number']) ? $instance['the_random_number'] : rand( 0, 999 );

        $ed_id   = $this->get_field_id( 'wp_editor_' . $rand );
        $ed_name = $this->get_field_name( 'wp_editor_' . $rand );

        $content   = !empty( $instance['the_random_number']) ? $instance['wp_editor_' . $rand] : 'Content goes here!';          
        $editor_id = $ed_id;

        $settings = array(
        'media_buttons' => true,
        'textarea_rows' => 3,
        'textarea_name' => $ed_name,
        'teeny'         => true,
        );

        wp_editor( $content, $editor_id, $settings ); `

And I also reinitialized the editor because it was broken after save

jQuery(document).on('widget-updated', function(e, widget){
if(widget[0].id.includes("cw_pa_text_widget")) { // if it is the right widget
    let editor ="widget-" + widget[0].id.substring(widget[0].id.indexOf('_') + 1);
    let randNum = editor + "-the_random_number";
    let wpEditorId = editor + "-wp_editor_" + document.getElementById(randNum).value;

    var settings = {
        quicktags: true,
    };
    wp.editor.initialize(wpEditorId, settings);

    //create the ID for the text tab
    var textTab  = wpEditorId + '-tmce';

    // trigger a click
    document.getElementById(textTab).click();
}}); 

Thank you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM