How to Add a Select Menu of Formidable Forms in Customizer

I recently had a need to list all the published Formidable forms as a select control in Customizer. Formidable doesn’t spell out how to get this list, but I eventually stumbled on this method.

$forms = FrmForm::get_published_forms();
$choices = array();
foreach ( $forms as $form ) {
$choices[$form->id] = $form->name;
}
// Formidable Forms Select Field
$wp_customize->add_setting(
'formidable_form_select',
array(
'capability' => 'edit_theme_options',
'default' => '',
'transport' => 'postMessage',
'type' => 'theme_mod'
)
);
$wp_customize->add_control(
'formidable_form_select',
array(
'active_callback' => '',
'choices' => $choices,
'description' => esc_html__( '', 'text-domain' ),
'label' => esc_html__( 'Formidable Forms Select', 'text-domain' ),
'priority' => 10,
'section' => 'your-section',
'settings' => 'formidable_form_select',
'type' => 'select'
)
);
$wp_customize->get_setting( 'formidable_form_select' )->transport = 'postMessage';

Brief explanation

Use the get_published_forms() static function in the FrmForm class from Formidable to get an array of public form objects.

Loop through them and add each to the $choices array, which is used for the choices in the Customizer select control.

This control will return the form ID. You could tweak this to use the form key or any other data from the form object.

How to Link to the Customizer

I recently needed to link to a custom panel in the Customizer and had to figure it out. Devin Price pointed me in the right direction, but I ended up looking in the WordPress core to see how they do it and this is how.

This a simple link to Customizer:

<a href="<?php echo esc_url( admin_url( 'customize.php' ) ); ?>">Link to Customizer</a>

Linking to Panels, Sections, and Controls in the Customizer

If you want to link to a specific panel in the Customizer, you’ll want to use this:

$query['autofocus[panel]'] = 'nav_menus';
 $panel_link = add_query_arg( $query, admin_url( 'customize.php' ) );
 ?><a href="<?php echo esc_url( $panel_link ); ?>">Link to Panel</a>

If you aren’t familiar with add_query_args, its worth reading up on it. I learned about it from Fränk Klein for how to properly add Google Fonts to WordPress. Pippin Williamson also has a good post about write-up about using add_query_args too. We’ll see later how you can use it to create more advanced links into the Customizer.

One warning: always specify the URL parameter and always escape the output. The core developers discussed this issue in April of 2015. If you don’t specify the URL and don’t escape the output of this function, then someone might be able to use it as a XSS attack vector. If you’ll notice, I’m including the esc_url() function in the output of each of the examples above and the URL parameter is specified too.

In the $query array, the key is tells the Customizer what to do, then the value tells it where we’re going. The this example: autofocus in a panel called “nav_menus”. You can change the value to the panel of your choice. Here’s a list of the default panels included in WordPress (as of version 4.5.2):

  • widgets = Widget panel
  • nav_menus = Menus panel

If you want to link to a section instead, you can change part of the key:

$query['autofocus[section]'] = 'title_tagline';
 $section_link = add_query_arg( $query, admin_url( 'customize.php' ) );
 ?><a href="<?php echo esc_url( $section_link ); ?>">Link to Section</a>

Here are the IDs for the default sections in WordPress:

  • static_front_page = Static Front Page section
  • title_tagline = Site Identity section

Some of the default themes like Twenty Sixteen add their own sections and any theme can add the following sections by declaring theme support for them:

  • background_image = Background Image section
  • header_image = Header Image section

The real magic is linking to the customizer and autofocusing on a specific field (aka control):

$query['autofocus[control]'] = 'blogname';
 $control_link = add_query_arg( $query, admin_url( 'customize.php' ) );
 ?><a href="<?php echo esc_url( $control_link ); ?>">Link to Control</a>

This links to the Site Title field in the Site Identity section. If you’re asking people to go to a specific place and make an edit, go ahead and link this way to make it easier.

After the Customizer

In addition to linking to somewhere within the Customizer, you can also specify where to go after you exit. Core uses the page you’re currently on by default. You can check the link to the Customizer from different places in the admin and see that return value changes.

$query['return'] = admin_url();
 $link_with_return = add_query_arg( $query, admin_url( 'customize.php' ) );

That will link to the Customizer and return you to the Dashboard.

FYI, you cannot specify any old URL to go to afterwards. For instance, this does not work:

$query['return'] = 'http://www.cnn.com';
 $link = add_query_arg( $query, admin_url( 'customize.php' ) );
 ?><a href="<?php echo esc_url( $link ); ?>">Go to CNN after</a>

The Customizer runs these return URLs through the function wp_validate_redirect(). By default, the only allowed URL is the home_url(). Additional URLs can be added using the allowed_redirect_hosts() filter. The wp_validate_redirect() function is used for many parts of WordPress, so I’d advise caution when adding URLs to this allowed list.

Now, we can build more specific URLs for the Customizer. This could be especially useful if you’re walking a site admin through performing several steps:

$query['autofocus[control]'] = 'blogname';
 $query['return'] = admin_url( 'post-new.php' );
 $link = add_query_arg( $query, admin_url( 'customize.php' ) );
 ?><a href="<?php echo esc_url( $link ); ?>">Set title, then write post</a>

This links into the Customizer, autofocuses on the Site Title field, then once you’re done, takes you to the new post page.

Set the Preview Page

If you have Customizer controls that only apply to specific pages, you can specify which page appears in the previewer:

$query['url'] = site_url( '/news' );
 $link = add_query_arg( $query, admin_url( 'customize.php' ) );
 ?><a href="<?php echo esc_url( $link ); ?>">News Page in Preview</a>

In this case, the Previewer will display the News page instead of the home page. I’m planning to do additional testing to see if this could be used to style a plugin-specific page.

All Together Now!

Those are all the parameters currently available for the Customizer. Now you can get really crazy (and specific) about your links to the Customizer. For example, go to the Menu Locations, show the About page in the previewer, then when you’re done, add a new page:

$query['autofocus[section]'] = 'menu_locations';
 $query['return'] = admin_url( 'post-new.php?post_type=page' );
 $query['url'] = site_url( '/about-us' );
 $link = add_query_arg( $query, admin_url( 'customize.php' ) );
 ?><a href="<?php echo esc_url( $link ); ?>">Craziness!</a>

To wrap up, there are three parameters you can use to link into the customizer: return, url, and autofocus. Use add_query_arg to build the URL and esc_url to display it. You can use the autofocus parameter to focus on a panel, a section, or a specific field. You can use the url parameter to display a specific page in the Previewer. You can use the return parameter to go to a particular place after going to the Customizer. Happy linking!

Here’s a gist of all the code, if you prefer that.

How to Change the Featured Image Labels

When creating a site for a client or creating a plugin, I’ve found its helpful to customize things as much as possible to the intended usage. This is especially important for client work since most clients have an internal language, or terminology they use for things. In the case of Featured Images, the site or plugin might be using the featured image differently than how one might use it on a news or blog post.

I’m currently writing a plugin with a custom post type and using the featured image as a headshot for an employee. While “featured image” may work fine, “headshot” is more specific and makes more sense in this context. I haven’t been able to find anything recent about how to change the labels on the existing Featured Image metabox. The most commonly referenced code only works some of the time. Specifically, when one removes a featured image, the label for the link changes back to referencing “featured image” instead of the customized label.

I dug through the core and found the post_type_labels_{$post_type} filter, which was added in version 3.5. This filter makes customizing the featured image labels super easy:

/**
* Changes strings referencing Featured Images for a post type
*
* In this example, the post type in the filter name is "employee"
* and the new reference in the labels is "headshot".
*
* @see https://developer.wordpress.org/reference/hooks/post_type_labels_post_type/
*
* @param object $labels Current post type labels
* @return object Modified post type labels
*/
function change_featured_image_labels( $labels ) {
$labels->featured_image = 'Headshot';
$labels->set_featured_image = 'Set headshot';
$labels->remove_featured_image = 'Remove headshot';
$labels->use_featured_image = 'Use as headshot';
return $labels;
} // change_featured_image_labels()
add_filter( 'post_type_labels_employee', 'change_featured_image_labels', 10, 1 );
view raw gistfile1.txt hosted with ❤ by GitHub

