Half-Elf on Tech

Thoughts From a Professional Lesbian

Author: Ipstenu (Mika Epstein)

  • Show Feedback in “Right Now”

    Show Feedback in “Right Now”

    The “Right Now” section of the WordPress dashboard is a great way to get an overview of the goings on of your site. But it doesn’t quite list everything. What if you could add things like ‘messages’ to the the “At a Glance” section like this:

    The "At a Glance" section, with messages added in.

    Guess what? You can!

    The Code

    Presmuing you’re using Jetpack’s contact form module, you automatically get a new kind of post called ‘Feedback.’ In order to make it display it’s count in “At a Glance,” there are two parts. First we add the CSS, which does the styling. Then we add the PHP that counts and displays the number of posts in feedback.

    add_action( 'dashboard_glance_items', 'helf_dashboard_glance' );
    add_action( 'admin_head', 'helf_dashboard_glance_css' );
    
    /*
     * Show Feedback in "Right Now"
     */
    function helf_dashboard_glance() {
    	if ( class_exists( 'Jetpack' ) && Jetpack::is_module_active( 'contact-form' ) ) {
    		foreach ( array( 'feedback' ) as $post_type ) {
    			$num_posts   = wp_count_posts( $post_type );
    			$count_posts = ( isset( $num_posts->publish ) ) ? $num_posts->publish : '0';
    			if ( 0 !== $count_posts ) {
    				if ( 'feedback' === $post_type ) {
    					// translators: %s is the number of messages
    					$text = _n( '%s Message', '%s Messages', $count_posts );
    				}
    				$text = sprintf( $text, number_format_i18n( $count_posts ) );
    				printf( '<li class="%1$s-count"><a href="edit.php?post_type=%1$s">%2$s</a></li>', esc_attr( $post_type ), wp_kses_post( $text ) );
    			}
    		}
    	}
    }
    
    /*
     * Custom Icon for Feedback in "Right Now"
     */
    function helf_dashboard_glance_css() {
    	if ( class_exists( 'Jetpack' ) && Jetpack::is_module_active( 'contact-form' ) ) {
    		?>
    		<style type='text/css'>
    			#adminmenu #menu-posts-feedback div.wp-menu-image:before, #dashboard_right_now li.feedback-count a:before {
    				content: '\f466';
    				margin-left: -1px;
    			}
    		</style>
    		<?php
    	}
    }
  • Selective DeGutenberging

    Selective DeGutenberging

    Okay let’s be honest, friends. Not everything is ready for Gutenberg. In fact, I myself have certain sites that aren’t ready for it today. That’s why there exists an excellent plugin known as the Classic Editor. This allows you to decide it you want to block Gutenberg (which is the default option) or if you want to allow users to chose between Gutenberg and Classic editors.

    The settings page for the Classic editor.

    But what if you want to go a step further?

    What if you want to have Gutenberg on by default for posts and pages, but not for a custom post type?

    Don’t worry. We can do that.

    The Code

    The basic idea is that if WP is 5.0 or higher, make sure that the Classic Editor is installed. If it’s less than 5.0, make sure Gutenberg is installed. Then block the code as needed:

    class HELF_Gutenberg {
    
    	public $gutenfree = array();
    
    	public function __construct() {
    		$this->gutenfree = array( 'post_type_ONE', 'post_type_TWO', 'post_type_THREE' );
    		add_action( 'current_screen', array( $this, 'gutenberg_removal' ) );
    	}
    
    	public function gutenberg_removal() {
    
    		// WP 5.0+ requires Classic Editor
    		// WP 4.9- requires Gutenberg
    		if ( ( version_compare( get_bloginfo( 'version' ), 5.0, '<=' ) && ! is_plugin_active( 'gutenberg/gutenberg.php' ) ) || ( version_compare( get_bloginfo( 'version' ), 5.0, '=>' ) && ! is_plugin_active( 'classic-editor/classic-editor.php' ) ) ) {
    			return;
    		}
    
    		// Intercept Post Type
    		$current_screen    = get_current_screen();
    		$current_post_type = $current_screen->post_type;
    
    		// If this is one of our custom post types, we don't gutenize
    		if ( in_array( $current_post_type, $this->gutenfree, true ) ) {
    			remove_filter( 'replace_editor', 'gutenberg_init' );
    			remove_action( 'load-post.php', 'gutenberg_intercept_edit_post' );
    			remove_action( 'load-post-new.php', 'gutenberg_intercept_post_new' );
    			remove_action( 'admin_init', 'gutenberg_add_edit_link_filters' );
    			remove_filter( 'admin_url', 'gutenberg_modify_add_new_button_url' );
    			remove_action( 'admin_print_scripts-edit.php', 'gutenberg_replace_default_add_new_button' );
    			remove_action( 'admin_enqueue_scripts', 'gutenberg_editor_scripts_and_styles' );
    			remove_filter( 'screen_options_show_screen', '__return_false' );
    		}
    	}
    
    }
    
    new HELF_Gutenberg();
  • Shortcodes vs Blocks

    Shortcodes vs Blocks

    One of the things that Gutenberg changes for everyone is the concept of shortcodes not being absolutely necessary anymore. 

    Shortcodes Today

    One of the nice things about WordPress is that we can use shortcodes to insert dynamic content into our posts. For example, I could use [ copyright ] and have it echo © 2026. And when you have inline dynamism, that works great.

    One of the other cool things you can do is to have an embed like [ embed height="400" width="600"]...[/embed ] to embed a video:

    Yes, you could just paste in the video URL, but this is a demonstration of a shortcode as a sort of block. And speaking of blocks…

    Blocks Tomorrow

    In Gutenberg (which this post was written with), you can keep using in-line shortcodes and even add a shortcode as a block:

    An example of the Shortcode block.

    To a degree, that works well. But there are other options with Gutenberg.

    First, you can see this in a normal paragraph block. Adding options to the sidebar:

    An example of the sidebar editor, with options and the empty additional css class.

    This allows you to edit the various options on the right sidebar and, thus, change the customizable aspects of the block. For many shortcodes, you can keep that interface and have everything be perfectly functional. Have a block that shows user information? Put a dropdown for the users on the sidebar, and so on.

    Inline Edits

    The other options is an integrated block. For example, here’s my example of a review block, with text fields and dropdowns to allow you to edit in situ.

    An example of a block with dropdowns in the block itself.

    In my opinion, this is a more fluid interface, as you can see example what you’re doing and what it’s going to look like.

    How Will You Use The Future?

    There are still hurdles to overcome with Gutenberg, but as we step forward, we’re getting a better look at an integrated editor that gives you a lot of that desired ‘What you see is what you get’ experience.

  • Gutenberg Spoiler Blocks Redux

    Gutenberg Spoiler Blocks Redux

    While I did write up Spoiler Blocks for Gutenberg one way, I also sat down recently and rewrote it a little cleaner. The primary difference here is how I’m properly using defaults:

    The Code

    ( function( blocks, element, editor, components ) {
    
    	const { registerBlockType } = blocks;
    	const { RichText } = editor;
    	const { createElement } = element;
    	const { InspectorControls } = editor;
    	const { SelectControl, ToggleControl } = components;
    
    	registerBlockType( 'library/spoilers', {
    		title: __( 'Spoiler Warning' ),
    		icon: 'vault',
    		category: 'halfelf',
    		customClassName: false,
    		className: false,
    		attributes: {
    			content: {
    				source: 'children',
    				selector: 'div',
    				default: 'Warning: This post contains spoilers!'
    			}
    		},
    
    		save: function( props ) {
    			const content = props.attributes.content;
    			const container = createElement(
    				'div', { className: 'alert alert-danger' },
    				React.createElement( RichText.Content, { value: content })
    			);
    			return container;
    		},
    
    		edit: function( props ) {
    			const content = props.attributes.content;
    			const focus = props.focus;
    
    			function onChangeSpoiler( newContent ) {
    				props.setAttributes( { content: newContent } );
    			}
    
    			const editSpoiler = createElement(
    				RichText,
    				{
    					tagName: 'div',
    					className: props.className,
    					onChange: onChangeSpoiler,
    					value: content,
    					focus: focus,
    					onFocus: props.setFocus,
    				}
    			);
    
    			return createElement(
    				'div', { className: 'alert alert-danger' },
    				editSpoiler
    			);
    		},
    
    	});
    
    })(
    	window.wp.blocks,
    	window.wp.element,
    	window.wp.editor,
    	window.wp.components,
    	window.wp.i18n
    );
    

    Learning more and more about Gutenberg, and javascript, I’ve been able to iterate on the existing code and keep improving.

  • Gutenberg Categories

    Gutenberg Categories

    No, this isn’t something snazzy about doing cool things with categories within Gutenberg (although you could). This is about making a section for your own blocks. A category.

    What’s a Category?

    I’m incredibly lazy, so when I use blocks, I type /head and make sure I get the right block, hit enter, and keep on typing.

    The slash command at work!

    But. Sometimes I think I need a specific block and I don’t know the name, so I click on the circle + sign and I get a list of categories!

    Block categories

    You won’t see reusable if you didn’t make some, but the point is that you could make a custom category for your custom blocks.

    Show me the code!

    Glad you asked! You’re gonna love this one.

    add_filter( 'block_categories', function( $categories, $post ) {
    	return array_merge(
    		$categories,
    		array(
    			array(
    				'slug'  => 'halfelf',
    				'title' => 'Half-Elf',
    			),
    		)
    	);
    }, 10, 2 );

    Yep. That’s it! It’s an array, so you can add more and more and more as you want. Don’t go too wild, though, or you’ll make it too long.

  • Advanced Block Behaviour

    Advanced Block Behaviour

    Making a straight forward block to insert content in Gutenberg is (relatively) easy. I hate using the word ‘easy’ here, because in order to do it you will need to master a whole new world of coding, but all things considered, yes. It is easy. In fact, Gary (aka Pento) wrote a sample plugin that will let you convert a shortcode to a Gutenberg Block.

    I myself have written a mildly complicated Spoiler Block (there’s a new version of it I will share soon). But then the day happened that my cohort in lesbian TV crime, Tracy, expressed annoyance at how Gutenberg destroyed her listicle.

    What is a Listicle?

    Have you seen those posts that show you the top ten ways to LifeHack your used egg cartons? Those are listicles. They’re lists (list) articles (icle). Makes sense, right? Listicles have a pretty basic format as well, there will be a header with some sort of numerical mark, then content with images etc. This repeats for the number of times you have an article.

    Most people make them by hand by manually editing the numbers in their header. That’s all well and good until you want to craft better formatting and have a listicle look somehow ‘different’ from the rest of your content. Maybe you want them to have a special background color, or a different design for the header. 

    If we were doing this in the old, simple, HTML way, it would look like this:

    <dl class="listicle">
        <dt>The Title</dt>
        <dd>The Content</dd>
    </dl>

    Of course that doesn’t make anything look like a list until you put in some CSS magic:

    .listicle {
      counter-reset: listicle-counter;
    }
    
    .listicle dt:before { 
        content: counter(listicle-counter);
        counter-increment: listicle-counter;
        margin-right: 6px;
    }

    What this does is create a CSS counter and increment it every time you use <dt> creating an auto incrementing list.

    No HTML for Gutenberg

    Now, if you know the HTML, you can still do this in Gutenberg in HTML by using the HTML block.

    Example of summoning the Custom HTML block.

    But if you don’t know HTML, then this is a bloody nightmare to handle. And part of the reason why I’m very pro-Gutenberg is that it’s 2018, and expecting people to know all the myriad magical steps of HTML, in order to create a webpage, feels passé. No, it feels restrictive. We can’t expect websites to advance and become more than just pages if we don’t give them the tools.

    Complex Design

    Unlike the relatively simple javascript I used to make my Spoiler Box block, to do this requires the use of a feature called ‘Inner Blocks‘ which is effectively putting a block inside a block. 

    My original idea was to have a multiple nested block with the following:

    1. Listicle Block that calls a template of a list item
    2. ListItem block that calls a title and description
    3. ListDT block that calls the title
    4. ListDD block that allows you to add whatever more inner blocks you want

    It sounds incredibly complicated, and sadly the perfect version was so difficult I actually started with a pared down version.

    1. Listicle block that sets up a template of title and description

    The problem here is that I end up having a separate dl for each block. I can work around it with some CSS magic, but it’s not perfect. So I knuckled down and actually wrote the code that does exactly what I want. Whew.

    Some Code

    … Actually I’m going to do something I hate and that’s link to an external directory.

    I’ve build out Listicles for Gutenberg for you to peruse and fork and enjoy. Or even use if you want, becuase it does work. But it’s big. No, it’s huge for an in-post example. And to explain everything line by line wouldn’t help.

    If you go to the repository, the Gutenberg source code is located in /src/ – that’s where most (if not all) of your work will happen.

    • blocks.js – A list of all the separate JS files included
    • /block/listicle.js – The main listicle file
    • /block/listitem.js – Individual list items (this is only usable inside the Listicles block)
    • /block/listdt.js – The list title
    • /block/listdd.js – The list content (this allows you to add as many sub blocks as you can)

    And yes, not only does it auto increment as you move the slider (or bump the counter), you can flip it into reverse mode:

    The real trick of it all was the copious use of templates.

    It’s all Complicated

    Besides the fact that the blocks aren’t quite  where I want them to be, I also have to use a block builder to convert that javascript into my real files. I chose the Create Guten Block builder, instead of building out my own NPM build script.

    That too illustrates some of the concerns people have, and rightly so, about blocks being incredibly more complicated than they need to be. And yet, having gone through the exercise myself, I think that it’s perhaps not going to be that much of a drama.

    For those of use who generally just make new shortcodes, the world won’t change too much. Gutenberg supports inline shortcodes, after all, which is the majority of what people need from it. We want to be able to make our own embed blocks, which again isn’t terrible, and when someone gets to the complicated point of needing something advanced like a listicle, well eventually there will be a plugin that will handle this better than a shortcode.

    Or you could just use that HTML block.