Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Repeatable fields #244

Open
danielbachhuber opened this issue Mar 27, 2015 · 9 comments
Open

Repeatable fields #244

danielbachhuber opened this issue Mar 27, 2015 · 9 comments

Comments

@danielbachhuber
Copy link
Contributor

Request from WordPress.org:

A repeater field would be for making an element with X number of parts to it. Like tabs for example.

@mattheu mattheu added this to the next milestone Apr 6, 2015
@mattheu mattheu self-assigned this Apr 13, 2015
@mattheu
Copy link
Contributor

mattheu commented Apr 20, 2015

Going to punt this from 0.3.

  • I'm not sure how to do this with the current structure.
  • I'm also wary of rewriteing the whole thing and building fieldmanager
  • We should reach out to the Metadata API featured plugin project to ask about this.
  • I'll hold off assigning a new milestone until this has better direction

@mattheu mattheu removed this from the v0.3.0 milestone Apr 20, 2015
@StaggerLeee
Copy link

So it means we could use Shortcake as best possible visual tables editing TinyMce tool ?
If it is so it is revolutionary.

@widoz
Copy link

widoz commented Apr 3, 2016

Any news on this?

@kaoquan
Copy link

kaoquan commented Apr 27, 2017

I created a new field attribute fields
(I'm using richtext plugin as well but you can remove the "shortcake-richtext" class from the textarea https://wordpress.org/plugins/shortcode-ui-richtext/)

This has a bug, it will not update the last keypress or if you do only image add.

You have to create a class with the code below:


/**
 * Primary controller class for Shortcake Columns Field
 */
class Shortcake_Field_Columns {

    /**
     * Shortcake Columns Field controller instance.
     *
     * @access private
     * @var object
     */
    private static $instance;

    /**
     * All registered post fields.
     *
     * @access private
     * @var array
     */
    private $post_fields  = array();

    /**
     * Settings for the Columns Field.
     *
     * @access private
     * @var array
     */
    private $fields = array(
        'columns' => array(
            'template' => 'fusion-shortcake-field-columns',
            'view'     => 'editAttributeField',
        ),
    );

    /**
     * Get instance of Shortcake Columns Field controller.
     *
     * Instantiates object on the fly when not already loaded.
     *
     * @return object
     */
    public static function get_instance() {
        if ( ! isset( self::$instance ) ) {
            self::$instance = new self;
            self::$instance->setup_actions();
        }
        return self::$instance;
    }

    /**
     * Set up actions needed for Columns Field
     */
    private function setup_actions() {
        add_filter( 'shortcode_ui_fields', array( $this, 'filter_shortcode_ui_fields' ) );
        add_action( 'shortcode_ui_loaded_editor', array( $this, 'load_template' ) );
    }

    /**
     * Whether or not the color attribute is present in registered shortcode UI
     *
     * @return bool
     */
    private function columns_attribute_present() {

        foreach ( Shortcode_UI::get_instance()->get_shortcodes() as $shortcode ) {

            if ( empty( $shortcode['attrs'] ) ) {
                continue;
            }

            foreach ( $shortcode['attrs'] as $attribute ) {
                if ( empty( $attribute['type'] ) ) {
                    continue;
                }

                if ( 'columns' === $attribute['type'] ) {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * Add Color Field settings to Shortcake fields
     *
     * @param array $fields
     * @return array
     */
    public function filter_shortcode_ui_fields( $fields ) {
        return array_merge( $fields, $this->fields );
    }

    /**
     * Output templates used by the Columns field.
     */
    public function load_template() {

        ?>
        <script type="text/javascript">
            function updateColumnData(id){
                var data = [];

                jQuery.each(jQuery('#'+id+"_list > li"), function(index, value){
                    var columnData = {
                        title: htmlspecialchars(jQuery(value).find('.r_title').val()),
                        text_content: htmlspecialchars(jQuery(value).find('.r_text_content').val()),
                        imgid: jQuery(value).find('.imagedata .r_imageid').val(),
                        imgurl: jQuery(value).find('.imagedata .r_imageurl').val()
                    };
                    data.push(columnData);
                });

                var dataText = JSON.stringify(data);
                dataText = dataText.replace('[','').replace(']','').replace(/[\\"']/g, '\'').replace(/\u0000/g, '\'');
                jQuery('#'+id).val((dataText));
            }

            function checkColumns(id){
                if(jQuery('#'+id+"_list > li").size > 15){
                    jQuery('#'+id+"_add_review").hide();
                } else {
                    jQuery('#'+id+"_add_review").show();
                }
            }

            function addColumn(id){
                var list = jQuery('#'+id+'_list');
                var first = jQuery('#'+id+'_first');
                var newElement = first.clone();
                newElement.attr('id','');
                jQuery('input[type=text]', newElement).val('');
                jQuery('.previewimage', newElement).css('background-image','none');
                jQuery('.removeimage', newElement).hide();
                jQuery('input[type=hidden]', newElement).val('');
                jQuery('input[type=number]', newElement).val('');
                jQuery('textarea', newElement).val('');
               
                jQuery(newElement).find('.shortcake-richtext').summernote( 'destroy' );
                jQuery(newElement).find('.note-editor').remove();
                jQuery(newElement).find('.shortcake-richtext').summernote({
                    toolbar: [
                        [ 'style', ['style'] ],
                        [ 'para', [ 'ul', 'ol' ] ],
                        [ 'font', [ 'bold', 'italic', 'underline', 'strikethrough', 'superscript', 'subscript', 'clear' ] ],
                        [ 'fontsize' , [ 'fontsize' ] ],
                        [ 'color', [ 'color' ] ],
                        [ 'table', [ 'table' ] ],
                        [ 'insert', [ 'link', 'picture', 'video' ] ],
                        [ 'view', [ 'codeview', 'help' ] ]
                    ]
                });
                list.append(newElement);
                checkColumns(id);
            }

            function removeColumn(id,element){
                var parent = jQuery(element).parent('li');
                if(jQuery('#'+id+'_list > li').length > 1){
                    if(parent.attr('id') == id+'_first') {
                        parent.next().attr('id', id+'_first');
                    }
                    parent.remove();
                    updateColumnData(id);
                }
                checkColumns(id);
            }

            function initColumns(id){

                var initdata = jQuery('#'+ id +'_initdata').val();
                initdata = '[' + initdata.replace(/[\\']/g, '"') + ']';
                initdata = JSON.parse(initdata);

                if(initdata.length){
                    for(var i = 0; i < initdata.length; i++){
                        var eData = initdata[i];
                        var element = jQuery('#'+id+'_first');
                        var target;
                        if(i == 0){
                            target = element;
                        } else {
                            target = element.clone();
                            jQuery('input[type=text]', target).val('');
                            jQuery('.previewimage', target).css('background-image','none');
                            jQuery('.removeimage', target).hide();
                            jQuery('input[type=hidden]', target).val('');
                            jQuery('input[type=number]', target).val('');
                            jQuery('textarea', target).val('');
                           
                            jQuery(target).find('.shortcake-richtext').summernote( 'destroy' );
                            jQuery(target).find('.note-editor').remove();
                            jQuery(target).find('.shortcake-richtext').summernote({
                                toolbar: [
                                    [ 'style', ['style'] ],
                                    [ 'para', [ 'ul', 'ol' ] ],
                                    [ 'font', [ 'bold', 'italic', 'underline', 'strikethrough', 'superscript', 'subscript', 'clear' ] ],
                                    [ 'fontsize' , [ 'fontsize' ] ],
                                    [ 'color', [ 'color' ] ],
                                    [ 'table', [ 'table' ] ],
                                    [ 'insert', [ 'link', 'picture', 'video' ] ],
                                    [ 'view', [ 'codeview', 'help' ] ]
                                ]
                            });
                        }

                        if(eData.title){
                            jQuery(target).find('.r_title').val(htmlspecialchars_decode(eData.title));
                        }
                        if(eData.text_content){
                            jQuery(target).find('.r_text_content').val(htmlspecialchars_decode(eData.text_content));
                        }
                        if(eData.imgid){
                            jQuery(target).find('.imagedata .r_imageid').val(eData.imgid);
                            jQuery(target).find('.imagedata .removeimage').show();
                        }
                        if(eData.imgurl){
                            jQuery(target).find('.imagedata .r_imageurl').val(eData.imgurl);
                            jQuery(target).find('.imagedata .previewimage').css('background-image','url(' +eData.imgurl + ')');
                        }

                        if(i != 0){
                            var list = jQuery('#'+id+'_list');
                            target.attr('id','');
                            list.append(target);
                        }
                    }
                }
                updateColumnData(id);
            }

            function attachColumnImage(id,element){

                var meta_image_frame;

                if ( meta_image_frame ) {
                    wp.media.editor.open();
                    return;
                }

                meta_image_frame = wp.media.frames.meta_image_frame = wp.media({
                    title: '<?php  echo __('Select Image', 'xapt') ?>',
                    button: { text:  '<?php  echo __('Insert', 'xapt') ?>' },
                    library: { type: 'image' }
                });

                meta_image_frame.on('select', function(){
                    var media_attachment = meta_image_frame.state().get('selection').first().toJSON();
                    var parent = jQuery(element).parents('.imagecontainer');
                    parent.find('.r_imageid').val(media_attachment.id);
                    parent.find('.r_imageurl').val((media_attachment.sizes && media_attachment.sizes.full.url || media_attachment.url));
                    parent.find('.previewimage').css('background-image','url(' + (media_attachment.sizes && media_attachment.sizes.thumbnail.url || media_attachment.url) + ')');
                    parent.find('.removeimage').show();

                    updateColumnData(id);
                });

                meta_image_frame.open()

            }

            function removeColumnImage(id,elem){
                var parent = jQuery(elem).parents('.imagecontainer');
                parent.find('.r_imageid').val('');
                parent.find('.r_imageurl').val('');
                parent.find('.previewimage').css('background-image','none');
                parent.find('.removeimage').hide();

                updateColumnData(id);
            }

        </script>

        <script type="text/html" id="tmpl-fusion-shortcake-field-columns">
            <div class="field-block shortcode-ui-field-columns shortcode-ui-attribute-{{ data.attr }}">
                <input type="button" class="button-primary" value="<?php  echo __('Add Column', 'xapt') ?>" id="{{ data.id }}_add_review" onclick="addColumn('{{ data.id }}')" />
                
                <hr />
                
                <form id="{{ data.id }}_reviews" name="{{ data.id }}_counters">

                    <input type="hidden" class="large-text" name="initdata" id="{{ data.id }}_initdata" value="{{ data.value }}" />

                    <input type="hidden" class="large-text" name="{{ data.attr }}" id="{{ data.id }}" value="{{ data.value }}" />

                    <ul class="sortable" id="{{ data.id }}_list">

                        <li id="{{ data.id }}_first">
                            <table>
                                <tr>
                                    <td style="vertical-align: top;">
                                        <input type="text" class="regular-text r_title" placeholder="<?php  echo __('Title', 'xapt') ?>" onkeyup="updateColumnData('{{ data.id }}')" /><br />
                                        <textarea class="shortcake-richtext regular-text r_text_content" style="margin: 10px 0 0; width: 300px; height: 131px;" placeholder="<?php  echo __('Content', 'xapt') ?>" onkeyup="updateColumnData('{{ data.id }}')"></textarea>
                                    </td>
                                    <td class="imagecontainer imagedata" style="vertical-align: top; padding-left: 10px;">
                                        <input type="hidden" id="{{ data.id }}_img" class="r_imageid" />
                                        <input type="hidden" id="{{ data.id }}_imgurl" class="r_imageurl" />
                                        <input type="button" class="button-secondary" value="<?php  echo __('Attach Image', 'xapt') ?>" onclick="attachColumnImage('{{ data.id }}',this)" />
                                        <input type="button" class="button-secondary removeimage" style="display: none;" value="<?php  echo __('Remove', 'xapt') ?>" id="{{ data.id }}_removeimage" onclick="removeColumnImage('{{ data.id }}',this)" />
                                        <div style="margin-top: 15px; width: 128px; height: 128px; border: 1px dashed #ccc; background-size: contain; background-repeat: no-repeat; background-position: center;" id="{{ data.id }}_preview" class="previewimage"></div>
                                    </td>
                                </tr>
                            </table>

                            <input type="button" class="button-primary remove-button" value="<?php  echo __('Remove', 'xapt') ?>" onclick="removeColumn('{{ data.id }}', this)" />
                            <hr />
                        </li>

                    </ul>
                </form>
                <script type="text/javascript">initColumns('{{ data.id }}');</script>
            </div>
        </script>

        <?php
    }

}

$feautres_field = Shortcake_Field_Columns::get_instance();

and use it in the shortcode like this:

shortcode_ui_register_for_shortcode( 'columns_block', array(
                'label' => __('Columns Block', 'xapt'),
                'listItemImage' => 'dashicons-layout',
                'post_type'     => array( 'post' ),
                'attrs' => array(
                    array(
                        'label'       => __('Columns Block', 'xapt'),
                        'attr'        => 'columns',
                        'type'        => 'columns',
                    ),
                )
            )
        );
add_shortcode( 'columns_block', function( $attr, $content = '' ) {
            $attr = wp_parse_args( $attr, array(
                'columns' => ''
            ) );

            ob_start();

            if(!empty($attr['columns'])){
                $attr['columns'] = '['.str_replace("'",'"',$attr['columns']).']';
                $columns = json_decode($attr['columns'],true);
                $columnsFull = array();
                
                foreach($columns as $column){
                    $column['title'] = urldecode($column['title']);
                    $column['text_content'] = urldecode($column['text_content']);
                    $image = wp_get_attachment_image_src( $column['imgid'], 'gallery_thumbnail');
                    $column['imgurl'] = (!empty($image) ? $image[0] : false );
                    $columnsFull[] = $column;
                }

                twig_render('components/shortcodes/shortcode.columns-block.twig', array(
                    'columns' => $columnsFull
                ));

            }else{
                echo '<div style="padding: 10px; width: 100%; text-align: center; border: 1px dotted #ccc;">' . __('Click here to customize', 'xapt') . '</div>';
            }
            return ob_get_clean();

        } );

If you don't use twig just repalce the twig_render function with the output html

@mattwatsoncodes
Copy link

Hi @kaoquan did you manage to fix that onkeyup bug? I'm implementing a similar solution, and have the same issue!

@mattwatsoncodes
Copy link

@kaoquan I managed a hacky solution, by triggering a change() on another field.

@kaoquan
Copy link

kaoquan commented Oct 13, 2017

@mwtsn Yes I did here it goes

i have a js file for the admin like this

var richTextSelector = 'textarea.shortcake-richtext-field';
var richText = {};

/* globals jQuery, alert */
jQuery(function( $ ) {
    'use strict';
    
    richText.load = function( selector ) {
        if ( ( 'undefined' !== tinyMCE ) && ( $( selector ).length ) ) {
            $( selector ).each( function() {

                var textarea_id = $(this).attr('id');

                if( null === tinyMCE.get( textarea_id ) ) {

                    // Add a slight delay to offset the loading of any elements on the page. Sometimes doesn't load correctly
                    setTimeout(function () {
                        // Bind tinyMCE to this field
                        tinyMCE.execCommand('mceAddEditor', false, textarea_id );
                    }, 10);

                }

            });

            return true;
        } else {
            return false;
        }
    };

    richText.unload = function( selector ) {

        if ( ( $( selector ).length ) ) {
            $( selector ).each( function() {
                var textarea_id = $( this).attr('id');
                if( null != tinyMCE.get( textarea_id ) ) {
                    // Remove tinyMCE from the field
                    tinymce.execCommand( 'mceRemoveEditor', false, textarea_id );
                }
                
            });

            return true;
        } else {
            return false;
        }
    };

} );

function addItem(id){
    var list = jQuery('#'+id+'_list');
    var first = jQuery('#'+id+'_first');
    richText.unload( jQuery( first ).find( richTextSelector ) );
    var newElement = first.clone();
    richText.load( jQuery( first ).find( richTextSelector ) );
    
    newElement.attr('id','');
    
    jQuery('input[type=text]', newElement).val('');
    jQuery('.previewimage', newElement).css('background-image','none');
    jQuery('.removeimage', newElement).hide();
    jQuery('input[type=hidden]', newElement).val('');
    jQuery('input[type=number]', newElement).val('');
    jQuery('textarea', newElement).val('');
    
    richText.count++;
    jQuery(newElement).find('.r_text_content').attr('id',id + '-text-cotent-' + richText.count);
    richText.load( jQuery( newElement ).find( richTextSelector ) );
   
    list.append(newElement);
}

function removeItem(id,element){
    var parent = jQuery(element).parent('li');
    if(jQuery('#'+id+'_list > li').length > 1){
        if(parent.attr('id') == id+'_first') {
            parent.next().attr('id', id+'_first');
        }
        richText.unload( jQuery( parent ).find( richTextSelector ) );
        parent.remove();
    }
}

function attachItemImage(id,element){

    var meta_image_frame;

    if ( meta_image_frame ) {
        wp.media.editor.open();
        return;
    }

    meta_image_frame = wp.media.frames.meta_image_frame = wp.media({
        title: 'Select Image',
        button: { text:  'Insert'},
        library: { type: 'image' }
    });

    meta_image_frame.on('select', function(){
        var media_attachment = meta_image_frame.state().get('selection').first().toJSON();
        var parent = jQuery(element).parents('.imagecontainer');
        parent.find('.r_imageid').val(media_attachment.id);
        parent.find('.r_imageurl').val((media_attachment.sizes && media_attachment.sizes.full.url || media_attachment.url));
        parent.find('.previewimage').css('background-image','url(' + (media_attachment.sizes && media_attachment.sizes.full.url || media_attachment.url) + ')');
        parent.find('.removeimage').show();
    });

    meta_image_frame.open()

}

function removeItemImage(id,elem){
    var parent = jQuery(elem).parents('.imagecontainer');
    parent.find('.r_imageid').val('');
    parent.find('.r_imageurl').val('');
    parent.find('.previewimage').css('background-image','none');
    parent.find('.removeimage').hide();
}

/** fps corencting encoding **/
function htmlspecialchars(str) {
    var map = {
        "<": "%3C",
        ">": "%3E",
        "[": "%5B",
        "]": "%5D",
        "\\": "%5C",
        "\"": "%22",
        "'": "%27",
        "+": "%2B",
        "\n": "%0A",
        "\t": "%09"
    };
    if(str == '<p><br></p>'){
        str = '';
    }
    return str.replace(/[<>\[\]\\"'+\n\t]/g, function(m) { return map[m]; });
}
function htmlspecialchars_decode(str) {
    var map = {
        "%3C": "<",
        "%3E": ">",
        "%5B": "[",
        "%5D": "]",
        "%5C": "\\",
        "%22": "\"",
        "%27": "'",
        "%2B": "+",
        "%0A" : "\n",
        "%09" : "\t"
    };
    return str.replace(/(%3C|%3E|%5B|%5D|%5C|%22|%27|%2B|%0A|%09)/g, function(m) { return map[m]; });
}```

and the class I changed it like this i hope it help, (off for the weekend but will reply for any question on monday)

```<?php

/**
 * Primary controller class for Shortcake Columns Field
 */
class Shortcake_Field_Columns {

    /**
     * Shortcake Columns Field controller instance.
     *
     * @access private
     * @var object
     */
    private static $instance;

    /**
     * All registered post fields.
     *
     * @access private
     * @var array
     */
    private $post_fields  = array();

    /**
     * Settings for the Columns Field.
     *
     * @access private
     * @var array
     */
    private $fields = array(
        'columns' => array(
            'template' => 'fusion-shortcake-field-columns',
            'view'     => 'editAttributeField',
        ),
    );

    /**
     * Get instance of Shortcake Columns Field controller.
     *
     * Instantiates object on the fly when not already loaded.
     *
     * @return object
     */
    public static function get_instance() {
        if ( ! isset( self::$instance ) ) {
            self::$instance = new self;
            self::$instance->setup_actions();
        }
        return self::$instance;
    }

    /**
     * Set up actions needed for Columns Field
     */
    private function setup_actions() {
        add_filter( 'shortcode_ui_fields', array( $this, 'filter_shortcode_ui_fields' ) );
        add_action( 'shortcode_ui_loaded_editor', array( $this, 'load_template' ) );
    }

    /**
     * Whether or not the color attribute is present in registered shortcode UI
     *
     * @return bool
     */
    private function columns_attribute_present() {

        foreach ( Shortcode_UI::get_instance()->get_shortcodes() as $shortcode ) {

            if ( empty( $shortcode['attrs'] ) ) {
                continue;
            }

            foreach ( $shortcode['attrs'] as $attribute ) {
                if ( empty( $attribute['type'] ) ) {
                    continue;
                }

                if ( 'columns' === $attribute['type'] ) {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * Add Color Field settings to Shortcake fields
     *
     * @param array $fields
     * @return array
     */
    public function filter_shortcode_ui_fields( $fields ) {
        return array_merge( $fields, $this->fields );
    }

    /**
     * Output templates used by the Columns field.
     */
    public function load_template() {

        ?>
        <script type="text/javascript">
            function updateColumnData(id){
                var data = [];

                jQuery.each(jQuery('#'+id+"_list > li"), function(index, value){
                    var columnData = {
                        title: htmlspecialchars(jQuery(value).find('.r_title').val()),
                        text_content: htmlspecialchars(jQuery(value).find('.r_text_content').val()),
                        imgid: jQuery(value).find('.imagedata .r_imageid').val(),
                        imgurl: jQuery(value).find('.imagedata .r_imageurl').val()
                    };
                    data.push(columnData);
                });

                var dataText = JSON.stringify(data);
                dataText = dataText.replace('[','').replace(']','').replace(/[\\"']/g, '\'').replace(/\u0000/g, '\'');
                jQuery( '#'+id ).val( dataText ).trigger( 'input' );
            }

            function initColumns(id){
                richText.count = 0;

                var initdata = jQuery('#'+ id +'_initdata').val();
                initdata = '[' + initdata.replace(/[\\']/g, '"') + ']';
                initdata = JSON.parse(initdata);
                
                var element = jQuery('#'+id+'_first');
                jQuery(element).find('.r_text_content').attr('id',id + '-text-cotent-' + 0);

                if(initdata.length){
                    richText.count = initdata.length;
                    for(var i = 0; i < initdata.length; i++){
                        var eData = initdata[i];
                        var target;
                        if(i == 0){
                            target = element;
                        } else {
                            target = element.clone();
                            jQuery('input[type=text]', target).val('');
                            jQuery('.previewimage', target).css('background-image','none');
                            jQuery('.removeimage', target).hide();
                            jQuery('input[type=hidden]', target).val('');
                            jQuery('input[type=number]', target).val('');
                            jQuery('textarea', target).val('');
                        }

                        if(eData.title){
                            jQuery(target).find('.r_title').val(htmlspecialchars_decode(eData.title));
                        }
                        if(eData.text_content){
                            jQuery(target).find('.r_text_content').val(htmlspecialchars_decode(eData.text_content));
                        }
                        if(eData.imgid){
                            jQuery(target).find('.imagedata .r_imageid').val(eData.imgid);
                            jQuery(target).find('.imagedata .removeimage').show();
                        }
                        if(eData.imgurl){
                            jQuery(target).find('.imagedata .r_imageurl').val(eData.imgurl);
                            jQuery(target).find('.imagedata .previewimage').css('background-image','url(' +eData.imgurl + ')');
                        }
                        jQuery(target).find('.r_text_content').attr('id',id + '-text-cotent-' + i);

                        if(i != 0){
                            var list = jQuery('#'+id+'_list');
                            target.attr('id','');
                            list.append(target);
                        }
                    }
                }
                
                richText.load( jQuery( richTextSelector ) );
            }

        </script>

        <script type="text/html" id="tmpl-fusion-shortcake-field-columns">
            <div class="field-block shortcode-ui-field-columns shortcode-ui-attribute-{{ data.attr }}">
                <input type="button" class="button-primary" value="<?php  echo __('Add Column', 'xapt') ?>" id="{{ data.id }}_add_review" onclick="addItem('{{ data.id }}')" />
                
                <hr />
                
                <form id="{{ data.id }}_reviews" name="{{ data.id }}_counters">

                    <input type="hidden" class="large-text" name="initdata" id="{{ data.id }}_initdata" value="{{ data.value }}" />

                    <input type="hidden" class="large-text" name="{{ data.attr }}" id="{{ data.id }}" value="{{ data.value }}" />

                    <ul class="sortable" id="{{ data.id }}_list">

                        <li id="{{ data.id }}_first">
                            <table>
                                <tr>
                                    <td style="vertical-align: top;">
                                        <input type="text" class="regular-text r_title" placeholder="<?php  echo __('Title', 'xapt') ?>" /><br />
                                        <textarea class="shortcake-richtext-field regular-text r_text_content" style="margin: 10px 0 0; width: 300px; height: 131px;" placeholder="<?php  echo __('Content', 'xapt') ?>"></textarea><br/>
                                        
                                    </td>
                                    <td class="imagecontainer imagedata" style="vertical-align: top; padding-left: 10px;">
                                        <input type="hidden" id="{{ data.id }}_img" class="r_imageid" />
                                        <input type="hidden" id="{{ data.id }}_imgurl" class="r_imageurl" />
                                        <input type="button" class="button-secondary" value="<?php  echo __('Attach Image', 'xapt') ?>" onclick="attachItemImage('{{ data.id }}',this)" />
                                        <input type="button" class="button-secondary removeimage" style="display: none;" value="<?php  echo __('Remove', 'xapt') ?>" id="{{ data.id }}_removeimage" onclick="removeItemImage('{{ data.id }}',this)" />
                                        <div style="margin-top: 15px; width: 128px; height: 128px; border: 1px dashed #ccc; background-size: contain; background-repeat: no-repeat; background-position: center;" id="{{ data.id }}_preview" class="previewimage"></div>
                                    </td>
                                </tr>
                            </table>

                            <input type="button" class="button-primary remove-button" value="<?php  echo __('Remove', 'xapt') ?>" onclick="removeItem('{{ data.id }}', this)" />
                            <hr />
                        </li>

                    </ul>
                </form>
                <script type="text/javascript">
                    initColumns('{{ data.id }}');
                    wp.shortcake.hooks.addAction( 'shortcode-ui.render_destroy', function() {
                        richText.unload( richTextSelector );
                        updateColumnData('{{ data.id }}');
                    } );
                </script>
            </div>
        </script>

        <?php
    }

}

$feautres_field = Shortcake_Field_Columns::get_instance();

@kaoquan
Copy link

kaoquan commented Oct 13, 2017

@mwtsn
this is the key
wp.shortcake.hooks.addAction( 'shortcode-ui.render_destroy', function() {
richText.unload( richTextSelector );
updateColumnData('{{ data.id }}');
} );
it only updateds when you close the popup window.
so only one update and not on every key :)

@mattwatsoncodes
Copy link

Thank you very much @kaoquan this worked a treat :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants