Enqueue scripts & styles responsibly

So you have a fancy plugin that’s doing something awesome on a WordPress admin page. The plugin needs some CSS and/or JS to work so you enqueue them in the admin_enqueue_scripts hook. All good™. Hmm, not really. What you did is correct, but not very responsible. The fact is, I rarely see plugins that do their stuff on all admin pages, so why enqueue the scripts and/or styles everywhere?

Here’s a simple trick to make a plugin enqueue its scripts & styles only on certain admin pages.

Let’s say we have a plugin that enhances the new and edit post screens:

/**
 * Enqueue admin script on new and edit post screens.
 */
function myplugin_enqueue_admin_scripts() {
	wp_enqueue_script(
		'myplugin-admin-script',
		plugin_dir_url( __FILE__ ) . 'script.js',
		array( 'jquery' ),
		'0.1.0',
		true
	);
}

add_action( 'load-post.php', 'myplugin_enqueue_admin_scripts' );
add_action( 'load-post-new.php', 'myplugin_enqueue_admin_scripts' );

Notice that we’re not using the admin_enqueue_scripts hook? That’s the trick! Instead, we’re using the load-(page) hook so that our script will only load on those pages.

Further Reading

Standard

Get menu items as multidimensional array

There are times when we need to get menu items as a big multidimensional array so we can do some processing before finally displaying them. We can’t simply use wp_get_nav_menu_items() because it returns a flat array. The solution for this is pretty simple: use a custom walker.

/**
 * Nav menu walker
 */
class Bridge_Walker_Nav_Menu extends Walker_Nav_Menu {

	/**
	 * Prepare item
	 *
	 * @param  object $item  Menu Item.
	 * @param  array  $args  Arguments passed to walk().
	 * @param  int    $depth Item's depth.
	 * @return array
	 */
	protected function prepare_item( $item, $args, $depth ) {
		$title   = apply_filters( 'the_title', $item->title, $item->ID );
		$title   = apply_filters( 'nav_menu_item_title', $title, $item, $args, $depth );
		$classes = apply_filters( 'nav_menu_css_class', array_filter( $item->classes ), $item, $args, $depth );

		return array(
			'id'          => absint( $item->ID ),
			'order'       => (int) $item->menu_order,
			'parent'      => absint( $item->menu_item_parent ),
			'title'       => $title,
			'url'         => $item->url,
			'attr'        => $item->attr_title,
			'target'      => $item->target,
			'classes'     => $classes,
			'xfn'         => $item->xfn,
			'description' => $item->description,
			'object_id'   => absint( $item->object_id ),
			'object'      => $item->object,
			'type'        => $item->type,
			'type_label'  => $item->type_label,
			'children'    => array(),
		);
	}


	/**
	 * Traverse elements to create list from elements.
	 *
	 * This method should not be called directly, use the walk() method instead.
	 *
	 * @param object $element           Data object.
	 * @param array  $children_elements List of elements to continue traversing.
	 * @param int    $max_depth         Max depth to traverse.
	 * @param int    $depth             Depth of current element.
	 * @param array  $args              An array of arguments.
	 * @param array  $output            Passed by reference. Used to append additional content.
	 */
	public function display_element( $element, &$children_elements, $max_depth, $depth, $args, &$output ) {
		if ( ! $element ) {
			return;
		}

		if ( ! is_array( $output ) ) {
			$output = array();
		}

		$id_field = $this->db_fields['id'];
		$id       = $element->$id_field;
		$item     = $this->prepare_item( $element, $args, $depth );

		if ( ! empty( $children_elements[ $id ] ) ) {
			foreach ( $children_elements[ $id ] as $child ) {
				$this->display_element(
					$child,
					$children_elements,
					1,
					( $depth + 1 ),
					$args,
					$item['children']
				);
			}

			unset( $children_elements[ $id ] );
		}

		$output[] = $item;
	}
}

Example Usage:

$menu_id   = 2;
$max_depth = 0; // All level.
$walker    = new Bridge_Walker_Nav_Menu;
$items     = $walker->walk( wp_get_nav_menu_items( $menu_id ), $max_depth );
Standard

Rambutan, bukan orangutan

All photos in this gallery are released under GPL v2. Attribution would be greatly appreciated.

Gallery

20150121

All photos in this gallery are released under GPL v2. Attribution would be greatly appreciated.

Gallery

Conditionally disable Jetpack’s Infinite Scroll

So you implemented Jetpack’s Infinite Scroll feature in your theme, but you don’t want it in a particular page, say a category archive page. Here’s the code you need to add to your theme’s functions.php file:

/**
 * Disable Jetpack's Infinite Scroll Conditionally
 *
 */
function _kucrut_disable_jetpack_infinite_scroll_conditionally() {
	if ( true === my_conditionals() ) {
		remove_theme_support( 'infinite-scroll' );
	}
}
add_action( 'template_redirect', '_kucrut_disable_jetpack_infinite_scroll_conditionally', 9 );

Just remember to change my_conditionals() with your actual conditionals and to never add the action callback after priority 9, otherwise it will be too late 😉

Standard