Better Text Widget

February 17, 2010

Yes, I’ve been quiet for a few weeks. I’ve had some issues come up, and have been trying to knock them out of the park. I was just saying this morning, it amazes me how I’m on sabbatical, but I’m busier now than I was when I wasn’t! (OMG – that has to be some kind of grammatical nightmare right there.)

Anyway, recently I’ve had a lot of people around me (not directly to me, but sort of discussing around me) that they are using WordPress, but wished they’d had a widget that would pull off certain functionality. I can’t give you their exact words, but the gist of it is that they want some kind of easier-to-use text widget.


If you don’t know what I mean, basically WordPress has a default widget (that comes with the installation) that’s called “Text Widget”. The description of said widget is “Arbitrary text or HTML” So basically you can type up any text you want and shove it into a Widget. If you know a little HTML, you can put in an image, etc., but you would have to know the proper syntax to do it. Most of my clients look at HTML as if it’s Mandarin Chinese. However, using other widgets are overkill, and sometimes present “TMI” that they can’t seem to sort through. What they wanted was a Widget where they could put in text (or even just have an excerpt from a particular page or post), easily add an image, and even have the title of said widget look different than the title they name the widget.


Lucky for you all, I’ve already written one, and have been using it for some time. Over the last 3 weeks (or so) I’ve been handing out the code for it when anyone asks me for it. I was just getting ready to send it again, when it just dawned on my that DUH – that’s what my site is for. So here. Take it! Just pop this code into your functions.php file, and run :)

Update on July 12, 2010: I’ve been asked also to add in something to make the title of the widget be optionally hidden. It just so happens that I just finished doing exactly that for a client recently, so I’m adding in those lines.

Also – not because I was asked, but because I’ve found this addition very handy – is the option to make accessing the theme directory files easier. Many times, I’m developing on my own server and eventually I need to move the site to a client’s server. Many of the widgets have a full path coded, and those don’t change when you move the site, so stuff ends up broken. I’ve edited the code to make that a whole lot easier.)

$home = get_bloginfo('home');
$templatedir = get_bloginfo('template_url');
$uploadsdir = wp_upload_dir();
$uploadsdir = $uploadsdir['baseurl'];
$imgdir = $templatedir . '/images'; // be sure to change the directory to whatever you've named your images directory within your themes folder

add_action( 'widgets_init', 'easier_text_widgets' );

function easier_text_widgets() {
register_widget( 'Easier_Text_Widget' );
}

