Advertisement
Plugins

Building a Simple Announcements Plugin for WordPress

by

Let's say that you're a launching new product, giving away freebies or organizing an event. How do you deliver the message to your readers? Popular choice is to display a modal dialog in a lightbox, thus forcing the user to take notice. But there's another, less obtrusive, yet still effective way, to get a user's attention. In this tutorial we'll be creating a plugin that displays custom site-wide announcements across the top of the page, with the ability to schedule messages to appear between two given dates.


Step 1 Creating the Plugin

Our first step is to create a plugin folder and the main plugin file, with properly formatted header. Head on to wp-content/plugins and create a folder named simple-announcements. Now open your favorite editor and create a new php file called simple-announcements.php - the main file for our plugin. All the following PHP code should be placed in this file. Next, add the following code at the very beginning of the file:

<?php
/*
Plugin Name: Simple Announcements
Plugin URI: http://wp.tutsplus.com
Description: A simple announcements plugin.
Version: 1.0
Author: Aleksandra Laczek
Author URI: http://webtuts.pl
*/
?>

It's a standard plugin header, and you could extend it with other information if you like (read more in Plugins section of the WordPress Codex).

Once it's done, go to Plugins section of WordPress administration area, and you should see the plugin, ready to be activated.

Before we move any further, we will define a constant to store our plugin path. This constant will be used throughout the plugin, and will make our job a little easier. Drop this line of code into simple-announcements.php, below the header.

<?php
define('SIMPLE_ANNOUNCEMENTS_PATH', plugin_dir_url( __FILE__ ));
?>

Step 2 Creating Custom Post Type

To make it easy to edit and add new announcements, we're going to create a dedicated custom post type called Announcements.

<?php
function sap_register_announcements() {

	$labels = array(
		'name' => _x( 'Announcements', 'post type general name' ),
		'singular_name' => _x( 'Announcement', 'post type singular name' ),
		'add_new' => _x( 'Add New', 'Announcement' ),
		'add_new_item' => __( 'Add New Announcement' ),
		'edit_item' => __( 'Edit Announcement' ),
		'new_item' => __( 'New Announcement' ),
		'view_item' => __( 'View Announcement' ),
		'search_items' => __( 'Search Announcements' ),
		'not_found' =>  __( 'No Announcements found' ),
		'not_found_in_trash' => __( 'No Announcements found in Trash' ),
		'parent_item_colon' => ''
	);

	$args = array(
		'labels' => $labels,
		'singular_label' => __('Announcement', 'simple-announcements'),
		'public' => true,
		'capability_type' => 'post',
		'rewrite' => false,
		'supports' => array('title', 'editor'),
	);
	register_post_type('announcements', $args);
}
add_action('init', 'sap_register_announcements');
?>

Now head to the administration area. There should be a new item in the menu, just below Comments.


Step 3 Creating Custom Meta Boxes

Announcements are rather simple, and all we really need is the post edit section to input our message. But to be able to schedule announcements, we'll need two additional fields to input a start and end date. For this purpose we're going to create a meta box and put our fields inside (we could also use custom fields instead).

Adding Meta Box

<?php
function sap_add_metabox() {
	add_meta_box( 'sap_metabox_id', 'Scheduling', 'sap_metabox', 'announcements', 'side', 'high' );
}
add_action( 'add_meta_boxes', 'sap_add_metabox' );
?>

Wptuts+ has a great step by step tutorial on Custom Meta Boxes.

This piece of code adds a meta box named 'Schedule' to the right column on the Announcements post edit screen. You can read more about the add_meta_box function and its parameters in the WordPress Codex.

I just want you to take notice of the third parameter - sap_metabox. It's the name of callback function that renders HTML for the meta box content. We'll be writing that function in a moment.

Adding the Fields

We're going to add two fields to store the start and end date of the announcements.

<?php
function sap_metabox( $post ) {
	$values = get_post_custom( $post->ID );
	$start_date = isset( $values['sap_start_date'] ) ? esc_attr( $values['sap_start_date'][0] ) : '';
	$end_date = isset( $values['sap_end_date'] ) ? esc_attr( $values['sap_end_date'][0] ) : '';
	wp_nonce_field( 'sap_metabox_nonce', 'metabox_nonce' );
	?>
	<p>
		<label for="start_date">Start date</label>
		<input type="text" name="sap_start_date" id="sap_start_date" value="<?php echo $start_date; ?>" />
	</p>
	<p>
		<label for="end_date">End date</label>
		<input type="text" name="sap_end_date" id="sap_end_date" value="<?php echo $end_date; ?>" />
	</p>
	<?php
}
?>

First thing we do here, is get all current custom fields' values. Then we create a nonce field, that will be needed for validation later.

Finally we're printing out HTML code for the two input fields, with values that we determined at the beginning.


