In my earlier post I’ve added a very basic control to the Theme Customizer.
It’s time to actually make that multiple image selector take care of those selected images.
The link function
I’ve spent quite some time trying to figure out how the Theme Customizer will actually know I’ve set some values and will save and restore them: the magic (I mean it) is Backbone-driven and the way it works is actually quite simple. Once I understood it.
The current control method flow starts from here
public function render_content()
{
// get the set values if any
$imageSrcs = explode(',', $this->value());
if (!is_array($imageSrcs)) {
$imageSrcs = array();
}
$this->theTitle();
$this->theButtons();
$this->theUploadedImages($imageSrcs);
}
and, sparing the theTitle
method which is trivial in its markup, the theButtons
methods reads like
public function theButtons()
{
?>
<div>
<input type="hidden" value="<?php echo $this->value(); ?>" <?php $this->link(); ?>/>
<a href="#" class="button-secondary multi-images-upload">
<?php echo 'Upload'; ?>
</a>
<a href="#" class="button-secondary multi-images-remove">
<?php echo 'Remove images'; ?>
</a>
</div>
<?php
}
aside for the evil thing that is that much mixing of PHP
and HTML
the method contains the first component that will allow a user to select multiple images: the hidden input
field will, in fact, store the comma separated urls the media manager will provide.
The $this->link()
method call will output markup like
<input type="hidden" value="" data-customize-setting-link="some_plugin[some_setting]">
and that’s what will make the current value
be saved to the database under the some_plugin
option in the database. The option will be an array and some_setting
will be one of its keys.
Calling the media manager
Via evil ways I will print the following JavaScript code to the page
jQuery(document).ready(function($) {
"use strict";
var file_frame;
// bind to click event for each upload button on the page
jQuery('.multi-images-upload').live('click',
function(event) {
event.preventDefault();
// file frame already created, return
if (file_frame) {
file_frame.open();
return;
}
var root = $(this).parent();
// 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
file_frame.on('select', function() {
var selected = file_frame.state().get('selection').toJSON(),
urls = [];
// store each image url in an hidden text field
for (var i = selected.length - 1; i >= 0; i--) {
var url = selected[i].url;
urls.push(url);
}
// get the input field that will store the image sources
var store = root.find('input[type=hidden]');
// store the new values and trigger a change
store.val(urls).trigger('change');
});
// open the just created file frame
file_frame.open();
});
});
Which is a blatant copy of the scripts found in Mike Jolley article save for the part where the selected images urls are saved in the hidden input
field value
attribute and trigger the save action that will turn the Save $ Publish
button on and actually save the selected urls in a comma-separated list in the database.
Show those images
I’ve gone further and the MultiImageControl::theUploadedImages
will take care, via evil inline style
, of showing the selected images on the page
public function theUploadedImages($srcs = array())
{
$imageStyle = array('width:25%', 'height:auto;', 'padding:2px', 'box-sizing:border-box', 'float:left');
?>
<div class="customize-control-content">
<div class="thumbnails">
<?php if (is_array($srcs)): ?>
<?php foreach ($srcs as $src): ?>
<img src="<?php echo $src; ?>" style="<?php echo implode(';', $imageStyle) . ';'; ?>" alt="the imag">
<?php endforeach; ?>
<?php endif; ?>
</div>
</div>
<?php
}
This is the current output [caption id=“attachment_768” align=“aligncenter” width=“603”] Not very nice. The cats.[/caption]
What’s badly missing and I will implement next
Right now the control responsiveness is very 90’s meaning that once the theme user has selected some images he will need to actually reload the whole Theme Customizer, hence re-fire the PHP part of it, to see the new images in place.
I will implement the control responsiveness next to make it at least enter the 2000’s.