class Easier_Text_Widget extends WP_Widget {

function Easier_Text_Widget() {
$widget_ops = array( 'classname' => 'easier_text_widget', 'description' => __('Similar to the plain-vanilla "Text", but makes it easier to manipulate without the need to know PHP or HTML.', 'easier_text_widget') );

$control_ops = array( 'width' => 300, 'height' => 350, 'id_base' => 'easier-widget' );

$this->WP_Widget( 'easier-widget', __('Easier Text Widget', 'easier_text'), $widget_ops, $control_ops );
}

function widget( $args, $instance ) {
global $post, $imgdir, $uploadsdir, $templatedir, $home;
extract( $args );

$title = apply_filters('widget_title', $instance['title'] );
$hide = $instance['hide'];
$image = $instance['image'];
$link = $instance['link'];
$link_text = $instance['link_text'];
$id = $instance['id'];
$text = $instance['text'];

// replace "home" with home url
$findimg = strpos($image, 'images');
$findhome = strpos($link, 'home');
$finduploads = strpos($image, 'uploads');
$findlinkuploads = strpos($image, 'uploads');

if($findimg !== false) $image = str_replace('images', $imgdir, $image);
if($finduploads !== false) $image = str_replace('uploads', $uploadsdir, $image);
if($findhome !== false) $link = str_replace('home', $home, $link);
if($findlinkuploads !== false) $link = str_replace('uploads', $uploadsdir, $link);

if($hide !== false) $class = 'class="hideme"';
else $class = '';

echo $before_widget;

if (!empty($link) && empty($image) && empty($link_text)) {
echo $before_title . '<a style="font-size:1.1em;" ' . $class . ' href="' . $link . '">';

if (!empty($title))
echo $title;

echo '</a>' . $after_title;
} else if(!empty($title)) {
if($class == '') echo $before_title . $title . $after_title;
}

if (!empty($image))
$img = '<img src="' . $image . '" alt="' . $link_text . '" />';

if (!empty($link)) {
echo '<a href="' . $link . '">';

if(!empty($image))
echo $img;
else if(!empty($link_text))
echo $link_text;

echo '</a>';
} else if(!empty($image)) {
echo $img;
}

if (!empty($id)) {
$excerpt = get_the_excerpt();

if($excerpt == '') {
$excerpt = get_post_meta($id, 'page_excerpt_value', true); // post meta value
}
echo '<p>' . $excerpt;
echo '<a class="more-link" href="' . get_permalink($id) . '"> more</a></p>';
}

if (!empty($text)) {
$findimg = strpos($text, 'images');
$findhome = strpos ($text, 'home');
$finduploads = strpos($text, 'uploads');
if($findimg !== false) $text = str_replace('images', $imgdir, $text);
if($findhome !== false) $text = str_replace('home', $home, $text);
if($finduploads !== false) $text = str_replace('uploads', $uploadsdir, $text);
apply_filters( 'widget_text', $instance['text'] );
echo $instance['filter'] ? wpautop($text) : $text;
}

echo $after_widget;
}

function update( $new_instance, $old_instance ) {
$instance = $old_instance;
$instance['title'] = strip_tags($new_instance['title'] );
$instance['hide'] = isset($new_instance['hide']);
$instance['image'] = strip_tags($new_instance['image']);
$instance['link'] = strip_tags($new_instance['link']);
$instance['link_text'] = strip_tags($new_instance['link_text']);
$instance['id'] = strip_tags($new_instance['id']);
//$instance['$text'] = stripslashes($new_instance['text']);
if ( current_user_can('unfiltered_html') )
$instance['text'] = $new_instance['text'];
else
$instance['text'] = wp_filter_post_kses( $new_instance['text'] );
$instance['filter'] = isset($new_instance['filter']);
return $instance;
}

function form( $instance ) {
global $imgdir, $uploadsdir, $templatedir, $home;
$defaults = array( 'title' => __('', 'easier_text'),
'hide' => __('', 'easier_text'),
'image' => __('', 'easier_text') ,
'link' => __('', 'easier_text'),
'link_text' => __('', 'easier_text'),
'id' => __('', 'easier_text'),
'text' => __('', 'easier_text')
);
$instance = wp_parse_args( (array) $instance, $defaults ); ?>

<p><label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e('Title:', 'hybrid'); ?></label>
<input id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" value="<?php echo $instance['title']; ?>" style="width:100%;" />
</p>

<p><input type="checkbox" id="<?php echo $this->get_field_id( 'hide' ); ?>" name="<?php echo $this->get_field_name( 'hide' ); ?>" <?php checked($instance['hide']); ?> />
<label for="<?php echo $this->get_field_id( 'hide' ); ?>"><?php _e('Visually hide title'); ?></label>
</p>

<p><small style="color:#777; font-style:italic;display:block;">If you'd like to use an image (that's not already within the content) in this widget, enter in the full path to the image. <br />
Use "<strong>images</strong>" instead of the full path for images located within the theme files. For example, "images/BG.jpg" will convert to "<?php echo $imgdir; ?>/BG.jpg. <br />
Use "<strong>uploads</strong>" for the path to the uploads directory, if using a media file image. This will give you the first part of the directory, but you will need to supply the rest of the path to the file - the year, month directories and image file name.")</small><label for="<?php echo $this->get_field_id( 'image' ); ?>"><?php _e('Image Path:', ''); ?></label>
<input id="<?php echo $this->get_field_id( 'image' ); ?>" name="<?php echo $this->get_field_name( 'image' ); ?>" value="<?php echo $instance['image']; ?>" />

<p><label for="<?php echo $this->get_field_id( 'link' ); ?>"><?php _e('Full URL to link image or text to - rules for paths apply as with images:', ''); ?></label>
<input id="<?php echo $this->get_field_id( 'link' ); ?>" name="<?php echo $this->get_field_name( 'link' ); ?>" value="<?php echo $instance['link']; ?>"/>
</p>

<p><label for="<?php echo $this->get_field_id( 'link_text' ); ?>"><?php _e('Link text (will also be used as the alternate text for the image):', ''); ?></label>
<input id="<?php echo $this->get_field_id( 'link_text' ); ?>" name="<?php echo $this->get_field_name( 'link_text' ); ?>" value="<?php echo $instance['link_text']; ?>" />
</p>

<p><label for="<?php echo $this->get_field_id( 'id' ); ?>"><?php _e('ID of Page or post you would like the excerpt from:', ''); ?></label>
<input id="<?php echo $this->get_field_id( 'id' ); ?>" name="<?php echo $this->get_field_name( 'id' ); ?>" value="<?php echo $instance['id']; ?>" />
</p>

<p><label for="<?php echo $this->get_field_id( 'text' ); ?>"><?php _e('If not using an excerpt, then enter in text you would like to display. HTML is allowed.', ''); ?></label>
<textarea class="widefat" rows="7" cols="20" id="<?php echo $this->get_field_id('text'); ?>" name="<?php echo $this->get_field_name('text'); ?>"><?php echo $instance['text']; ?></textarea>
</p>

<p><input id="<?php echo $this->get_field_id('filter'); ?>" name="<?php echo $this->get_field_name('filter'); ?>" type="checkbox" <?php checked($instance['filter']); ?> /> <label for="<?php echo $this->get_field_id('filter'); ?>"><?php _e('Automatically add paragraphs.'); ?></label></p>

<?php
}
}

View Comments

Thanks for the code. It is very helpful, both in itself and as a tool to help learn how to make widgets.

But one thing you need a “}” after

function easier_text_widgets() {
register_widget( ‘Easier_Text_Widget’ );

It breaks without it.

Thanks

Daniel

This one function widget is definitely going to the top of my list as favorites and thanks also to Daniel about that curly bracket because it helped. Anyway, everything is great, except I can’t seem to get excerpts in the front-end. It’s just the image and the read more link.

Thanks Daniel – I’ll fix that now.

AJ – are you running WP 3.0? Because I had the same problem when I upgraded to 3.0 :) (This might also work in earlier versions, I don’t know. Before, what’s above worked fine – I just noticed the issue in 3.0).

Basically, you change these two lines:

$thispost = get_post($id);
$excerpt = $thispost->post_excerpt;

to this:

$excerpt = get_the_excerpt();

Hi Shelly….yes, tried it in WP 3 and also another install (locally on xampp) with 2.9.2 as well but didn’t work. However, your new excerpt code change worked for 2.9.2 (just have to control how much of excerpt shows) but looks like something else is affecting it in WP 3.0 still.

Hi AJ,
Okay, I’m giving it a shot in an old 2.9 install I have on my localhost, and I’m coming up with a couple of issues as well.

I’m going to fix the code up there – I’ve tested it in 2.9 *and* 3.0 – and thank you for pointing it out for me! :)

Got somethin' to say?