3

Is there a way to extend the Wordpress Customizer, in order to enable multiple selections?

This looks like what I want: https://github.com/lucatume/multi-image-control. I don't get it to work. It only shows add button and remove button but they don't do anything.

Is there another existing extension script that I can use?

2 Answers 2

7

What I eventually did was extending the WP_Customize_Control class as follows:

<?php

if (!class_exists('WP_Customize_Image_Control')) {
    return null;
}

class Multi_Image_Custom_Control extends WP_Customize_Control
{
    public function enqueue()
    {
      wp_enqueue_style('multi-image-style', get_template_directory_uri().'/css/multi-image.css');
      wp_enqueue_script('multi-image-script', get_template_directory_uri().'/js/multi-image.js', array( 'jquery' ), rand(), true);
    }

    public function render_content()
    { ?>
          <label>
            <span class='customize-control-title'>Image</span>
          </label>
          <div>
            <ul class='images'></ul>
          </div>
          <div class='actions'>
            <a class="button-secondary upload">Add</a>
          </div>

          <input class="wp-editor-area" id="images-input" type="hidden" <?php $this->link(); ?>>
      <?php
    }
}
?>

I use javascript to open the WP media selector when the user clicks on 'Add'. When an image is selected, the image must appear inside <ul class='images'></ul>. Furthermore the user needs to be able to remove an image by clicking on an image. I made the following javascript file:

( function( $ ) {

        $(window).load(function(){
            var begin_attachment_string = $("#images-input").val();
            var begin_attachment_array = begin_attachment_string.split(",");
            for(var i = 0; i < begin_attachment_array.length; i++){
                if(begin_attachment_array[i] != ""){
                    $(".images").append( "<li class='image-list'><img src='"+begin_attachment_array[i]+"'></li>" );
                }
            }
            $(".button-secondary.upload").click(function(){
                var custom_uploader = wp.media.frames.file_frame = wp.media({
                    multiple: true
                });

                custom_uploader.on('select', function() {
                    var selection = custom_uploader.state().get('selection');
                    var attachments = [];
                    selection.map( function( attachment ) {
                        attachment = attachment.toJSON();
                        $(".images").append( "<li class='image-list'><img src='"+attachment.url+"'></li>" );
                        attachments.push(attachment.url);
                        //
                     });
                     var attachment_string = attachments.join() + "," + $('#images-input').val();
                     $('#images-input').val(attachment_string).trigger('change');
                 });
                 custom_uploader.open();
             });

             $(".images").click(function(){
                 var img_src = $(event.target).find("img").attr('src');
                 $(event.target).closest("li").remove();
                 var attachment_string = $('#images-input').val();
                 attachment_string = attachment_string.replace(img_src+",", "");
                 $('#images-input').val(attachment_string).trigger('change');
             });
         });

} )( jQuery );

At last, I added some CSS:

.image-list{
  width: 100%;
  height: 150px;
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
  -webkit-box-shadow: inset 0 0 15px rgba(0,0,0,.1), inset 0 0 0 1px rgba(0,0,0,.05);
  box-shadow: inset 0 0 15px rgba(0,0,0,.1), inset 0 0 0 1px rgba(0,0,0,.05);
  background: #eee;
  cursor: pointer;
  vertical-align: middle;
  display:flex;
  justify-content:center;
  align-items:center;
  overflow: hidden;
  position: relative;
}
.image-list:before{
  content: '';
  position: absolute;
  display: none;
  top: 0px;
  right: 0px;
  left: 0px;
  bottom: 0px;
  box-shadow: inset 0 0 0 1px #fff, inset 0 0 0 5px #c60c31;
}
.image-list:hover:before{
  display: block;
}
2
  • Thanks for this solution @Tom Groot
    – bdalina
    Oct 27, 2019 at 11:07
  • For Firefox support, i've just had to replace the $(window).load with $(window).ready callback, otherwise the currently configured images won't show up May 24, 2021 at 19:50
0

@tom-groot this worked for me, but I tweaked it a few ways. This saves ids instead of the full url, removes the trailing comma, and avoids using "event" since it's deprecated.

Javascript:

  "use strict";
  $(window).load(function () {
    /*
    * Show photos on load
    */
    var begin_attachment_string = $("#images-input").val();
    var begin_attachment_array = begin_attachment_string.split(",");

    // get all attachments
    var promises = [];
    for (var i = 0; i < begin_attachment_array.length; i++) {
      var id = begin_attachment_array[i];
      if (id != "") {
        promises[i] = wp.media.attachment(id).fetch();
      }
    }
    // wait until they all finish since it's async
    Promise.all(promises)
    // add the images into the dom
    .then(function() {
      for (var i = 0; i < begin_attachment_array.length; i++) {
        var id = begin_attachment_array[i];
        if (begin_attachment_array[i] != "") {
          $(".images").append(
            "<li class='image-list'><img src='" +
              wp.media.attachment(id).get("url") +
              "' data-id='" +
              id +
              "'></li>"
          );
        }
      }
    })


    /*
    * Add Photos
    */
    $(".button-secondary.upload").click(function () {
      var custom_uploader = (wp.media.frames.file_frame = wp.media({
        multiple: true,
      }));

      custom_uploader.on("select", function () {
        var selection = custom_uploader.state().get("selection");
        var attachments = [];
        selection.map(function (attachment) {
          attachment = attachment.toJSON();
          $(".images").append(
            "<li class='image-list'><img src='" +
              attachment.url +
              "' data-id='" +
              attachment.id +
              "'></li>"
          );
          attachments.push(attachment.id);
        });
        var previous = $("#images-input").val() ? "," + $("#images-input").val() : ""; // get rid of trailing commas
        var attachment_string = attachments.join() + previous;
        $("#images-input").val(attachment_string).trigger("change");
      });
      custom_uploader.open();
    });


    /*
    * Remove images when you click on an image
    */
    $(".images").click(function (e) {
      var img_id = $(e.target).find("img").attr("data-id");
      $(e.target).closest("li").remove();
      var attachment_string = $("#images-input").val();
      attachment_string = attachment_string.replace(img_id, "");
      attachment_string = attachment_string.replaceAll(",,", ","); // get rid of duplicate commas
      attachment_string = attachment_string.replace(/^,+|,+$/g, ""); // get rid of leading or trailing commans
      $("#images-input").val(attachment_string).trigger("change");
    });
  });
})(jQuery);

The php to call it:


function register_customize_sections( $wp_customize ) {
 
    $wp_customize->add_section( 'image_selector_section', array(
       'title'=> __( 'Image Selector Section', 'TextDomain' ),
       'priority' => 201
    ) );

    $wp_customize->add_setting( 
        'multi_image_selector', 
        array(
            'default'   => array(),
            'transport' => 'refresh',
        ) 
    );

    $wp_customize->add_control( new Multi_Image_Custom_Control (
        $wp_customize,
        'multi_image_selector',
        array(
            'description' => 'Select One or Multiple Images',
            'section'  => 'image_selector_section',
        )
    ) );
}
add_action('customize_register', 'register_customize_sections');```


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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