Step 4 Registering JavaScript and CSS Files

We just created two custom meta boxes to input the dates for scheduling announcements. To make this task easier, we're going to add a JavaScript date picker. For this purpose I decided to use jQuery Datepicker. The script is actually bundled in with WordPress, so we just need to enqueue it, but for the CSS we need a jQuery UI theme. As we've mentioned before Helen Hou-Sandi, core WordPress contributor, has worked on two jQuery UI themes which complement WordPress. We'll use the 'fresh' theme which matches the default WordPress admin, so download the jquery-ui-fresh.css file from her GitHub repository, and save it to your simple-announcements/js folder.

We need one more JavaScript file to store all custom JavaScript code related to front and back end. We will call this file announcements.js. For now just create an empty JavaScript file and put it in the js folder, we'll get to writing custom code later.

After this, the plugin folder should be organized as shown below.

Now it's time to enqueue scripts and stylesheets, so that we can actually use them.

<?php
function sap_backend_scripts($hook) {
	global $post;

	if( ( !isset($post) || $post->post_type != 'announcements' ))
		return;

	wp_enqueue_style( 'jquery-ui-fresh', SIMPLE_ANNOUNCEMENTS_PATH . 'css/jquery-ui-fresh.css');
	wp_enqueue_script( 'announcements', SIMPLE_ANNOUNCEMENTS_PATH . 'js/announcements.js', array( 'jquery', 'jquery-ui-datepicker' ) );
}
add_action( 'admin_enqueue_scripts', 'sap_backend_scripts' );
?>

Our script will be used only in admin section, and what is more, only while adding or editing Announcements Post Type. Therefore we should make sure, that any scripts and styles are loaded only when needed.


Step 5 Adding Datepicker to Date Fields

In order to use the datepicker, we need to add some custom JavaScript code to assign date pickers to input fields. This code goes into the announcements.js file created in the previous step.

jQuery(document).ready(function($) {
	if($('#sap_start_date').length) {
		$(function() {
			var pickerOpts = {
				dateFormat: "yy-mm-dd"
			};
			jQuery("#sap_start_date").datepicker(pickerOpts);
			jQuery("#sap_end_date").datepicker(pickerOpts);
		});

	}
});

Notice the dateFormat option. We need to separate elements of the date with a '-' character. This will be important later, during validation.

More documentation on how to use Datepicker can be found in jQuery UI website.

To see the datepicker in action, go ahead and add a new Announcement. Try to add a start or end date and you'll notice the datepicker calendar pop up.


Step 6 Saving Meta Box Data

Now that we've got all the needed fields, we can proceed to saving the data from the meta box to the database. We do that by calling the sap_metabox_save function on the save_post action.