The labels are in an object and we then reset the values of each specific item to what we want. Then return the object.

Avoiding get_theme_mod Errors

If you’re getting an error related to get_theme_mod, its most likely from how you’re checking if the returned result is empty. Most developers will probably do the same thing I did: make a variable and assign it to the result of get_theme_mod. Then check if its empty using PHP’s empty() method. Sadly, this is where you’re getting an error. Instead, check if the result is equal to ”, or blank.

/**
* Do this
*/
if ( '' == get_theme_mod( 'something' ) ) { ... }
/**
* Not this
*/
if ( empty( get_theme_mod( 'something' ) ) ) { ... }

Inline SVG the Sane Way

Like everyone else these days, I’ve totally jumped onboard the SVG train. They’re scalable and easy to use. If you use inline SVG, they are style-able and reduce server requests, which can help your SEO.

Sadly, inline SVG also borks up your code. There’s nothing more disappointing than combing through neatly organized code thats completely marred by a giant block of inline SVG gibberish in the middle of it.

Recently, I discovered a simple way to have my cake and eat it too (mmm, cake!). Check this out:

https://gist.github.com/slushman/4c1295adc18a98678b05

Simple, right? The function has one parameter that determines which SVG is returned. While this one function may look out of control (although in my editor, each SVG is on one looooooong line, so it still remains neat and tidy), the SVGs and their craziness are contained to one place in your code.

This still gives you all the advantages of inline SVG, without borking up your nicely indented, organized code. In my next post, I’ll show how combining this with some other simple functions can give you inline SVGs in menu items!

As a footnote, the $output being initiated and returned outside the switch means there’s a fallback. If the requested icon isn’t in the switch, nothing is returned. You could do that with a “default” statement within the switch, but I’ve also found being able to append the $output variable is more dummy-proof that other methods.

Adding a Custom Class to a Submit Button

While you can hand-code the HTML for a submit button in a form, WordPress has a nice function, submit_button(), that can drop in the correct code for you.

For a recent project, I wanted to restyle some buttons to make them look like links, like on the posts page, rather than buttons. While you don’t NEED an special class to pull this off, it certainly makes it easier and neater in the CSS. I thought this would be achievable in the $other_attributes, but the $type parameter accepts any string, not just the WordPress defaults.

Basically, whatever you put there will be added to the class attribute of the button and you’re good to restyle the button however you want using your custom class.

/**
* Default WordPress submit() parameters
*
* @param string $text changes the text on the button
* @param string $type determines the style of the button. WordPress styling options:
* primary - the default
* secondary
* delete
* custom - add your custom class for styling here!
* @param string $name sets the name attribute for the button, its "Submit" by default.
* @param string $wrap determines if the button is wrapped in paragraphs tags or not, the default is true.
* @param array $other_attributes sets other attributes for the button.
*/
submit_button( 'Whatever Text', 'my-custom-class' );
view raw wp-submit-button hosted with ❤ by GitHub

How to Add a Class to a Metabox

While developing a new plugin, I had needed to show/hide some metaboxes based on which radio button is selected from another metabox. Fortunately, I found this method and wanted to share my findings. You can see this method at the top of the gist below.

The add_filter() statement works like this: the {post_type_name} is exactly that, the name of your post type. In my plugin, it would be “slushman_portfolio”, but if you’re doing this with the built-in WordPress posts, it would “posts”. The {metabox_id} is the id attribute of the metabox for which you want to apply the filter.

The add_metabox_classes() function grabs the $classes array and adds your additional class to the end, then returns the array. When the metabox gets created, the $classes array contains all the classes that are put into the class attribute.

Now, you’re all finished. The class you want to add to your metabox is added. I’ll write another tutorial on how to use jQuery to show or hide that metabox based on the value of the radio buttons.

