WordPress has some amazing features and a pretty robust plug-in system that allows coders to extend it way beyond the base functionality. However the plug-in system is often poorly documented and is by no means complete.
This post is going to review some thoughts I’ve had while developing the Schedule Posts Calendar plugin.
The Schedule Posts Calendar plug-in has been an adventure in the frustrations of both WordPress and JavaScript.
The idea is pretty simple really, by default when WordPress wants the user to enter a date it presents a series of html controls as such:
This is ok, but if you are trying to schedule a series of posts and want to change the date from this Friday to Monday in three weeks, it’s kind of hard without having a calendar handy.
The idea behind the Schedule Posts Calendar plug-in was simply to replace the default WordPress controls with something better.
Version 1
Unfortunately WordPress does not have any hooks for replacing the default calendar controls so I knew I was going to have to do it through JavaScript. The first thing though was to find a calendar control, I found several but that was not the only consideration.
Many of the JavaScript calendar controls I found used the jQuery JavaScript library to do the bulk of the work for them, which was fine, but WordPress also uses jQuery extensively and virtually all of the calendar controls I found didn’t work within WordPress. After several tries, I found dhtmlxcalendar which doesn’t conflict with WordPress and had all the features I needed.
The first couple of versions of the plug-in focused on the post and page edit pages in WordPress, these pages have a publish time that uses the default WordPress controls and was the most common place I personally used them.
The first challenge here was simply getting my JavaScript to fire on the page load. WordPress has MANY JavaScripts, both core and from other plug-in’s, that fire on page load so simply using the classic onLoad hook in JavaScript simply failed as it was overwritten by other scripts.
I was fortunate enough to find a nice example of how to hook the onLoad even in JavaScript, but this is really an example of how broken JavaScript is from a design perspective. It has multiple ways to do just about everything and only half of them are supported by and given browser 🙁
The next trick was getting the calendar control inserted in to the page. This was actually a little easier than I thought it would be as WordPress has identified a lot of its page layout elements with id’s, including the calendar controls.
Once inserted the control updates the original WordPress controls each time the user clicks on a new date or time.
One interesting point about dhmtlxcalendar was that it has two JavaScript hooks for events on the control, one for onClick and the other for onChange. It turns out you have to capture both events as onClick is fired when the time is changed and onChange is fired when the date is changed (or visa versa, I don’t recall exactly which was which ;).
Version 2
Version 2 of the plug-in added two significant pieces of code, a pop-up calendar (instead of an inline one) and preferences support.
Both of these new features required a pile of JavaScript changes.
The pop-up support required a different control to be inserted in the page and along with the preferences required some way to configure what the user wanted.
Preferences would seem to be a reality easy task, however, JavaScript makes it a challenge as of course there’s no built in way to pass data between PHP and JavaScript. Instead you have to pass them as “parameters” to the script when you do the include line in PHP and then decode them again in the JavaScript.
And of course there’s no way to tell what script you are running in as everything is just on the page so you have to walk the entire list of JavaScript files to find the one you are looking for.
Version 3.0
The previous versions of the plug-in focused exclusively on the edit pages in WordPress, however there is another place where the calendar control is used and that is in the “Quick Edit” on the posts and pages lists.
Quick Edit presents an entirely different set of problems, namely that it’s implemented in JavaScript to start with so altering it would require JavaScript to be modifying JavaScript. While I belive it would be possible to do this, in principle I’m against it as it would likely be very brittle and any changes to the WordPress code could cause serious issues.
The most obvious solution would be to simply change the existing WordPress JavaScript code to include the calendar, however WordPress does not support any kind of update to core files through plug-ins (and I don’t blame them for that either). In this case I would not be able to use the WordPress plug-in repository to distribute, combined with having to re-install the plug-in after each core update, I decided against this option.
The next option I looked at was that WordPress does have a hook to add additional content to the Quick Edit menu. This seemed like a good idea, so while I would not be able to replace the existing calendar controls, I would be able to add new ones and hide the old ones. However, one of the “features” in WordPress is that to add items to the Quick Edit menu, you have to add columns to the posts/pages list.
Now I can see the logic here, you add a column to the list and then you need to add some additional items to the Quick Edit menu. However that is a pretty limited view of the functionality and it would make more sense for these hooks to be completely separate. As I didn’t have any requirement to add an additional column this option didn’t work for me either.
The final option (and the one I’ve gone with) was to leave Quick Edit alone and create a new “Schedule” option that behaved much like Quick Edit but was completely separate.
From a WordPress perspective this is the cleanest option as there are hooks to add the new menu item to both the posts and pages list. Likewise much of the code from the posts/pages JavaScript can be reused.
There are of course some new hurdles to overcome:
- Inserting new rows in to the posts/pages tables
- Deleting rows from the tables
- Updating the hidden values Quick Edit uses
- executing the update through AJAX
The insert/delete code for table rows was the second biggest single issue in the development of this code, messing with tables in JavaScript requires a lot of thought and careful planning. Once you get it working though, the code is pretty stable.
I mentioned earlier that WordPress does a pretty good job of using id’s to mark their pages up for easy reference later. However the Quick Edit mode is one exception I’ve found. WordPress uses some hidden div’s to store the time/date in for each post but does not add id’s to the div’s so you have to walk through them one by one until you find what you’re looking for.
So I knew I would be updating them again later, when I find them the first time I’ve added unique id’s to them. This may break things in a future version of WordPress, but I’ll gladly update the code if it does ;).
The biggest hurdle was the AJAX update, there were multiple issues here:
- jQuery conflict
- Required fields
- Inline edit
remember jQuery and how I said dhtmlxcalendar didn’t conflict with WordPress? Well apparently that was a lie ;). Pulling the AJAX code from the build in WordPress JavaScript file caused all kinds of issues, mostly around the use of the $ shortcut to jQuery.
Fixing this required using the noConflict version of jQuery, which looks a little ugly, but seems to work just fine.
The second issue was find out which fields were required to do an update, it turns out you have to include the post id as well as any fields you are updating.
The final issue was that WordPress checks some kind of unique value when receiving an AJAX request, which turns out is stored on the page in a div with “_inline_edit” as the ID.
Adding all of this together and submitting the AJAX request succeeds in updating WordPress.
As a final step, you have to update the hidden div’s that we tagged earlier with the new date/time info so if the user want to Quick Edit the entry after scheduling it, Quick Edit will have the right time/date.
Final Thoughts
WordPress
WordPress has an amazing array of options and extensibility, but you can still see some of the patchwork nature of it when you want to do things that are a little bit outside of the core.
JavaScript
JavaScript is a mess, it’s missing key functionality that should be built in but instead coders have to rebuild each time they write scripts.
Likewise support across browsers is weird and flaky, testing is key if you want anything to work.
jQuery
I hate this library with a passion, it seems to be everywhere but so poorly documented and breaks without any easy way to figure out why.
Honourable Mention: Opera Dragonfly
Schedule Posts Calendar would simply not have been possible without Opera Drafonfly (ok, it might have been possible, but it would have taken MUCH longer). The ability to actually see what is going on inside the browser as your code executes is awesome, it’s as close to a real IDE/debugger as is out there for JavaScript.