<?php
function sap_metabox_save( $post_id ) {
	if( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
		return $post_id;

	if( !isset( $_POST['metabox_nonce'] ) || !wp_verify_nonce( $_POST['metabox_nonce'], 'sap_metabox_nonce' ) )
		return $post_id;

	if( !current_user_can( 'edit_post' ) )
		return $post_id;

	// Make sure data is set
	if( isset( $_POST['sap_start_date'] ) ) {

		$valid = 0;
		$old_value = get_post_meta($post_id, 'sap_start_date', true);

		if ( $_POST['sap_start_date'] != '' ) {

			$date = $_POST['sap_start_date'];
			$date = explode( '-', (string) $date );
			$valid = checkdate($date[1],$date[2],$date[0]);
		}

		if ($valid)
			update_post_meta( $post_id, 'sap_start_date', $_POST['sap_start_date'] );
		elseif (!$valid && $old_value)
			update_post_meta( $post_id, 'sap_start_date', $old_value );
		else
			update_post_meta( $post_id, 'sap_start_date', '');
	}

	if ( isset( $_POST['sap_end_date'] ) ) {

		if( $_POST['sap_start_date'] != '' ) {

			$old_value = get_post_meta($post_id, 'sap_end_date', true);

			$date = $_POST['sap_end_date'];
			$date = explode( '-', (string) $date );
			$valid = checkdate($date[1],$date[2],$date[0]);
		}
		if($valid)
			update_post_meta( $post_id, 'sap_end_date', $_POST['sap_end_date'] );
		elseif (!$valid && $old_value)
			update_post_meta( $post_id, 'sap_end_date', $old_value );
		else
			update_post_meta( $post_id, 'sap_end_date', '');
	}
}
add_action( 'save_post', 'sap_metabox_save' );
?>

This is a fairly standard way of saving meta box data. First, we check that:

  1. the post is not being auto saved,
  2. the nonce is present and valid,
  3. current user can actually edit the post.

After that we proceed with data validation, and finally save both dates to the database.


Step 7 Displaying Announcements

It's time to display our announcement! It'll be a two step process - first we need to create a function that selects relevant announcements using WP_Query and creates HTML markup, and then we'll write some JavaScript and CSS to style the output.

Display Function

<?php
function sap_filter_where( $where = '' ) {
	// ...where dates are blank
	$where .= " OR (mt1.meta_key = 'sap_start_date' AND CAST(mt1.meta_value AS CHAR) = '') OR (mt2.meta_key = 'sap_end_date' AND CAST(mt2.meta_value AS CHAR) = '')";
	return $where;
}

function sap_display_announcement() {

	global $wpdb;

	$today = date('Y-m-d');
	$args = array(
		'post_type' => 'announcements',
		'posts_per_page' => 0,
		'meta_key' => 'sap_end_date',
		'orderby' => 'meta_value_num',
		'order' => 'ASC',
		'meta_query' => array(
			array(
				'key' => 'sap_start_date',
				'value' => $today,
				'compare' => '<=',
			),
			array(
				'key' => 'sap_end_date',
				'value' => $today,
				'compare' => '>=',
			)
		)
	);

	// Add a filter to do complex 'where' clauses...
	add_filter( 'posts_where', 'sap_filter_where' );
	$query = new WP_Query( $args );
	// Take the filter away again so this doesn't apply to all queries.
	remove_filter( 'posts_where', 'sap_filter_where' );

	$announcements = $query->posts;

	if($announcements) :
		?>
		<div id="announcements" class="hidden">
			<div class="wrapper">
				<a class="close" href="#" id="close"><?php _e('x', 'simple-announcements'); ?></a>
				<div class="sap_message">
					<?php
					foreach ($announcements as $announcement) {
						?>
						<?php echo do_shortcode(wpautop(($announcement->post_content))); ?>
						<?php
					}
					?>
				</div>
			</div>
		</div>
		<?php
	endif;
}
add_action('wp_footer', 'sap_display_announcement');
?>

The key is to select the right announcements from the database, based on the start and end date. We need only those which start before, and end after, the current date. Also, since we didn't make the start and end date fields mandatory, we should include announcements without a scheduled date.

Start and end date are saved in the postmeta table, assigned to a specific post via the post_id column. We use a meta_query with WP_Query to fetch the right posts.

Finally, we loop through all selected announcements with simple foreach statement and display them with custom HTML markup.

Frontend JavaScript and CSS

Right now you should be able to see the announcements displayed on the home page, but you'll notice a few problems:

  • announcements are at the bottom of the page
  • it's impossible to close them
  • they lack styling

Taking care of those issues will require writing some custom JavaScript code. But before we get to that, we need two more external JavaScript plugins:

  • jQuery Cookie - we don't need the whole package, just the jquery.cookie.js file
  • jQuery Cycle - we'll be using the Lite version - jquery.cycle.min.js.

Copy both files to simple-announcements/js folder. Now, remember how we loaded JavaScript in admin to show the datepicker? It's time to add some scripts and styles to the front end. Don't worry about the announcements.css, we'll create it shortly.

<?php
function sap_frontend_scripts() {
	wp_enqueue_style( 'announcements-style', SIMPLE_ANNOUNCEMENTS_PATH . 'css/announcements.css');
	wp_enqueue_script( 'announcements', SIMPLE_ANNOUNCEMENTS_PATH . 'js/announcements.js', array( 'jquery' ) );
	wp_enqueue_script( 'cookies', SIMPLE_ANNOUNCEMENTS_PATH . 'js/jquery.cookie.js', array( 'jquery' ) );
	wp_enqueue_script( 'cycle', SIMPLE_ANNOUNCEMENTS_PATH . 'js/jquery.cycle.lite.js', array( 'jquery' ) );
}
add_action('wp_enqueue_scripts', 'sap_frontend_scripts');
?>

Now that we have all the necessary tools we can write the final piece of JavaScript. This code goes in announcements.js, below scripts added in step 5, inside the main jQuery(document).ready() function.

if($('#announcements').length) {
	if($.cookie('sap_active') == 'false') {
		$("#announcements").hide();
	};
	$("#close").click(function() {
		$("#announcements").slideUp("normal");
		$.cookie('sap_active', 'false', { expires: 2, path: '/'});
		return false;
	});
	$("body").prepend($("#announcements"));
	$('#announcements .sap_message').cycle('fade');
}

Let's break down the code.

The Close Button

We don't want to annoy our visitors, that's why we added a closing button to the announcement. But right now it doesn't do anything. With a little JavaScript we're going to hide the announcement on the click event, with a nice slide effect. To make sure that the announcement doesn't pop up when a user visits us next time, we're creating a cookie that will expire in two days (that's what we needed the jQuery Cookie plugin for).

if($.cookie('sap_active') == 'false') {
	$("#announcements").hide();
};
$("#close").click(function() {
	$("#announcements").slideUp("normal");
	$.cookie('sap_active', 'false', { expires: 2, path: '/'});
	return false;
});

First thing we need to do, is to check if our cookie named 'sap_active' is present. If it is and its value equals to 'false', we simply hide the whole announcements bar. The cookie is created when the user hits the close button.

Moving Announcement to Top of the Page

$("body").prepend($("#announcements"));

Next we move the announcements bar to top of the page. To display the announcement bar, we hooked into wp_footer, since themes are required to implement it. wp_footer is a hook that is fired right before the closing </body> tag, which means that our announcement will be appended to the end of the document (that's why it's displayed at the bottom). Here we're using jQuery to display it at the very top of the page, at the same time pushing down the content.

Cycle Through Announcements

$('#announcements').cycle('fade');

Remember when I said that it's possible to have more than one announcement active on any given date? If that happens, we don't want to display all of them at once, but rather cycle through them. That's exactly what this last piece of code does.


Step 8 Styling the Announcement Bar

Right now our announcements bar doesn't look like much. Let's add some CSS rules and style it up a bit. All CSS rules should be placed in the announcements.css file in the simple-announcements/css folder.

#announcements {display: hidden; text-align: center; background: #FF7F00; height: 35px;}
#announcements .wrapper {width: 1000px; text-align: left; margin: 0 auto; padding: 5px 0;}
#announcements .wrapper .close {float: right; font-weight: bold; padding: 0 5px;}
#announcements .wrapper .close:hover{background: #000; border-radius: 5px;}
#announcements .wrapper .sap_message p{margin: 0;color: #fff;}

With these few rules we changed the background color of the announcement bar to orange, positioned the close button to the right and centered announcements on the page. What we've done here is really basic, you could certainly go further, and play with the background or add a shadow, change the font etc.

That's it! Let's take a look at the end result.


Conclusion

Announcements bar is simple yet effective way to communicate with visitors. You could definitely do more in terms of styling and functionality, but I believe this tutorial should be a good starting point. Feel free to use this code as a canvas for your own custom plugins, and let us know about your ideas in comments below.

Related Posts
  • Code
    PHP
    Creating a Photo Tag Wall With Twilio Picture Messaging & PHPProcedural to oop php retina preview
    Twilio's recently announced Picture Messaging has vastly opened up what we can do with text messaging, now we can attach photos to our text messages and have them get used in different ways. In our case, we are going to build a Photo Tag Wall, which will contain photos linked to tags that will be displayed on a website.Read More…
  • Code
    Plugins
    Integrating Multiple Choice Quizzes in WordPress - Creating the BackendIntegrating multiple choice quizzes in wordpress
    Multiple choice questions are something that most of us have faced at least once in our life. We love them because we can provide correct answers by logically thinking about provided possibilities, even if we don't exactly know the correct answer. Also answering takes less time which makes it so popular. Creating a multiple choice quiz in WordPress can be a very exciting and profitable task. You can use it in your personal blog to attract more visitors, or you can create a premium section with advanced quizzes, or you can create quizzes focusing on popular certification exams. There are numerous possibilities for making it profitable.Read More…
  • Code
    Plugins
    Incorporating the jQuery Date Picker Into the Post Editor: Preparing the PluginDatepicker
    We cover a lot of topics on this blog - anything ranging from something as simple as how to include and require template files in WordPress projects to something such as an entire series on the Settings API, but I think there's always room to cover a straightforward How-To that covers a single, specific task within the context of WordPress. So, in this two-part series, we're going to take a look at how to introduce a jQuery date picker into our post editor so that we can associate a date with a given post.Read More…
  • Code
    Plugins
    Creating Responsive Pricing Table Plugin for WordPressPricing table plugin
    Pricing tables are a key component of your business that promotes your products and helps users choose between different services you have. Most modern commercial WordPress themes provide built in Pricing Tables. There are also plenty of free and commercial pricing table plugins for WordPress. This tutorial is intended to provide knowledge to WordPress developers on creating a plugin from scratch which enables customization in different projects. Every web design is trying to accomplish responsive features which enable better look and feel on any kind of device. The pricing tables created with this plugin will work on all kinds of devices such as mobiles and tablets as well. So let's get started.Read More…
  • Code
    Theme Development
    How to Display Metaboxes According to the Current Post FormatHow to display metaboxes according to the current post format
    Today I'd like to show you how to go further with custom metaboxes and specifically how to use them according to post formats. We won't cover how to build reusable custom metaboxes as it has already been covered in a previous topic, so please refer to this article if you have any trouble with this.Read More…
  • Code
    Creative Coding
    Posting via the Front End: Advanced SubmissionPreview advanced submission
    Today, we will be continuing with our mini-series on inserting posts via the front end, but in this part we will be exclusively looking into how to manage custom meta fields which we may have within our post type. So, let's get ready and begin!Read More…