EDIT (4/7/2014):

I’ve recently updated this method in four ways to make it simpler and easier. First of all, the $classes parameter passed in from WordPress is an array, so make sure the parameter itself is optional by assigning it as a blank array if its empty. Second, create an array of the class or classes you’d like to add. Third, check the existing $classes array to make sure you don’t add a class that’s already in there. Fourth, instead of using the array_push function, just assign it to the next place in the $classes array using the brackets after the variable.

/**
* The simplistic way to add a custom class to a specific metabox
*
* @param array $classes The current classes on the metabox
* @return array The modified classes on the metabox
*/
function add_metabox_classes( $classes = array() ) {
return array_push( $classes, sanitize_html_class( 'my-custom-class' ) );
} // add_metabox_classes()
/**
* {post_type_name} The name of the post type
* {metabox_id} The ID attribute of the metabox
*/
add_filter( 'postbox_classes_{post_type_name}_{metabox_id}, 'add_metabox_classes' );
/**
* The more thorough way to add a custom class to a specific metabox
*
* Uses the same add_filter call, but its easier to add additional classes
* and it checks if new class is already there.
*
* @param array $classes The current classes on the metabox
* @return array The modified classes on the metabox
*/
function add_class( $classes = array() ) {
$add_classes = array( 'new_class1', 'new_class2' );
foreach ( $add_classes as $class ) {
if ( ! in_array( $class, $classes ) ) {
$classes[] = sanitize_html_class( $class );
}
} // End of foreach loop
return $classes;
} // add_class()

 

 

How to Add the jQuery UI Datepicker to a Plugin

Updated – 4/14/2015

I’ve since learned a better way to do this. It essentially does the same thing, the same way, but using better WordPress practices. Use the code in this gist instead of what’s below:

/**
* Adds the datepicker settings to the admin footer.
* Only loads on the plugin-name settings page
*/
function admin_footer() {
$screen = get_current_screen();
if ( $screen->id == 'settings_page_plugin-name' ) {
?><script type="text/javascript">
jQuery(document).ready(function(){
jQuery('.datepicker').datepicker({
dateFormat : 'D, m/d/yy'
});
});
</script><?php
}
} // admin_footer()
add_action( 'admin_print_scripts', array( $this, 'admin_footer' ), 1000 );
/**
* Enqueues the built-in Datepicker script
* Only loads on the plugin-name settings page
*/
function enqueue_scripts( $hook_suffix ) {
$screen = get_current_screen();
if ( $screen->id == $hook_suffix ) {
wp_enqueue_script( 'jquery-ui-datepicker' );
}
} // enqueue_scripts()
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
/**
* Enqueues a Datepicker theme
* Only loads on the plugin-name settings page
*/
function enqueue_styles( $hook_suffix ) {
$screen = get_current_screen();
if ( $screen->id == $hook_suffix ) {
wp_enqueue_style( 'jquery.ui.theme', plugin_dir_url( __FILE__ ) . '/css/datepicker.css' ), array( 'jquery-ui-core', 'jquery-ui-datepicker' ), $this->version, 'all' );
}
} // enqueue_styles()
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_styles' ) );

 

datepicker-head

I recently decided to dive into jQuery and figure out how to add a Datepicker to the Seminar system plugin I’m building for the Curb College at Belmont.  Thankfully, I didn’t need to write one from scratch because jQuery UI already makes a great Datepicker and including it in a plugin is super easy.  While I owe a great deal to Zigpress’s great tutorial, the instructions are unfortunately outdated, so I’m going to update them here.

If you’re using WordPress 3.3 or higher, then the jQuery UI Datepicker is already included, otherwise you should update your WordPress install or include the files.  In either case, you will need to include a theme for the Datepicker and add a few lines of code.  FYI, all the following code samples are written within a class, which you should be doing in your plugin, but feel free to adapt as necessary.  First thing, in your __construct() function, you’ll need to add a few lines that tells the plugin to reference a function that will include the jQuery references.

Add Actions

