在Widget中可以使用动态表单/条目吗?

时间:2017-02-21 作者:Sengngy Kouch

我是WordPress插件开发的新手,我刚刚开始使用这个小部件。我的问题是:WordPress小部件的局限性是什么?

我试图使用jQuery使小部件表单更具交互性/动态性,但它似乎根本不起作用。例如,我有一个按钮,单击该按钮时会添加一个字符串“Hello!”到id为“here”的div。

<div id="here"></div> 
<input type="button" id="add" value="Click Me!" " />

<script>

    jQuery(document).ready(function(){ 
             //call when the button is click
             $(document).on(\'click\', \'#add\', function() {
                  $(\'#here\').append(\'<p>Hello</p>\');
             });
        });


</script>
为什么表格上没有显示“Hello”一段?是因为widget表单阻止它这样做吗?

我也听说了脊骨。js刷新前端,但我不确定这是否有效。

如果可能,请解释整个wordpress小部件类是如何工作的。提前感谢您!

Update: I already tried what are suggested, but it still doesn\'t work. Here are my code.

repeat.php

     <?php
    /**
     * Plugin Name: Repeat Field
     *
     */



     class repeat_field_widget extends WP_Widget {

        /**
         * Sets up the widgets name etc
         */
        public function __construct() {
            $widget_ops = array(
                \'classname\' => \'repeat_field_widget\',
                \'description\' => \'Repeat Field for Name input\',
            );
            parent::__construct( \'repeat_field_widget\', \'Repeat Field\', $widget_ops );
        }

        /**
         * Outputs the content of the widget
         *
         * @param array $args
         * @param array $instance
         */
        public function widget( $args, $instance ) {
            // outputs the content of the widget
        }

        /**
         * Outputs the options form on admin
         *
         * @param array $instance The widget options
         */
        public function form( $instance ) {
            // outputs the options form on admin
    ?>
        <div id="here"></div>
        <input type="button" id="addRepeat" value="Click Me!" />

      <?php
        }

        /**
         * Processing widget options on save
         *
         * @param array $new_instance The new options
         * @param array $old_instance The previous options
         */
        public function update( $new_instance, $old_instance ) {
            // processes widget options to be saved
        }
    }


    function register_repeat_field_widget() {
        register_widget( \'repeat_field_widget\' );
    }
    add_action( \'widgets_init\', \'register_repeat_field_widget\' );

    function repeat_field_widget_scripts() {
    wp_enqueue_script( \'repeat-field-widget-scripts\', get_template_directory_uri() . \'/repeat.js\', array( \'jquery\' ), \'1.0.0\', true );
}
add_action( \'wp_enqueue_scripts\', \'repeat_field_widget_scripts\' );

repeat.js

    jQuery(document).ready(function($){
       //call when the button is click
       $("#addRepeat").click(function() {
           $(\'#here\').append(\'<p>Hello</p>\');
       });
    });

2 个回复
最合适的回答,由SO网友:Sengngy Kouch 整理而成

非常感谢。Dave RomseyMark Kaplun 用于指出在WordPress小部件中不使用HTML ID。我终于找到了满足我需求的解决方案。

Solution:

我们需要在所有3个函数(小部件、表单、更新)中添加一个预设变量。在我的代码中,它们被称为“spotlight\\u image\\u link1、spotlight\\u image\\u link2等”。然后在“form function”中使用php代码给出它们的id。请阅读下面的代码以了解更多信息。

What can my solution do?

基本上,它不是完全动态的,因为我们需要预先定义所有聚光灯。在我的例子中,我只预定义了两个聚光灯,以使代码易于阅读。

Here what it looks like: enter image description here

Logic behind the scene:

每当“点击我!”按钮,将添加聚光灯

Limitation:

到目前为止,无论何时单击“保存”,聚光灯顺序都会从1重新排列为n。这不是超级用户友好的,但我计划使用Ajax将前端同步到后端。我还不知道怎么回事。

Source code:

从WordPress 4.7.2开始,它的工作没有任何错误

repeat.php

    <?php
/**
 * Plugin Name: Repeat Field
 *
 */

 class repeat_field_widget extends WP_Widget {

    /**
     * Sets up the widgets name etc
     */
    public function __construct() {
        $widget_ops = array(
            \'classname\' => \'repeat_field_widget\',
            \'description\' => \'Repeat Field for Name input\'
        );
        parent::__construct( \'repeat_field_widget\', \'Repeat Field\', $widget_ops );
    $tracker1;
    }

    /**
     * Outputs the content of the widget
     *
     * @param array $args
     * @param array $instance
     */
    public function widget( $args, $instance ) {
        // outputs the content of the widget
    $spotlight_add_row = ! empty( $instance[\'spotlight_add_row\'] ) ? $instance[\'spotlight_add_row\'] : \'\';
    $spotlight_row_appender = ! empty( $instance[\'spotlight_row_appender\'] ) ? $instance[\'spotlight_row_appender\'] : \'\';

    /**============== Spotlight 1 =========================*/
    $spotlight_image_link1 = ! empty( $instance[\'spotlight_image_link1\'] ) ? $instance[\'spotlight_image_link1\'] : \'\';
    $spotlight_add_image1 = ! empty( $instance[\'spotlight_add_image1\'] ) ? $instance[\'spotlight_add_image1\'] : \'\';
    $spotlight_image_preview1 = ! empty( $instance[\'spotlight_image_preview1\'] ) ? $instance[\'spotlight_image_preview1\'] : \'\';
    $spotlight_name1 = ! empty( $instance[\'spotlight_name1\'] ) ? $instance[\'spotlight_name1\'] : \'\';
    $spotlight_description1 = ! empty( $instance[\'spotlight_description1\'] ) ? $instance[\'spotlight_description1\'] : \'\';
    $spotlight_link1 = ! empty( $instance[\'spotlight_link1\'] ) ? $instance[\'spotlight_link1\'] : \'\';

    /**============== Spotlight 2 =========================*/
    $spotlight_image_link2 = ! empty( $instance[\'spotlight_image_link2\'] ) ? $instance[\'spotlight_image_link2\'] : \'\';
    $spotlight_add_image2 = ! empty( $instance[\'spotlight_add_image2\'] ) ? $instance[\'spotlight_add_image2\'] : \'\';
    $spotlight_image_preview2 = ! empty( $instance[\'spotlight_image_preview2\'] ) ? $instance[\'spotlight_image_preview2\'] : \'\';
    $spotlight_name2 = ! empty( $instance[\'spotlight_name2\'] ) ? $instance[\'spotlight_name2\'] : \'\';
    $spotlight_description2 = ! empty( $instance[\'spotlight_description2\'] ) ? $instance[\'spotlight_description2\'] : \'\';
    $spotlight_link2 = ! empty( $instance[\'spotlight_link2\'] ) ? $instance[\'spotlight_link2\'] : \'\';
    }

    /**
     * Outputs the options form on admin
     *
     * @param array $instance The widget options
     */
    public function form( $instance ) {
        // outputs the options form on admin
    $instance = wp_parse_args( (array) $instance, array( \'spotlight_add_row\' => \'\', \'spotlight_row_appender\' => \'\', \'spotlight_image_link1\' => \'\', \'spotlight_add_image1\' => \'\', \'spotlight_image_preview1\' => \'\', \'spotlight_name1\' => \'\', \'spotlight_description1\' => \'\', \'spotlight_link1\' => \'\',
    \'spotlight_image_link2\' => \'\', \'spotlight_add_image2\' => \'\', \'spotlight_image_preview2\' => \'\', \'spotlight_name2\' => \'\', \'spotlight_description2\' => \'\', \'spotlight_link2\' => \'\' ));

    //Create Add and delete button
    $spotlight_add_row = $instance[\'spotlight_add_row\'];
    $spotlight_row_appender = $instance[\'spotlight_row_appender\'];

    /**================== Spotlight 1 ==============*/
    $spotlight_image_link1 = $instance[\'spotlight_image_link1\'];
    $spotlight_add_image1 = $instance[\'spotlight_add_image1\'];
    $spotlight_image_preview1 = $instance[\'spotlight_image_preview1\'];
    $spotlight_name1 = $instance[\'spotlight_name1\'];
    $spotlight_description1 = $instance[\'spotlight_description1\'];
    $spotlight_link1 = $instance[\'spotlight_link1\'];

    /**================== Spotlight 2 ==============*/
    $spotlight_image_link2 = $instance[\'spotlight_image_link2\'];
    $spotlight_add_image2 = $instance[\'spotlight_add_image2\'];
    $spotlight_image_preview2 = $instance[\'spotlight_image_preview2\'];
    $spotlight_name2 = $instance[\'spotlight_name2\'];
    $spotlight_description2 = $instance[\'spotlight_description2\'];
    $spotlight_link2 = $instance[\'spotlight_link2\'];

    $starter = 1; //Store which number to continue adding spotlight.
    $num = 1;
    $max_spotlight = 2; //number of spotlight allowed.
    static $tracker = array(0,0); //setup a tracker for each spotlight, zero mean none active.

    while($num <= $max_spotlight){
      $tempImage = \'spotlight_image_link\' . $num;

       if ($$tempImage != \'\'){
        $starter++;
        $tracker[$num - 1] = 1;
?>
        <!-- Image input -->
        <div>
        <p class="spotlight-para">Spotlight <?php echo $num; ?></p>
        <p> <?php $tempImage = \'spotlight_image_link\' . $num;  $tempDeleteName = \'deletespotlight_\'. $num;?> <!-- store the combined name. -->
            <label for="<?php echo esc_attr( $this->get_field_id( $tempImage ) ); ?>"><?php esc_attr_e( \'Image\\\'s link:\', \'text_domain\' ); ?></label>
            <input
                   class="widefat"
                   id="<?php echo $this->get_field_id($tempImage); ?>"
                   name="<?php echo $this->get_field_name($tempImage); ?>"
                   type="text"
                   value="<?php echo esc_attr($$tempImage); ?>"
                   />
           <input style="float:right;" id="delete-spotlight" name="<?php echo $tempDeleteName; ?>" type="button" value="Delete Spotlight" class="button"/>
           <br />
        </p>
        </div>
<?php
      }
     $num++;
    }
    $id_prefix = $this->get_field_id(\'\'); //get the widget prefix id.
?>
    <span id="<?php echo $this->get_field_id(\'spotlight_row_appender\'); ?>"> </span>
    <div>
      <br />
      <input
            class="button"
            type="button"
            id="<?php echo $this->get_field_id(\'spotlight_add_row\'); ?>"
            value="Click Me!"
            onclick="repeater.uploader(\'<?php echo $this->id;?>\', \'<?php echo $id_prefix;?>\'); return false;"
            />
    </div>

    <script>
    jQuery(document).ready(function($){
      var tracker = <?php echo json_encode($tracker); ?>;
      var c1 = <?php echo json_encode($starter - 1); ?>;//index of the array.

      //disbale add button when reaches max spotlight.
      if(tracker.every(x => x > 0)){
        $(\'#\' + \'<?php echo $id_prefix; ?>\' + \'spotlight_add_row\').attr("disabled",true);
      }

      repeater = {
          //TRY to mass Number into this function........
          uploader :function(widget_id, widget_id_string){
            //Find the non active element
            var i;
            for (i = 0; i < <?php echo $max_spotlight; ?>; i++){
              if ( tracker[i] == 0){
                c1 = i;
                break;
              }
            }
            c1++;
            //alert(c1);



            $("#" + widget_id_string + "spotlight_row_appender").append(\'<div> <p class="spotlight-para">Spotlight \'+c1+\'</p><p> <label for="<?php echo esc_attr( $this->get_field_id( "spotlight_image_link\'+c1+\'")); ?>"><?php esc_attr_e( \'Image\\\'s link:\', \'text_domain\' ); ?></label>  <input  class="widefat" id="<?php echo $this->get_field_id("spotlight_image_link\'+c1+\'"); ?>"  name="<?php echo $this->get_field_name("spotlight_image_link\'+c1+\'"); ?>" type="text" value="" />  <input style="float:right;"id="delete-spotlight" name="deletespotlight_\'+c1+\'" type="button" value="Delete Spotlight" class="button"/><br /> </p></div>\');
            //check element as active
            tracker[c1-1] = 1;

            //if all element is > 0, disable the deleteButton.
            if(tracker.every(x => x > 0)){
              $(\'#\' + \'<?php echo $id_prefix; ?>\' + \'spotlight_add_row\').attr("disabled",true);
            }
            //alert(c1);
            return false;
          }
      };

      $(document).on(\'click\', \'#delete-spotlight\', function() {

        $(this).parent().parent().remove(); //remove the field.
        $(\'#\' + \'<?php echo $id_prefix; ?>\' + \'spotlight_add_row\').removeAttr("disabled"); //reset add button.

        //Get the name, and parse to get the ID.
        var deleteButtonName = this.name;
        var stringDeleteButton = deleteButtonName.split("_").pop();
        var deleteButtonID = parseInt(stringDeleteButton);

        tracker[deleteButtonID-1] = 0; //reset element
        //alert(tracker);
      });

    });
    </script>
  <?php
    }

    /**
     * Processing widget options on save
     *
     * @param array $new_instance The new options
     * @param array $old_instance The previous options
     */
    public function update( $new_instance, $old_instance ) {
        // processes widget options to be saved
    $instance = $old_instance;
    $instance[\'spotlight_add_row\'] = sanitize_text_field($new_instance[\'spotlight_add_row\']);
    $instance[\'spotlight_row_appender\'] = sanitize_text_field($new_instance[\'spotlight_row_appender\']);

    $increment = 1;
    while ( $increment <= 2 ){
      //increment variables
      $increment_image_link = \'spotlight_image_link\' . $increment;
      $increment_add_image = \'spotlight_add_image\' . $increment;
      $increment_image_preview = \'spotlight_image_preview\' . $increment;
      $increment_description = \'spotlight_description\' . $increment;
      $increment_name = \'spotlight_name\' . $increment;
      $increment_link = \'spotlight_link\' . $increment;

      $instance[$increment_image_link] = sanitize_text_field( $new_instance[$increment_image_link] );
      $instance[$increment_add_image] = sanitize_text_field( $new_instance[$increment_add_image] );
      $instance[$increment_image_preview] = sanitize_text_field( $new_instance[$increment_image_preview]);
      $instance[$increment_name] = sanitize_text_field( $new_instance[$increment_name] );
      $instance[$increment_description] = sanitize_text_field( $new_instance[$increment_description] );
      $instance[$increment_link] = sanitize_text_field( $new_instance[$increment_link] );

      $increment++;
    }
    $starter = 1;
    $num = 1;

    return $instance;
    }
}


function register_repeat_field_widget() {
    register_widget( \'repeat_field_widget\' );
}
add_action( \'widgets_init\', \'register_repeat_field_widget\' );

Quick Note:

我知道这不是最干净、安全和最好的代码,但我仍在学习。我希望这能帮助任何和我面临同样问题的人。

SO网友:Mark Kaplun

小部件表单对于JS操作来说很棘手。通常,您不应该使用ID来检测表单中的元素,而应该使用类和find(), parent()

原因是HTML页面上可能有多个表单。可以肯定的是,在小部件管理页面上有一个“模板”表单没有显示,IIRC用于生成新小部件的表单。这意味着将至少有两个元素具有相同的ID,并且尝试通过DOM API访问它们将不会得到一致的结果。