Back End Instructions – official release

So, you might remember, back in August, I wrote a plugin called “Back End Instructions” and popped it on my site for you all to freely download and use, if you wanted. If you recall, the plugin is for those of you who have a lot of clients that utilize WordPress, and you’ve written a custom theme for them, but no matter how many times you send instructions or answer their questions on how to use it, they still keep asking you.

I’ve discovered that the reason clients do this is because (and no offense to clients – we live in an “instant gratification” age right now) it’s easier to just call you and ask when they forget how to do something than search for the last time they asked you and you provided that answer. You can send them written instructions or answer their questions with meaningful subject lines in email (so it’s easy to find), but they’ll still just call you when they forget instead of looking to see if the question’s already been answered. They want something that’s right there, in their face, and they don’t have to go looking for it.

So I came up with this plugin, and I tell ya, it’s been a lifesaver. read more »

New Plugin: Back End Instructions

Well hello there!

I’m all excited. I think I’ve mentioned before (although for the life of me I can’t find reference to it) that I wrote a quick plugin once to provide back end instructions for clients. It was using the Userextra/Usermeta plugins, and I edited/added text right in the plugin area to pull up the right stuff, so it wasn’t easily managed. It worked (and was a “quick fix”) – but I wanted it to be better.

My dream was to have it really easy for an administrator to manage, edit and remove instructions for clients. Bonus points for allowing video and/or audio content.

I finally pulled it off :)

So this plugin basically uses the new custom post types functionality that WP provides. It installs a new type, and you simply go in, write a post, tell it what page to show up in, and publish. There’s custom fields that you can use for various things – but in essence, it’s writing a post via WordPress that will publish in the back-end instead of the front. It uses jQuery so it “slides open” on demand to reveal the “instructables”, and on pages that don’t have instructions, there’s no indication of the plugin at all.

Now, this is not quite ready for an official release. Right now, I’m after testers to help me find and squish bugs. So if you’d like to download this and give it shot (and let me know how it goes for you) I’d really appreciate that.

You can download the files here: Back End Instructions for WordPress

Notes to go along with this:

  • I’m still working on the stylesheet – so some of the output looks weird at the moment.
  • If your WP install is in a subdirectory, you won’t see it working properly (I know why – I just have to fix it). This will work for installs in the root of your site.
  • The only multimedia I’ve used with this is YouTube. I’d like to have other media tried – like vimeo, or Jing (working for Jing – at least the SWF files anyway!) – and have audio files, etc. tried out and see how that goes.
  • I’m considering adding an admin page (or something) so you can easily uninstall this plugin. Deactivating it will still leave the content in your database, since it’s using native WordPress capabilities. I’m riding the fence on this, because in truth, all the plugin truly adds to your database is the little registration to let the system know it’s there. The rest is just posts – it’s just a custom post type. So if you deactivate the plugin, the posts/content remain, you just wont’ see them anymore. I’m leaning towards somehow changing the post type back to “post” so the content will show up in your regular post listing – because I keep thinking that people would want to remove the plugin, but keep the content. This is under debate – I’m not sure what the best way to handle it is.

So please, if you download this and try it out, please let me know how it goes! Thanks!

Update: 8/14/2010 I’ve actually been putting this to use today for a client’s site, and have found (and worked out) a few little bugs. I’m not finished, but I expect I’ll have the full plugin ready for serious scrutiny by Monday. I’ve finally checked the Jing capabilities, and even though the file you’re downloading right now doesn’t work with Jing, I’ve already gotten fixes in place that do. So watch for it on Monday!

Update: 8/16/2010 Okay, I’ve uploaded a new version this morning. I’m terrible, because I need to figure out how to let people know it’s been updated! I always forget to do that. But It’s now working with YouTube and Jing, but I’d still like to try it out on Vimeo and Blip.tv. I also worked out a bug/conflict that I ran into with Role Scoper, and I’ve edited it a bit so if you have role-specific instructions, it’ll hide them from lower-level users.

Update: 8/16/2010 @ 11:05 am Another update – the newest upload now contains internationalization, and I’ve cleaned up the code so the header stuff doesn’t get added to pages it doesn’t need to be added to. I’ve also added some commenting to make understanding the code better, and grouped certain functions into new files. Oh, and in the earlier update this morning, I’d forogtten to add the necessary Jing files – whoops! They’re in there now.

Update: 9/1/2010 @ 3:32 pm Per request, you can now add instructions for the dashboard. I’ve also cleaned up and reorganized the file system, so be careful when you upload. (There’s a readme file in there – pay attention to it!)

Better Text Widget

NOTE: October 5, 2010
I just recently used this plugin while developing locally for a client. I did an SQL export of the site to move the testbed to the live server, and was muchly surprised to discover this widget does not get retained in the database for some reason. I had to redo all of the widgets manually.

I just wanted to post notice of this bug, because I want you to know that I know, and I’m working to correct it.

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
}
}

Creating an HTML signature file for just about anything

So I’ve recently had the opportunity to create a plethora of (pinatas?) e-mail siggy files :) And not just a nice little siggy file to place with your Outlook or Mac Mail program, but in ALL KINDS of things. Even for Gmail.

I had to piece together the “how-to”s from a bunch of different sources throughout the web, but I’m here to share how I did it, and how I managed to make it work for all kinds of different mail-reading-and-sending programs.
read more »

Holy crap, I made a boo-boo!

I was just informed about a stupid mistake I made with my CakeShop plugin (formerly called “Simple Cart”). So please, if ANY of you have downloaded those files before today, redownload them NOW.

Here’s the reason why…
read more »