When you go to quick edit for a post, you will automatically see your custom taxonomies as editable fields:
But there’s a problem … I don’t want these to be text fields nor do I want them to be checkboxes. When it’s just you running a site, there’s less to worry about with regards to these things. You know what you’re adding, and if you typo, you blame yourself. At the same time, WordPress only has two options for these sorts of things: tags (freeform text) and categories (checkboxes).
Technically they’re settings for hierarchical, where false is text and true is checkboxes, and I’ve hidden the parent field (a topic for another post). But doing that makes them all check boxes, and I want to restrict people to one and only one checkbox. Except I don’t. The UX of having checkboxes vanish is pretty shitty, and it isn’t logical that you would only check one box.
Let me explain. In this example, which is practical, I have a taxonomy for human sexuality. I chose taxonomies and not post-meta because that would allow me to sort much more easily on data by groups. Simply, I can grab a list of all people who are flagged as ‘pansexual’ with one function and not have to reinvent the wheel.
That means I can use radio buttons or a dropdown. I feel a dropdown is a better, cleaner, UX, so that’s what I’m going to do. You can use the same logic here, though, so don’t worry.
After reading ShibaShake’s documentation on adding in quick edit values I winced. Adding it with quick_edit_custom_box
is super easy. The problem is that you have to use an incredibly weird amount of javascript to get the post ID and pass data back and forth. As weird and annoying as that was, it actually works. The example, of course, is comparing a CPT, where as I am using a custom taxonomy, so my own code was a little crazier.
Remove the taxonomy from Quick Edit
To do this starts out sounding like the stupidest idea ever, but you want to set show_in_quick_edit
to false
in your taxonomy. That does what it sounds like, removing the item from the quick edit page. Obviously now I have to add it back.
It’s important to note that if you don’t have any custom columns in your post list view, the rest of this won’t work. I do, and since part two of all this will be about being able to edit those custom columns, I don’t have to worry. If you do, here’s how you add a fake column… Ready? You add and remove the column. I know, I know, WP can be weird:
add_filter('manage_posts_columns', 'lezchars_add_fake_column', 10, 2); function lezchars_add_fake_column( $posts_columns, $post_type ) { $posts_columns['lez_fakeit'] = 'Fake Column (Invisible)'; return $posts_columns; } add_filter('manage_edit-post_columns', 'lezchars_remove_fake_column'); function remove_dummy_column( $posts_columns ) { unset($posts_columns['lez_fakeit']); return $posts_columns; }
Like I said, I know it’s weird.
Add the Quick Edit Box
Since I know I’m going to be building out a few more of these, and one is a cross-relational CPT to CPT drama, I’ve broken mine out into a switch/case basis.
// Add quick Edit boxes add_action('quick_edit_custom_box', 'lezchars_quick_edit_add', 10, 2); function lezchars_quick_edit_add($column_name, $post_type) { switch ( $column_name ) { case 'shows': // Multiselect - CPT where characters may have multiple break; case 'roletype': // Single Select - Custom Taxonomy break; case 'taxonomy-lez_sexuality': ?> <fieldset class="inline-edit-col-left"> <div class="inline-edit-col"> <span class="title">Sexual Orientation</span> <input type="hidden" name="lez_sexuality_noncename" id="lez_sexuality_noncename" value="" /> <?php $terms = get_terms( array( 'taxonomy' => 'lez_sexuality','hide_empty' => false ) ); ?> <select name='terms_lez_sexuality' id='terms_lez_sexuality'> <option class='lez_sexuality-option' value='0'>(Undefined)</option> <?php foreach ($terms as $term) { echo "<option class='lez_sexuality-option' value='{$term->name}'>{$term->name}</option>\n"; } ?> </select> </div> </fieldset> <?php break; } }
This is all pretty basic stuff. I’m simply making a form for a drop-down based on the contents of my taxonomy. If you want to make it radio buttons, do that.
Saving The Changes
Now we’re getting a little weirder. We need to save our changes, but only if it’s not an auto-save, and if it’s the correct post type (post_type_characters
for this page), and if the user can edit the page:
add_action('save_post', 'lezchars_quick_edit_save'); function lezchars_quick_edit_save($post_id) { // Criteria for not saving: Auto-saves, not post_type_characters, can't edit if ( ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) || ( 'post_type_characters' != $_POST['post_type'] ) || !current_user_can( 'edit_page', $post_id ) ) { return $post_id; } $post = get_post($post_id); // Lez Sexuality if ( isset($_POST['terms_lez_sexuality']) && ($post->post_type != 'revision') ) { $lez_sexuality_term = esc_attr($_POST['terms_lez_sexuality']); $term = term_exists( $lez_sexuality_term, 'lez_sexuality'); if ( $term !== 0 && $term !== null) { wp_set_object_terms( $post_id, $lez_sexuality_term, 'lez_sexuality' ); } } }
The two checks going on here are first to be sure it’s the right POST
action to save on, and then to only update if the term already exists. If you wanted to append terms instead of replace, you could add a ‘true’ param to wp_set_object_terms, however I want only set one sexuality per person in this case.
At this point, the code actually works!
Changing the current selection for the dropdown
There’s one problem though. If you’re working along with me this far, you’ll have noticed that the default selection is always ‘(Undefined)’ and that’s not what we want. The extension of this problem is we have to use bloody javascript to edit it. Damn it.
// Javascript to change 'defaults' add_action('admin_footer', 'lezchars_quick_edit_js'); function lezchars_quick_edit_js() { global $current_screen; if ( ($current_screen->id !== 'edit-post_type_characters') || ($current_screen->post_type !== 'post_type_characters') ) return; ?> <script type="text/javascript"> <!-- function set_inline_lez_sexuality( widgetSet, nonce ) { // revert Quick Edit menu so that it refreshes properly inlineEditPost.revert(); var widgetInput = document.getElementById('terms_lez_sexuality'); var nonceInput = document.getElementById('lez_sexuality_noncename'); nonceInput.value = nonce; // check option manually for (i = 0; i < widgetInput.options.length; i++) { if (widgetInput.options[i].value == widgetSet) { widgetInput.options[i].setAttribute("selected", "selected"); } else { widgetInput.options[i].removeAttribute("selected"); } } } //--> </script> <?php } // Calls the JS in the previous function add_filter('post_row_actions', 'lezchars_quick_edit_link', 10, 2); function lezchars_quick_edit_link($actions, $post) { global $current_screen; if (($current_screen->id != 'edit-post_type_characters') || ($current_screen->post_type != 'post_type_characters')) return $actions; $lez_nonce = wp_create_nonce( 'lez_sexuality_'.$post->ID); $lez_sex = wp_get_post_terms( $post->ID, 'lez_sexuality', array( 'fields' => 'all' ) ); $actions['inline hide-if-no-js'] = '<a href="#" class="editinline" title="'; $actions['inline hide-if-no-js'] .= esc_attr( __( 'Edit this item inline' ) ) . '" '; $actions['inline hide-if-no-js'] .= " onclick=\"set_inline_lez_sexuality('{$lez_sex[0]->name}', '{$lez_nonce}')\">"; $actions['inline hide-if-no-js'] .= __( 'Quick Edit' ); $actions['inline hide-if-no-js'] .= '</a>'; return $actions; }
Please don’t ask me to explain that. And yes, I know we should be using Unobtrusive Javascript and hooking into the DOM instead, but I don’t yet know how to do that.
I do know that if I wanted to add in multiple checks, one way is to duplicate the function set_inline_lez_sexuality( widgetSet, nonce )
and rename it to set_inline_lez_gender
and then extend the actions like this:
$actions['inline hide-if-no-js'] .= " onclick=\"set_inline_lez_sexuality('{$sex_terms[0]->name}', '{$sex_nonce}');set_inline_lez_gender('{$gender_terms[0]->name}', '{$gender_nonce}')\">";
There are more combinations and concatenations one can do here. Knock yourself out. It’s enough javascript for me today!
Comments
One response to “Customizing Taxonomies as Dropdowns in Quick Edit”
Bloody brilliant! Thanks a bunch for sharing this, Mika!