// Add jQuery calender
add_action( 'admin_print_scripts-post.php', array( $this, 'seminar_scripts' ), 1000 );
add_action( 'admin_print_scripts-post-new.php', array( $this, 'seminar_scripts' ), 1000 );
add_action( 'admin_footer', array( $this, 'admin_footer' ) );

In my plugin, I’m using the Datepicker for a meta box on the custom post type pages in the admin area, so I’m using the actions admin_print_scripts-post.php and admin_print_scripts-post-new.php and they both call the ‘seminar_scripts’ function.  I also have the admin_footer action call the admin_footer function.  Calling the Datepicker only on the required admin pages lowers the overhead for loading the Admin pages, keeping things as small as possible without sacrificing functionality.

Enqueue the Script and Theme

Now we have to functions to define two functions: seminar_scripts() and admin_footer().

function seminar_scripts() {
   global $post_type;
   if( 'cemb_seminar' != $post_type ) { return; }
   wp_enqueue_script( 'jquery-ui-datepicker' );
   wp_enqueue_style( 'jquery.ui.theme', plugins_url( '/css/jquery-ui-1.8.17.custom.css', __FILE__ ) );
} // End of seminar_scripts()

Seminar_scripts() starts by checking what post type you’re looking at.  If it’s not cemb_seminar (my custom post type – be sure to change this to match your plugin), then stop.  If it is cemb_seminar, then enqueue the Datepicker and it’s theme.  If you use a different folder structure for your plugin, you’ll need to change the plugins_url() line to match your structure.

jqui-theme

For now (2/23/2012), you will need to include a theme for your Datepicker.  WordPress doesn’t include a theme for the Datepicker, but that should be resolved in a coming update.  To get a theme, go to the jQuery UI ThemeRoller, select the Gallery tab on the right sidebar, and choose your theme.  I’m using Smoothness because I think it most closely matches the WordPress Admin UI.

jqui-download

Clicking the Download button under a theme will take you to a page where you can select options for your jQuery UI download.  Select your theme from the Theme drop menu, select the stable version, and click the Download button.

zip-folder

When it finishes downloading, unzip the file and go to the css > smoothness folder.  In my plugin, I’ve got a CSS folder.  Drag the jqery-ui-1.8.17.custom.css file and images folder from the zip file into your plugin’s css folder (or wherever you pointed the plugins_url() line in the enqueue statement in seminar_scripts()).

Add the jQuery Script

function admin_footer() { ?>
   <script type="text/javascript">
      jQuery(document).ready(function(){
         jQuery('.seminar_date').datepicker({
            dateFormat : 'D, m/d/yy'
         });
      });
   </script><?php
} // End of admin_footer()

Admin_footer() includes the actual jQuery statement to make things happen on the page in the footer of your admin page.  There are two things here you will need to customize for your plugin: the selector and the date format.  jQuery works by looking at the page and finding a part of the page – aka the selector – and performing the script.  My selector is the CSS class (.seminar_date) for the date field in the meta box.  You’ll need to modify that to match the CSS class (or ID) for your date field.  The date format is just how the date is printed on the page.  For my plugin, I choose a format like: Mon 2/22/2012.  You can see all the options on this page.

That’s it!  Once you’ve added all that code and uploaded the jQuery UI theme, test it out and see the Datepicker appear when you click in the field you selected in the selector.

How to Set Dashboard to Use One Column

I’m working on a plugin where I need the Dashboard to have one column for all users. While I could log into every user and change their Screen Options to one column, it would take next to forever with thousands of students accessing this site. Thankfully, I found this bit of code on Stackexchange (thanks sorich87!) and modified it for the Dashboard page. This will force all users to have one column on the Dashboard.

function screen_layout_columns( $columns ) {
$columns['dashboard'] = 1;
return $columns;
}
add_filter( 'screen_layout_columns', 'screen_layout_columns' );
function screen_layout_dashboard() {
return 1;
}
add_filter( 'get_user_option_screen_layout_dashboard', 'screen_layout_dashboard' );
view raw one-column-dashboard hosted with ❤ by GitHub