Multiple images upload Theme Customizer control – 04

I’ve took my time to get in touch with jQuery, Backbone and the whole company and am pretty much satisfied by the job I’ve made on my multiple image theme customizer control; I’ve packed it into my libraries to increase its usability and the sometimes strange code is mainly due to that.

Queuing properly

Previous version of the control did print its CSS and JS components inline in the control markup. That’s easily removed using the WP_Customize_Control::enqueue method

<?php namespace tad\customizer\controls; use tad\utils\Script as Script; if (!class_exists('\WP_Customize_Control')) { return null; } class MultiImageControl extends \WP_Customize_Control { public $type = 'multi-image'; protected $inputId = ''; protected $thumbnailsId = ''; public function __construct($manager, $id, $args = array()) { parent::__construct($manager, $id, $args); $this->inputId = $this->type . '-control-' . $this->id; $this->thumbnailsId = $this->inputId . '-thumbnails'; } public function enqueue() { wp_enqueue_media(); $jsPath = TADLIBS_ASSETS_URL . '/js/multi-image.js'; wp_enqueue_script('mutli-image-control', Script::suffix($jsPath), array('jquery')); $cssPath = TADLIBS_ASSETS_URL . '/css/multi-image.css'; wp_enqueue_style('mutli-image-control', Script::suffix($cssPath)); } ... 

Some interactivity

The basic version of the previous script did save the images selected in the Media Uploader but did not show any changes until the whole Theme Customizer page was refreshed: I’ve updated the script to allow some more interactivity

/*global jQuery, document, wp, console*/ jQuery(document).ready(function($) { "use strict"; var file_frame, thumbnails; // clicking the upload button will open the media frame // and update the input field value jQuery('a.multi-images-upload').each(function() { var button = jQuery(this), inputId = button.data('store'); // clicking the upload button will open the media manager button.on('click', function(evt) { evt.preventDefault(); // file frame already created, return if (file_frame) { file_frame.open(); return; } // create the file frame file_frame = wp.media.frames.file_frame = wp.media({ title: jQuery(this).data('uploader_title'), button: jQuery(this).data('uploader_button_text'), multiple: true, library: { type: 'image' } }); // get the selected attachments when user confirms selection file_frame.on('select', function(evt) { var selected = file_frame.state().get('selection').toJSON(), store = jQuery(inputId), urls = []; for (var i = selected.length - 1; i >= 0; i--) { urls.push(selected[i].url); } // triggering change will activate the Save & Close button store.val(urls).trigger('change'); // update the thumbnails using the new images store.trigger('updateThumbnails', { urls: urls }); }); // open the file frame file_frame.open(); }); }); // remove all images when the remove images button is pressed jQuery('a.multi-images-remove').each(function() { var button = $(this), input = jQuery(button.data('store')); button.on('click', function(evt) { evt.preventDefault(); // update the hidden input value and save input.val('').trigger('change'); // also refresh the thumbnails list input.trigger('updateThumbnails', { urls: '' }); }); }); //update the images when the input value changes jQuery('input.multi-images-control-input').each(function() { var input = jQuery(this), thumbContainer = jQuery(input.data('thumbs-container')); input.on('updateThumbnails', function(evt, args) { var urls = args.urls; // remove old images thumbContainer.empty(); // for each image url in the value create and append an image element to the list for (var i = urls.length - 1; i >= 0; i--) { var li = $('<li/>'); li.attr('style', 'background-image:url(' + urls[i] + ');'); li.attr('class', 'thumbnail'); li.attr('data-src', urls[i]); thumbContainer.append(li); } }); }); }); 

I’ve used the data-something attribute extensively in the code to avoid convolute function parameters and the two MultiImageControl methods below will show

public function theButtons() { ?> <div> <input type="hidden" value="<?php echo $this->value(); ?>" <?php $this->link(); ?> id="<?php echo $this->inputId; ?>" data-thumbs-container="#<?php echo $this->thumbnailsId; ?>" class="multi-images-control-input"/> <a href="#" class="button-secondary multi-images-upload" data-store="#<?php echo $this->inputId; ?>"> <?php echo 'Upload'; ?> </a> <a href="#" class="button-secondary multi-images-remove" data-store="#<?php echo $this->inputId; ?>" data-thumbs-container="#<?php echo $this->thumbnailsId; ?>"> <?php echo 'Remove images'; ?> </a> </div> <?php } public function theUploadedImages($srcs = array()) { ?> <div class="customize-control-content"> <?php if (is_array($srcs)): ?> <ul class="thumbnails" data-store="#<?php echo $this->inputId; ?>" id="<?php echo $this->thumbnailsId; ?>"> <?php foreach ($srcs as $src): ?> <li class="thumbnail" style="background-image: url(<?php echo $src; ?>);" data-src="<?php echo $src; ?>"> </li> <?php endforeach; ?> </ul> <?php endif; ?> </div> <?php } 

I will make the list sortable next and make more UI adjustments to make the control, that might be used by uncaring users, as easy to use as possible.

Code on GitHub

Actual code is available online.

I appreciate your input