Avoid printing empty blocks in Headway
March 7, 2014
I've talked about qTransalte language chooser block to a great extent and I'm using it here as an example and the code examples will use its code.
The objective
Sometimes a block added in design time could yield, in the dynamic environment of a live WordPress site, empty results.
In the example I'm making here the block will return a message when the plugin it gets its content from is not active or not installed
<?php
namespace qtblock;
class Block extends \HeadwayBlockAPI
{
public $id = 'qtblock';
public $name = 'qTranslate language chooser';
public $options_class = '\qtblock\BlockOptions';
public $description = 'An Headway block to display qTranslate plugin language chooser on the page.';
public function content($block)
{
if (function_exists('qtrans_generateLanguageSelectCode')) {
$displayMode = \HeadwayBlocksData::get_block_setting($block, 'display-mode', 'dropdown');
$out = qtrans_generateLanguageSelectCode($displayMode);
echo $out;
return;
}
echo 'Either qTranslate plugin is not installed or it\'s not activated';
}
and in the site will output a message which is informative to a WordPress administrator but not the nicest thing to see. I can imagine the same happening for a block that displays related pages or some other kind of information that might actually be not present or empty at the time of that particular page request. Once a block is added to a page layout Headway will print it, and along with it its title and subtitle, to the page.
[caption id="attachment_697" align="aligncenter" width="994"][](http://theaveragedev.local/wordpress/wp-content/uploads/2014/03/Visual_Editor__Blog_Index.png) The block in the page layout[/caption] If the block should return a list of current promotions and no promotions are present then printing "There are no promotions at the moment" to the page could not be the best result and no option is added to the blocks by default to prevent such behaviour.
Empty output
The bare minimum Headway will print to the page, when title and subtitle are set, is
<div id="block-9" class="block block-type-qtblock block-fluid-height">
<div class="block-content">
<hgroup>
<h1 class="block-title"><span>Choose language</span></h1>
<h2 class="block-subtitle">You not speak english?</h2>
</hgroup>
</div><!-- .block-content -->
</div>
while this is what will be printed to the page when no title, subtitle and content are present
<div id="block-9" class="block block-type-qtblock block-fluid-height">
<div class="block-content">
</div><!-- .block-content -->
</div>
Which is not a lot but still is something that will get space and style on the page.
[caption id="attachment_696" align="aligncenter" width="1024"][](http://theaveragedev.local/wordpress/wp-content/uploads/2014/03/Screen-Shot-2014-03-07-at-14.15.39.png) Empty blocks still take place and style[/caption]
Hooking
Without going into much detail an hook will be called before any HTML is printed to the page
headway_before_block
and another after the block has been printed to the page
headway_after_block
I will hook into both to
- activate output buffering before any HTML is printed to the page
- print the block to the page if there is any actual content in it
And that's the modified block code shown by run-time
<?php
namespace qtblock;
class Block extends \HeadwayBlockAPI
{
public $id = 'qtblock';
public $name = 'qTranslate language chooser';
public $options_class = '\qtblock\BlockOptions';
public $description = 'An Headway block to display qTranslate plugin language chooser on the page.';
protected $content = true;
I hook into both actions when the block is initialized
public function init()
{
add_action('headway_before_block', array($this, 'bufferOutput'));
add_action('headway_after_block', array($this, 'maybePrintBlock'));
}
the first one will activate the output buffer to prevent any actual printing to the page
public function bufferOutput($block)
{
// do nothing if it's not this block type
if ($block['type'] != $this->id) {
return;
}
ob_start();
}
the content
function will either echo some content or set the $content
variable to false
public function content($block)
{
if (function_exists('qtrans_generateLanguageSelectCode')) {
$displayMode = \HeadwayBlocksData::get_block_setting($block, 'display-mode', 'dropdown');
$out = qtrans_generateLanguageSelectCode($displayMode);
echo $out;
return;
}
$this->content = false;
}
this one will eventually print the output to the page
public function maybePrintBlock($block)
{
// do nothing if it's not this block type
if ($block['type'] != $this->id) {
return;
}
$out = ob_get_contents();
ob_end_clean();
if (!$this->content) {
return;
}
echo $out;
}
...
}
A more specific hooking
More specific hooks exist in code in the form
headway_before_block_<blockId>
headway_after_block_<blockId>
The id
seen here is not something like qtblock
(the block $id
property) but a numbered selector like 9
(an int
value).
Sadly no hook can be attached there due to the fact that when Block::init()
function is called the block id
(the int
value) is not one of the available informations.
Caveats
In a grid system preventing a block from being printed to the page might issue some layout concerns and the non option-able behaviour seen here might not be the best solution in any layout. I had no problems in a vertically stacked grid but the solution might not cut it for side by side blocks.