This week’s post is something new. It’s new in two ways. First, rather than being a mostly text post, I made this first as a screencast. If that’s a speed and format you like, watch away. (You’ll probably need to watch at 720p or better resolution, ideally full screen. First time recording on the new computer made me forgetful about those issues.)
If not, read on. The other way this post is new is that I’m wanting to try out the idea of writing articles which take working code that serves a purpose and then explaining how it does that stuff. Reading code is a really useful practice, but one people rarely do. It’s also a really daunting task that most newer developers struggle with. So we’ll try at least a few of these and hope they’re useful. (Please weigh in via email, comment, etc if you have opinions on format.)
This week’s code reading is going to focus on a plugin I wrote: Require Featured Image. As you might be able to guess from the name, it requires that a post (or any other featured-image-supporting WordPress content type a user selects) has a featured image before it gets published. This is done by two different methods: there is JavaScript that checks for the image, and there is PHP that does too. This week, we’ll just be covering the JavaScript.
How the JavaScript Works
How the script file gets included isn’t especially interesting. What’s interesting about the Require Featured Image JavaScript is the parts that require the featured image. That’s mostly done with jQuery, because I still love that selector convenience and a few other things. The script is loaded on the editing screen when you’re on a post the plugin should enforce against.
Then, basically, it just does two things when it loads:
jQuery(document).ready(function($) { // functions are declared detectWarnFeaturedImage(); setInterval(detectWarnFeaturedImage, 800); });
What’s this? It’s a basic jQuery ready block for WordPress, with two calls to functions inside of it. The first is a bare call to the detectWarnFeaturedImage
function, which checks if the current post has a featured image and then warns if its image is inadequate. Missing from the name is the fact that the warning also disables the “Publish” button.
The second line, you may notice, is using the same function name detectWarnFeaturedImage
, but is passing it to a different function, setInterval
. This passing-a-function-to-a-function is the most essential idea of functional programming, but dwelling on that topic isn’t our goal. What you need to understand about this line is that setInterval
is just a native JavaScript function that lets you call a function at a specified interval. In this case, we’re going to re-call that same function every 800 thousandths of a second. So at page load, and then subsequently every 800 milliseconds the detectWarnFeaturedImage
function is called. What does that do?
Changing the Page If a Featured Image is Attached
The “detect/warn” function is pretty short:
function detectWarnFeaturedImage() { if (checkImageReturnWarningMessageOrEmpty()) { disablePublishAndWarn(checkImageReturnWarningMessageOrEmpty()); } else { clearWarningAndEnablePublish();
} }
What’s it do? Well if you can’t read the function names — they are quite verbose — it calls a function called checkImageReturnWarningMessageOrEmpty
which either returns an empty string if the post has a featured image (of adequate size), or it returns a bit of warning HTML. If that is an empty string a clearWarningAndEnable
publish function is called. If a warning is returned, that warning is passed to a disablePublishAndWarn
function which puts the warning message into the page and disables the publish button. The clearing/enabling and adding/disabling the button are pretty similar, so let’s just very quickly look at the removing function:
function clearWarningAndEnablePublish() {
$('#nofeature-message').remove();
$('#publish').removeAttr('disabled');
}
This removes an element with the ID of nofeature-message
(which the plugin creates elsewhere) and also removes the disabled
attribute from the default WordPress publish button, which helpfully has the publish
ID.
Checking on the Featured Image
We saw the checkImageReturnWarningMessageOrEmpty
function called earlier. Let’s look at it:
function checkImageReturnWarningMessageOrEmpty() {
var $img = $('#postimagediv').find('img');
if ($img.length === 0) {
return passedFromServer.jsWarningHtml;
}
if (passedImageIsTooSmall($img)) {
return passedFromServer.jsSmallHtml;
}
return '';
}
The function uses jQuery to seek for image elements in the #postimagediv
section of the page. This result is stored to $img
— unlike PHP, if dollar signs on variables are used at all in JavaScript they are typically used to signify that the variable is holding a jQuery element. That’s the case here.
If there is an image in the WordPress default “Featured Image” box, #postimagediv
, then $img
will have a length
(count of elements inside of it) greater than zero. If it is zero, then we know that there is no featured image set. That’s the first time this function exits, returning the value of passedFromServer.jsWarningHtml
if so. (passedFromServer
is a JavaScript global set up for the plugin by wp_localize_script
in PHP, which Fred explained in an article.)
If that check passed, we know that there is an image, and we instead need to know if the image is large enough. (Thanks to a pull request from cjk508, the plugin can require the image be at least, say, 800px tall and 900px wide.) This check is done in another function, passedImageIsTooSmall
which returns true or false based on the first image in $img
. If it’s false, then the final line return ''
is what exits the function, if not the value of passedFromServer.jsSmallHtml
is instead passed. This is, as you may guess, text that says that the image is too small and so the post can’t be published.
Checking the Featured Image’s Size
Actually checking the featured image’s size is a pretty cool little trick that cjk508 put together. Here’s the code:
function passedImageIsTooSmall($img) {
var input = $img[0].src;
var pathToImage = input.replace(/-\d+[Xx]\d+\./g, ".");
var featuredImage = new Image();
featuredImage.src = pathToImage;
return featuredImage.width < passedFromServer.width || featuredImage.height < passedFromServer.height;
}
There are two things you need to know to make this make sense: one is that the image WordPress places in the featured image box is typically a smaller-sized thumbnail. The other is that WordPress typically names such images in a style like: Image-Original-150x150.jpg
, where the original is just at Image-Original.jpg
. What is going on here is a hack to make sure we know the real size of the original image rather than the thumbnail. So we just use a regular expression and a call to replace to remove that -150x150
bit. (A full discussion of regular expressions is outside of the scope of this article, but understanding them is one of those little hard things that has lots of small useful applications.)
The script then takes that path to the full sized image, created a new Image element in the DOM to match it and compares the size of it to the sizes that are stored in the plugin that an image is supposed to have. If it’s smaller in either dimension, the function returns false
, it not it’ll be true
.
Now You Know How You Can Require a Featured Image
In the simplest terms, the JavaScript of the Require Featured Image plugin works by just checking the DOM for an image in the “Featured Image” box, and warning if it doesn’t match the criteria. But hopefully the exercise of seeing the code by which that is accomplished helps you understanding how you would solve a similar problem if it were put before you in the future. Happy hacking!
[…] Last time, we talked about how the Require Featured Image plugin stops a WordPress “post” from being published without a feature image attached. That approach is limited (as a few commenter pointed out) because users may disable JavaScript, and WordPress sometimes publishes posts at times other than when a user is clicking around the WordPress administration interface in a web browser. […]
[…] WPShout!: How To Stop a Post Publishing (Without a Featured Image) in WP with jQuery […]
[…] WPShout!: How To Stop a Post Publishing (Without a Featured Image) in WP with jQuery […]