Replacing select2 in admin backend for all selects

I originally posted this question as a javascript question here, but think maybe it would be better asked here. I tried adding select2 to all wordpress admin screens. However, since many selects are created dynamically, I needed to find a way to recognize the dynamic selects. I got it working, but the dynamic selects do not load with the right width and positioning. Take for example the http://example.com/wp-admin/edit.php page. When clicking quick edit, select2 does not find the correct width and positioning of the new selects. If you look at the source, you can see that the dropdown with the following style attributes:

style="width:0; top:0; left:0; 

Because of this, it doesn’t show when you click on it. However, if you click on a new select and then click again right below it, it updates the styles, but now moves the select2 overlay just to the right of the selects.

Here is an example plugin if anyone wants to test it followed by some screenshots:

<?php

/**
 * Plugin Name: Admin Select2 Not Working Everywhere
 * Plugin URI: 
 * Description: Adds select2 to all admin screens
 * Version: 1.0
 * Author: Bryan Willis
 * Author URI: 
 * License: GPL2
 */

function enqueue_select2_jquery() {
    wp_register_style( 'select2css', 'http://cdnjs.cloudflare.com/ajax/libs/select2/3.4.8/select2.css', false, '1.0', 'all' );
    wp_register_script( 'select2', 'http://cdnjs.cloudflare.com/ajax/libs/select2/3.4.8/select2.js', array( 'jquery' ), '1.0', true );
    wp_enqueue_style( 'select2css' );
    wp_enqueue_script( 'select2' );
    }
add_action( 'admin_enqueue_scripts', 'enqueue_select2_jquery' );

function select2jquery_inline() {
    ?>
<style type="text/css">
.select2-container {margin: 0 2px 0 2px;}
.tablenav.top #doaction, #doaction2, #post-query-submit {margin: 0px 4px 0 4px;}
</style>        
<script type="text/javascript">
jQuery(document).ready(function ($) {
   $("select").select2(); 
   $( document.body ).on( "click", function() {
        $("select").select2(); 
     });
});
</script>   
    <?php
 }
add_action( 'admin_head', 'select2jquery_inline' ); 

enter image description here

enter image description here

enter image description here

enter image description here

1 Answer
1

The trouble is to do with how quick edit works – WordPress uses a hidden <div /> to generate the form, which will have already had select2 applied (and thusly, the positions already calculated).

Your click event listener on the body won’t fire when you need it, since the core event handler for quick edit returns false, stopping any event propagation. Instead, you can sneakily listen to the focus event for the title input, which is fired once the quick edit form is rendered:

jQuery( document ).ready(
    function( $ ) {
        $( "select:visible" ).select2(); // Only fire on visible inputs to begin with.
        $( document.body ).on( "focus", ".ptitle,select",
            function ( ev ) {
                if ( ev.target.nodeName === "SELECT" ) {
                    // Fire for this element only
                    $( this ).select2({ width: "element" });
                } else {
                    // Fire again, but only for selects that haven't yet been select2'd
                    $( "select:visible" ).not( ".select2-offscreen" ).select2({
                        width: "element"
                    });
                }
            }
        );
    }
);

You’ll see I’ve also added the width: "element" argument. This means select2 will calculate an appropriate width based on the length of the options. Without it, select2 is far too narrow for some of the options, particularly “Page Parent” with long page titles.

This solution will specifically solve your issue with quick edit, but you’ll probably need to implement additional “fixes” for other dynamic situations, particularly if you want to play nice with plugins like Advanced Custom Fields.

Leave a Comment