Implement the WordPress Geolocation Plugin

For a while now WordPress has had apps across the mobile spectrum, and a great feature of these is geolocation - great, but who wants to know where I'm blogging from right? Well recently I had to build a blog for someone travelling around the world, and it quickly became apparent that using the data saved by the app on the site would be a great feature. In this tutorial we'll see the basic implementation of adding the plugin, but more importantly look at how we can then plot a route across the globe using data from every post. So let's get started!

First off you'll need to go and grab the Geolocation plugin and install it on your site. The default behaviour of this plugin is to insert a link at the bottom of single posts and show a map to users when they hover over it. But what if we want to show the map by default? And what about using all that geolocation data from each post? Well the first request is relatively simple - in fact it's just a change of CSS. Here's the alteration to style.css in the goelocation folder:

#map { background: #fff; border: solid 1px #999; padding: 20px; visibility: hidden; }
.home #map { display: none; }

The second rule is useful if you use the the_content() on your home page, this is because only 1 map is actually used for every post meaning that otherwise you'll just have a big empty div.

Plotting your posts on a map

Here's the exciting bit, to begin with we'll look at creating a route out of post data, and displaying it on a nice big map. Thankfully the WordPress app doesn't use anything big, scary, or evil to store its data, it just stores it as a custom variable! So accessing the data is easy as pie! Now in this case I'm assuming that you're whacking the PHP code in something like map.php - a template for a page, and that the JavaScript coming later will be in footer.php - this is important because the JS will be using a PHP variable - namely the coordinates to plot. If you have a different structure, you'll need to find some way of getting this data from PHP, either via an AJAX request, or clever script positioning. Let's take a look at how we'd go about getting all of this data into our PHP backend, before utilising it with the Google Maps JavaScript API:

<?php 
    $points = '';
    query_posts('posts_per_page=500'); 

    while ( have_posts() ) : the_post(); 
    
        $points .= '(' . get_post_meta($post->ID, 'geo_latitude', true) . ',' . get_post_meta($post->ID, 'geo_longitude', true) . '),';  

    endwhile; 
    
    $points = substr($points, 1, -2); // Remove the initial '(' and final '),'
?>

<div id="canvas"></div>

So above we have the standard WordPress loop that cycles through the 500 most recent posts (courtesy of query_posts()) - this should all be familiar. Inside the loop we keep adding to the $points variable in the format (latitude_1, longitude_1), (latitude_2, longitude_2) and so on. We use the handy get_post_meta() function (here's the reference), to get the coordinates, and we end by removing the first bracket and last bracket and comma - we do this because when we switch to JS we need a clean array. Finally we have a div with the ID "canvas" - this is where we'll put our map - so feel free to style this in your CSS, I added the following to the theme's style.css:

#canvas {
    height:600px;
    width: 96%;
    margin-left: 2%;
}

And now we're ready to move into the crazy realm of JavaScript!

Luckily for us the Geolocation plugin already takes care of adding the Google Maps API v3, so we can get straight into using it with our site! But before we get into our JavaScript we're going to be good coders and only deliver our code to users on the map page, so we'll use yet another handy WordPress function to detect when we're on the map.php template page. Go ahead and whack this into footer.php:

<?php  if ( is_page_template('map.php') ) : ?>

     /* JS goes here... */

<?php endif; ?>

Now let's get to the really meaty code. The code below uses 1 jQuery call, and it's just to check that the DOM is fully loaded, so you can use any equivalent function or whack the code into onload="" in the body tag. First up we'll look at getting the data from PHP and making it usable, put the following code within <script> tags:

function init(){
    var p = "<?php global $points; echo $points; ?>", mapCoords = null;
	
    p = p.split("),(");
	
    for(var x = 0; x < p.length; x++){
        p[x] = p[x].split(",");
        if(mapCoords == null){
            mapCoords = [new google.maps.LatLng(p[x][0], p[x][1])];
        }else {
            mapCoords.push(new google.maps.LatLng(p[x][0], p[x][1]));
        }
    }	
	
    newMap('canvas', mapCoords);
}


$(function(){ init(); });

So the function above begins by taking the data we just extracted using PHP and puts it into a variable called p, we also define one called mapCoords. Then we turn p into an array by splitting up each pair of coordinates, before jumping into a for loop. If you've not used the Google Maps API before this may look a little daunting, but it's fairly simple once you get started. First off we set up our loop to cycle though every set of coordinates in our array, and once inside we split our coordinates into longitude and latitude and store that array in p. Then we check to see if mapCoords is empty, if it is we use square brackets to create the array, otherwise that's the only difference. Then we add a new value to the mapCoords array - this value is a special object provided by the API for processing points on the map, and we just have to pass it the relevant values for the longitude and latitude. Once the loop is complete, we call a mysterious function named newMap(), and pass it the ID of our map canvas, as well as our newly created route coordinates. Lets take a look at how we implement this new function.

function newMap(id, mapCoords){
    var centre = (new google.maps.LatLng(51.44031275716014, 0.3955078125)),
	zoomLevel = 6,
        route,
        myOptions,
        map;
	
    route = new google.maps.Polyline({
        path: mapCoords,
        strokeColor: "#2324e4",
        strokeOpacity: .70,
        strokeWeight: 7,
        editable: false
    });
		    	
    myOptions = {
        center: centre,
        zoom: zoomLevel,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };
		
    map = new google.maps.Map(document.getElementById(id), myOptions);
    route.setMap(map);
}

First up we define a few variables: the map centre - as it appears to the user (here it's somewhere between the UK and France), zoom level - 6 will zoom pretty far out (16 is street level), and the route - we'll add to this soon. Then we make use of our route variable - this is a line that will be drawn on our map and will represent the route between posts. There are a number of options here, but the most important is the 'path' - we'll set it equal to the coordinates passed to our function. Next up we define some options for our map and put them into myOptions. Here we set the centre and zoom level - as defined above, as well as the type of map we want to display - here we've created a road-map. Finally we create our map, and tell our route that it needs to draw itself on that map.

Up to this point the code we've written will draw a blue line on your map, so if that's all you need you're done! But if you want to add your posts to the map as markers read on!

Plot Posts with Pins

Now it might be the case that you don't want a route plotted, or maybe you want a route with pins indicating where you've posted from - and once you've implemented the back-end above its remarkably simple. The only difference is that because we'll want to show the user an info window we'll need to store the names, dates, and links for our posts. This just requires a simple modification of the backend:

<?php 
    $points = '';
    $thePosts = '';

    query_posts('posts_per_page=500'); 

    while ( have_posts() ) : the_post(); 
    
        $points .= '(' . get_post_meta($post->ID, 'geo_latitude', true) . ',' . get_post_meta($post->ID, 'geo_longitude', true) . '),'; 
        $thePosts .= '(' . get_the_title() . '|' . get_permalink() . '|' . get_the_time() . '),';
    endwhile; 
    
    $points = substr($points, 1, -2); // Remove the initial '(' and final '),'
    $thePosts = substr($thePosts, 1, -2);
?>

<div id="canvas"></div>

So the only difference here is that we've now got another variable named $thePosts - which holds the title, permalink, and time posted for each post. We'll do essentially the same to this when we get into the JavaScript, and then we can use the data on the map. Notice I've used a pipe character (|) as the delimiter as it's common to have commas in titles. So lets take a look at the init() function in our JavaScript:

function init(){
    var p = "<?php global $points; echo $points; ?>", mapCoords;
	
    p = p.split("),(");
	
    for(var x = 0; x < p.length; x++){
	p[x] = p[x].split(",");
	if(mapCoords == null){
		mapCoords = [new google.maps.LatLng(p[x][0], p[x][1])];
	}else {
		mapCoords.push(new google.maps.LatLng(p[x][0], p[x][1]));
	}
    }	
	
    /* Create posts array */
    var posts = "<?php global $thePosts; echo $thePosts; ?>";
    posts = posts.split('),(');
	
    for(var x = 0; x < posts.length; x++){
	posts[x] = posts[x].split('|');
    }
	
    newMap('canvas', mapCoords, posts);
}

Here we've just added another variable and a for loop - notice this is above the newMap() call. We'll also alter this function to accept the posts variable. Now that we've got our variables set up, we can get into changing up our hefty newMap() function. But before we get to that we need to define a global variable that we'll use in the function, so go ahead and make a global variable like so:

var infowindow = new google.maps.InfoWindow();

This variable will be used to display an information window when the user clicks on a point, and we can utilise the handy API once again to do this. Now we can get into the juicy function to create our map:

function newMap(id, mapCoords, posts){
    var centre = (new google.maps.LatLng(51.44031275716014, 0.3955078125)),
	zoomLevel = 6,
        route,
        myOptions,
        map;

    route = new google.maps.Polyline({
        path: mapCoords,
        strokeColor: "#2324e4",
        strokeOpacity: .70,
        strokeWeight: 7,
        editable: false
    });
		    
    myOptions = {
        center: centre,
        zoom: zoomLevel,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };

    map = new google.maps.Map(document.getElementById(id), myOptions);
    route.setMap(map);
    
    // New code starts here
	
    function getInfoWindowEvent(marker, x) {
	infowindow.close()
	infowindow.setContent('<div class="infowindow"><a href="'+posts[x][1]+'"><strong>'+posts[x][0]+'</strong><br>'+posts[x][2]+'</a></div>');
	infowindow.open(map, marker);
    }
    
    var markers = [];
    
    for(var x = 0; x < mapCoords.length; x++){
        markers[x] = new google.maps.Marker({    
	    position: mapCoords[x],    
	    map: map,
	    icon: 'http://example.com/images/pin.png' // Remove this to use the default pin
	});
	    
	google.maps.event.addListener(markers[x], 'click', (function(x) {
	    return function(){ 
		getInfoWindowEvent(markers[x], x);
	    }
	})(x));			
    }  
}

Notice the comment about half way through - I'll begin explaining the code from there onwards.

First up we create ourselves a function called getInfoWindowEvent() - this will be used to move our info-window that we defined earlier around the map and to put our post content into it each time a point is clicked. The HTML inside the setContent() function is entirely up to you, so feel free to play with the styling and organisation of the code. Next up we create a new array called markers[] - this will hold every marker for the map. Then we have a for loop to iterate over every set of map coordinates that we have. Inside the loop we first create a new marker - the options here should be fairly obvious, but the icon one is entirely optional, remove it to use the default, well-known pin icon, otherwise supply a valid URL. Once we've got our array of markers we need to add event listeners to get ready for click events. The function we use simply calls the getInfoWindowEvent() function with the appropriate variables, namely the marker that has been clicked, and the index of that marker.

As a little side-note, if you want your own, custom pin on single post pages for the map, it's simply a matter of replacing img/wp-pin.png, and for greater customisation there's also wp_pin_shadow.png.

And that's it! You should now have a beautiful, dynamic map displaying all your posts - perfect for travel blogs!

WordPress: Load more posts on page scroll

Note: This article has been marked for a quality review and will soon be updated.

Although I don't visit archive pages very often, when I do I like it when I don't have to trawl through pages and pages of 10 posts using tiny navigation buttons at the bottom of the page. A great way to prevent this annoyance for your users is to use AJAX to dynamically append posts to the end of your archive list. To do this in WordPress we need to abstract the process of getting the list of posts and then use some Javascript (in out case jQuery aided) magic to load in our content. So lets get started.

First off we need to create a function that we can call to spit out a list of posts. Usually on an archive page we would use the normal WordPress loop to accomplish this, but in our case we need to abstract the loop into a separate function so that we can access it from any file - more specifically our Javascript file. We also need to be able to pass an offset value to this function to make sure we don't load the same posts every time it is called. This function is going to differ slightly depending on your markup for your archive page, but this is how it would look for Tom's Big Box:

function getArchives($count,$offset){
	query_posts('posts_per_page='.$count.'&offset='.$offset);
	
	$posts = array();

	if(have_posts()) : while(have_posts()) : the_post(); 	
		$img = post_image($post->ID);
		$commentsNo = get_comments_number();
		if($commentsNo==0){
			$comments = 'No Responses';
		}else if($commentsNo==1){
			$comments = '1 Response';
		}else {
			$comments = $commentsNo . ' Responses';
		}
		
		$item = '<li id="'. get_the_ID() .'">
			<figure class="vignette left">
				<img src="'. get_bloginfo('template_url') .'/scripts/timthumb.php?src='. $img->src .'&w=180&h=120" alt="'. $img->alt .'" />
			</figure>
			<h3><a href="'. get_permalink() .'">'. get_the_title() .'
			<p class="article-meta left">'. get_the_time('jS M Y',$post->ID) .' ~ '. $comments .'

<p class="extract"> '. get_the_excerpt() .' </p> </li>'; array_push($posts,$item); endwhile; endif; return $posts; }*/

Stick this in your functions.php file, and we can walk through what this code is doing. Firstly the two parameters that we it accepts are $count - which tells our functions how many posts we want, and $offset - to ensure that we don't load the same posts every time our function is called. We then send these parameters to WordPress's query_posts() function which will give us a list of posts. We then set up the $posts array to sold our data and begin iterating through the posts. I created a separate image variable to hold information about each post's image because I don't use WordPress's inbuilt image resizing, this is something which may not apply to you. After that an if statement creates a nice string based on the number of comments per post - this is because the inbuilt functions return only the number of comments or directly outputs to the document - something we don;t want. Then we load our content into the $item variable using whatever markup we need, and finally use array_push() to add our $item variable to the $posts variable, before returning the final $posts variable in its entirety.

Phew! Well that's most of the server-side stuff done, but before we can say goodbye to PHP, we need to do one more thing. We need to create a file to which we will pass our parameters, and that will execute the function we just created, and return the code we need. Don't worry, this is far simpler than the function above, let's take a look at the code:

require( '../../../../wp-load.php' );
$posts = getArchives(20,$_GET['offset'],false); 
foreach($posts as $p){
	echo str_replace("'","'",$p);
}

So, ignoring the first line for a moment, this file simply passes the $_GET['offset'] variable to our newly created function, and then iterates over the output, making sure to replace any single quotation marks to stop it from breaking. "But hang on Tom, what does that first line do?!" I hear you cry, well the first line makes sure we can access the function we just created, and for that matter all the inbuilt WordPress functions, so it is vital that you keep it. You will also need to change the path in the require() statement to ensure it matches the root directory of your WordPress install. Pop the above code in a file called get-posts.php and stick it in your theme's directory. And with that, we can say hasta la vista to PHP, and buongiorno to jQuery (that's right, I'm cultured).

Now, having made sure jQuery is included on your page, paste in the following code:

var halfWay = ($(document).height()/2);
var offset = 20;
var inAction = false;
var reachedEnd = false;

$(document).scroll(function(){
   if($(document).scrollTop() > halfWay && inAction == false){
       inAction = true;
		
       $('.article-list').append($('
').load('http://example.com/wp-content/themes/myTheme/get-posts.php?offset='+offset, function(){ offset = offset + 20; halfWay = halfWay + 1775; inAction = false; })); } });

Lets go through what this does. We have a function that fires whenever the page scrolls, and within that we compare the current scroll amount to half the overall document height, if it is greater (meaning that the user has scrolled more than half way down the page), and the variable inAction (I'll get to that in a moment) is true, it executes the following code. If the conditions are satisfied we then use AJAX to load in some more posts. Now it may appear a rather convoluted way to be doing so, but in my experience this way of handling an AJAX request of this type is the best. So for this method we send a request to our file that we just created in our theme's directory, and pass it the variable offset, when the content is loaded we run the embedded function which increments our offset variable by 20, adds a suitable amount to our halfWay variable. We then reset the inAction variable. This variable is used to prevent a massive build up of requests because of page scrolling, we use it because every time the page scrolls even a pixel, the function is called, so we don't want it to be called 3 times before we have a chance to offset the next post, otherwise we will end up with a huge amount of duplicate posts being loaded in. The conditions in the if statement will stop being satisfied after the last posts are loaded in because our inAction will stay in it's true state forever after one request for no posts means the success() function isn't executed.

And that's it! It might be a good idea to have a loading graphic at the bottom of you page when doing this to give some user feedback, and I would suggest also adding pagination just incase your server stops responding and leaves your users hanging. But aside from that, I think I covered the basics of how to implement the AJAx loading in of content. Oh and by the way, you will now also be able to generate archives anywhere on your site using the function getArchives(), meaning you will write less code in the long run - two birds with one stone!

Use PayPal for pay-per-post on WordPress.

Note: This article has been marked for a quality review and will soon be updated.

As you may know I like WordPress - it's a great platform for building websites on. As you may not know is, I like PayPal - it's an easy to way to safely make quick payments online. Now you may be asking what the hell I'm on about, have I been paid by WP and PayPal to go on about their services? Nope. Today I want to share with you an easy way to integrate these two fantastic services, to allow users of your site to pay each time they want to post on your site. For this we will be using the PayPal API, and a rather special page indeed which will allow your users to post from outside of the admin panel. If you didn't know, there is already a tutorial on doing so entitled - Publishing to WordPress from outside the admin panel, so go ahead and check that out, and then come back over here.

So first let's think about the theory behind this. We want users to go to our post-page, and then be asked to buy a token to post 1 article; we then want to send the user to PayPal, for them to pay us, and then be sent back to our site, where the same post-page now shows them everything they need to post an article. Sound good? Almost there, we need to make sure we prepare for something - say for instance the user has user paid, and there is a power-cut at their house, in that case they will have just lost the money they paid us, and will be rather angry that there is no way to get it back; so essentially we are covering for the user closing their browser without posting, having paid us. And for that we are going to enlist the help of the cookie monster! Nah, just kidding, we'll stick to just one cookie for now - which will be placed on the user's machine to tell our site that they have paid, and when they have posted we can alter the cookie to reflect that. So let's go ahead and start with our posting page, place this code above your form.

<?php
if($_POST['payment_status']=="Completed"){
  $paid = true;
}else if($_COOKIE['activeToken']=="true") {
  $paid = true;
}else {
  $paid = false;
}

if(!$paid){ ?>

// User hasn't paid

<?php }else {  ?>

So what do we have here? Well at the top we can see we are checking to see if a posted variable is equal to "Completed" - this is something that PayPal gives us when the user has completed their transaction. We then set the $paid variable equal to true. Next we check a cookie to see if it's value is "true", and once again if this is true, we set $paid equal to true. And finally if neither of the above conditions validates we simply set the variable equal to false. Next we have an if statement which runs if $paid is equal to false - using the handy ! just before the variable. Now, after the else { statement is where you will want to put your form for posting an article, but not before you enter our crazy AJAX/Cookie-goodness code which follows.

<script type="text/javascript">
  $(document).ready(function(){
    var dataString = "cval=true";
    $.ajax({
      type: "POST",
      url: "<?php bloginfo('template_url') ?>/scripts/cookie.php",
      data: dataString,
    });
  });
</script>

// Your HTML goes here

<?php } ?>

Woah what the frick is that?! I hear you shouting. Right well let's go from the top. First off we can see that we are using JavaScript, and also jQuery - so make sure it's included, and we are also waiting for the DOM to have fully loaded everything before beginning our code. Then inside of this code we are setting up a variable named dataString and setting it's value to "cval=true" - more on this soon. Then we create an AJAX call using jQuery which will POST to a URL which is in our theme folder in the scripts sub-folder, to a file named "cookie.php" the data in the variable dataString. Make sense? Hopefully it does. Now you might be thinking, but wait a moment, I don't have a file called cookie.php, and even more annoying is that I don't even have a folder called scripts in my theme directory. Well don't worry - go ahead and create a new file called cookie.php in your theme directory, and if you tend to store scripts in another directory like me, go ahead and move it into that directory - just be sure to update the URL there - and if you didn't know that handy bit of code that reads <?php bloginfo('template_url') ?> just spits out the URL of your theme's directory. Now, copy and paste the following code into your new file.

<?php
$expire = 60 * 60 * 24 * 60 + time();
setcookie('activeToken', $_POST['cval'], $expire,'/');
?>

So what does that code do? Well the first line sets up a variable named $expire which holds the value of the date two months from today using some basic maths. Then we use the PHP function setcookie() to create a cookie in the format setcookie(name,value>,expiry date,directory) - now you might be wondering what that final "directory" bit is about - put simply that is the location where your cookie can be read from - if you leave out this parameter you won't be able to access your cookie, except from the cookie.php page you created it on - not ideal.

Now we have a good thing going now, but we need to think about when the user has submitted the form, and posted an article - we need to alter the cookie to tell our site that the user has used up the token he bought - simply by using the same JavaScript code that we used above, but changing "cval=true" to "cval=false". Now if you submit your main form using AJAX you can simply add this function in the success: parameter, otherwise you might want to do any number of other things - using jQuery's submit() function like so.

$("#myform").submit(function(){
  var dataString = "cval=false";
  $.ajax({
    type: "POST",
    url: "<?php bloginfo('template_url') ?>/scripts/cookie.php",
    data: dataString,
  });
});

Or you could stick the code on the page to which new post data is posted (new-post.php). Either way, you just have to ensure, that when the submit button is clicked - the cookie is set to false.

Now we've done nearly everything without having touched PayPal - the subject of the next section of the article; but before we begin I want to eradicate any preconceptions you may have about working with PayPal. Many people think it will be rather difficult to use PayPal in the way I am going to describe - that because you are dealing with people's money there is a greater margin for error. But this isn't the case - because at the end of the day, PayPal is the one going all the ground-work, and if it doesn't like what you are doing - it's going to tell you, so don't worry - and just go crazy! So go ahead and replace that comment we created earlier "//User hasn't paid" with the following code - kindly provided by PayPal.

<form action="https://www.paypal.com/cgi-bin/webscr?return=<?php the_permalink(); ?>&cpp_header_image=http://example.com/myHeaderImage.jpg&cbt=Return and post an article&rm=2" method="post">
<!-- Identify your business so that you can collect the payments. -->
<input type="hidden" name="business" value="name@example.com">
<!-- Specify a Buy Now button. -->
<input type="hidden" name="cmd" value="_xclick">
<!-- Specify details about the item that buyers will purchase. -->
<input type="hidden" name="item_name" value="Job Post Token">
<input type="hidden" name="amount" value="1000"> <input type="hidden" name="currency_code" value="USD">
<!-- Display the payment button. -->
<button value="Buy Posting Token"><span>Buy Posting Token</span></button>
<img alt="" border="0" width="1" height="1" src="https://www.paypal.com/en_US/i/scr/pixel.gif" >
</form>

So above, we have a form with a heck of a lot of information in it, but if we break it down, it's actually rather simple. Firstly we set up the form and tell it to post to PayPal's website - we also specify a number of variables to post along with it - the values of which are highlighted in bold. Firstly we have return - where the user will be returned to, once payment has been completed, for this we use the page's URL, helpfully provided to us by WordPress. Then we send it something called cpp_header_image - a 90x750px image which will be used in the header - using an image of your own will make the user feel more comfortable, and looks more professional. Then a variable called - cbt - which is the text used on the button which will send users back to the return URL specified above. The last variable is to do with PayPal posting values back to our page - including that of the handy payment_status - so don't change that.

The next value highlighted in bold is an email address - this is where you should enter the email address of the PayPal account holder to which all transactions will be credited. Next is the value "1000" - which is the amount you wish to charge your users to post - in this case $1000 - may be a little pricy - you decide. The currency is also set below and is currently set to US Dollars. PayPal provides a full list of variables for you to use, which is worth checking out for further customisation.

And that, ladies and gentlemen, is that! So now hopefully you can see just how easy it is to integrate PayPal with WordPress. As always if you have any questions/problems with the tutorial, leave a comment and let me know what you think.

Edit
For those of you who wish to make visitors to your site pay per viewing of each post you would need the following code structure alongside the code above.

<?php
if($_POST['payment_status']=="Completed"){
  $paid = true;
}else if($_COOKIE['activeToken']=="true") {
  $paid = true;
}else {
  $paid = false;
}

if($paid){ ?>

// User had paid, therefore enter the WordPress loop for the post

if(have_posts()) : while(have_posts()) : the_post();

//etc

<?php }else { ?>

//User hasn't paid, so display the payment options

<?php } ?>

Check out the codex for more information on the loop.

Screencast #4 – Creating a WordPress Theme – Part 2

In part two of this tutorial I show you how to finish off creating a basic WordPress theme, demonstrating the creation of a single post page as well as looking at how the commenting system works. Also in the video is how to create custom page templates and then apply them to different pages, as well as using theme options to enhance the user experience; and of course "widgetizing" the sidebar.

Here is the link to the Nettuts article.

Download the code
View the demo

Screencast #3 – Creating a WordPress Theme – Part 1

In part one of this tutorial I show you how to get started creating a WordPress theme, explaining all about the core files and how WordPress works. I'll show you how to install WordPress and how to convert existing markup into a theme. In the tutorial I develop a theme named "Curiosity" - the markup for which can be found below the video. Part 2 is coming soon so stay tuned!

Download the code
View the demo

Publishing to WordPress from outside the admin panel

Note: This article has been marked for a quality review and will soon be updated.

I recently finished up a theme for which I had to allow users to post to WordPress from outside the admin panel. Now at first you may wonder why anyone would want to do such a thing, but let me tell you of my scenario. Basically I was creating a job board whereby users could post a job from a specific page - this meant that the numerous custom fields in operation could be handled in a rather aesthetically pleasing fashion and it would be a lot simpler for the user to get their job listed. Now the reason I'm posting this article is because this subject isn't well documented and I had to play around for quite a while before I could get it to work, so I hope that I can save you some frustration in sharing my code.

So what do we have to do first? Well we need to replicate the core features of the new post page in the admin panel of WordPress, this means replicating things such as the title and content fields, the category options, and the tags area. So set up all the required fields and any custom fields you want to include. Once you've done this you will need to create a separate file to post the information to, let's call it new-post.php. Set your form to post to this file, and then paste in the following code.


$title = stripslashes($_POST['title']);
$body = $_POST['body'];
$rpcurl = $_POST['rpcurl'];
$username = $_POST['user'];
$password = $_POST['pass'];
$category = $_POST['category'];
$keywords = $_POST['tags'];
$encoding = 'UTF-8';

$title = htmlentities($title,ENT_NOQUOTES,$encoding);
$keywords = htmlentities($keywords,ENT_NOQUOTES,$encoding);

$content = array(
'title'=>$title,
'description'=>$body,
'mt_allow_comments'=>0,  // 1 to allow comments
'mt_allow_pings'=>0,  // 1 to allow trackbacks
'post_type'=>'post',
'mt_keywords'=>$keywords,
'categories'=> array($category=>$category),
)

);
$params = array(0,$username,$password,$content,true);
$request = xmlrpc_encode_request('metaWeblog.newPost',$params);
$ch = curl_init();
curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
curl_setopt($ch, CURLOPT_URL, $rpcurl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 1);
$results = curl_exec($ch);
curl_close($ch);

Right, now that's quite a lot of code, allow me to explain. You can see all of those variables at the top - these are to be use further down and are given the values of what's posted to them. Title, body, category, and keywords are self-explanatory, however there are a number of other variables which appear to require some post variables - so what are they? $rpcurl is simply the ping-back URL of your blog - which is a URL that allows others to interact with your blog. The username and password variables must be valid credentials for the blog - this is because WordPress needs to verify that the person posting the post is allowed to do so. And finally the encoding variable is simple the way in which the content should be encoded - the default and most common is simple UTF-8 - and doesn't need to be changed.

So you know what the variables are, but how on earth do you get them to the file? Well personally I used AJAX to submit the form and so just sent the data in a data-string, but if that sounds too much like hard work, feel free to just use some hidden fields. To access the required data you can use the bloginfo() function for things like the "pingback_url". Now one thing that will require user input is the password variable, this is because it is impossible to obtain the user's password as it is stored as an encrypted hash, so I'd recommend that you add it as a security feature where you ask users to enter their password before posting - that way it'll be accessible to you.

The rest of the code simply posts all the info to the actual blog, and uses the ping-back URL to do so by inserting all of those lovely variables into place and then sending it over to WordPress to do all the hard work.

While this is a bit of an obscure function I think it's nice to know it can be done, and I hope this article can save some people the hassle that I had to go through to get the correct method and syntax.

 

Update

It has come to my attention that the method listed above might be a little hard to integrate into a WordPress theme, so below is the code for a form with which you could use the above method, to post to WordPress from outside the admin panel. Let's get started with the form.

<form id="post" name="post" action="post.php" method="post">

<label for="title">Title</label>
<input type="text" name="post_title" />

<label for="desc">Content</label>
<textarea name="content"></textarea>

<label for="category">Category</label>
<input name="category" type="text" />


<label for="title">Tags</label>
<input type="text" name="post_tags" id="tags" value="e.g. Graphic, Designer, HTML" onfocus="if (this.value == 'e.g. Graphic, Designer, HTML') {this.value = '';}" onblur="if (this.value == '') {this.value = 'e.g. Graphic, Designer, HTML';}" />

<p>Please verify the details above and then enter your password to complete the process.</p>
<p>&nbsp;</p>
<label for="password">Password</label>
<input type="password" name="password" id="password" />
<input type="submit" value="Submit" />
</div>
</form>

So that's a pretty standard form to which you can do whatever you like, but not the names of the fields as they will be important when we come to using the data stored in them. Next I'm going to use AJAX to post the form to the code which will post the WordPress, for the sake of this tutorial I'll assume that the code at the beginning of this tutorial is in a file called post.php. So go ahead and stick this somewhere on your page (Note: You will need to include jQuery for the following Javascript to work.

$("#post").submit(function(){
	var title = $("#post input[name=post_title]").val();
	var body = $("#post textarea[name=content]").val();
	var category = $("#post select[name=category]").val();
	var tags = $("input[name=post_tags]").val();
	
	var pass = $("#password").val();
	
	if(title=="" || body=="" || pass==""){
		alert("Please fill in all of the fields!");
		return false;
	}else {
		verify = true;
		
		var dataString = 'title=' + title + '&body=' + body + '&rpcurl=&user=user_login ?>&pass=' + pass + '&category=' + category + '&tags=' + tags;
		$.ajax({
			type: "POST",
			url: "post.php",
			data: dataString, 
		}   		
	});
	return false;
}

Okay then what do we have here? Well first off all the code is wrapped in a submit() function, which waits for the form to be submitted, and then executes the code inside. Just below this we assign the values of the inputs from the form, to variables, and then check to see if some of the fields are empty, the ones that are important that is. If any of them are empty then we alert the user and stop the form from going submitting. However if it's all good we then use the jQuery AJAX function to post all the information we have to our post.php file to be processed. Notice that we ask the user to verify the information entered by asking them to enter their password - this is a sneaky way of grabbing their password, and allows us to proceed with processing the post.

And that's that! Hopefully the above code has helped you to understand better how to integrate the code into a WordPresss environment, and if you're a little confused by the AJAX or just don't want it in your code, feel free to just make the form post directly to post.php, and you should be good to go.

Screencast #2 – Creating a Comment Preview in WP

So it's been a while since I've done a screencast, but here it is, number 2! In this screencast I'll show you how to create a comment preview section in WordPress which dynamically loads user information and updates as you type! For it I use the trusty jQuery library and a little bit of PHP code to spice things up. See below the video for the code used, and enjoy!



The comments.php code:

<div id="preview-comment">
<br />
<h4>Comment Preview:</h4>

<div></div>

<li>

<div id="div-comment-12">

<div>

<?php if(is_user_logged_in()){ global $current_user; get_currentuserinfo(); } ?>

<img id="avatar-preview" width="64" height="64" src="<?php if(!is_user_logged_in()){ ?>http://www.gravatar.com/avatar/<?php }else { echo "http://www.gravatar.com/avatar/" . md5($current_user->user_email); } ?>" alt="Avatar">

<cite><a rel="external nofollow" href="#"><?php if(!is_user_logged_in()){ ?>Mr Nobody<?php }else{ echo $current_user->user_firstname; } ?> </a></cite><span>says:</span>

</div>

<div>
<a><?php wp_reset_query(); echo gmdate("F j, Y \\a\\t g:i a ") ?></a>
</div>

<p>This is an example comment.</p>

<div>

<a>Reply</a>

</div>
</div>

</li>

<br />

</div>

And the Javascript:

<script type="text/javascript">// <![CDATA[
$(document).ready(function(){

$("#commentform input, #commentform textarea").focus(function(){
$("#preview-comment").slideDown();
});

$("#commentform input, #commentform textarea").blur(function(){
if($("#commentform #author").val()=="" && $("#commentform #email").val()=="" && $("#commentform #url").val()=="" && $("#commentform #comment").val()==""){
$("#preview-comment").slideUp();
}
});

$("#commentform #author").keyup(function(){
$("#preview-comment a.url").text($("#commentform #author").val() + " ")
});

$("#commentform #author").blur(function(){
$("#preview-comment a.url").text($("#commentform #author").val() + " ")
});

$("#commentform #email").blur(function(){
$("img#avatar-preview").load('/scripts/md5.php?m=' + $("#commentform #email").val());
});

$("#commentform #url").keyup(function(){
$("#preview-comment a.url").attr('href', $("#commentform #url").val());
});

$("#commentform #url").blur(function(){
$("#preview-comment a.url").attr('href', $("#commentform #url").val());
});

$("#commentform #comment").keyup(function(){
$("#preview-comment p").text($("#commentform #comment").val())
});

$("#commentform #comment").blur(function(){
$("#preview-comment p").text($("#commentform #comment").val())
});

});
// ]]></script>

And the md5.php file:


<script type="text/javascript">

<?php $hash = md5($_GET['m']); ?>

$("img#avatar-preview").attr('src','http://www.gravatar.com/avatar/<?php echo $hash ?>');

</script>

Note: Bear in mind that changing the comments form will involve changing the code above.

Squarespace is great, but…

Disclaimer: I think Squarespace provides an excellent service and I don't hate them!

So there has been a lot of hype recently surrounding the service Squarespace recently. And I read an article in .NET which was an interview with the founder, but when I finished reading I realized that I disagreed with some of the points he raised in the interview. So basically the people behind Squarespace think that the future is them, that is, people won't go to services such as WordPress and Drupal to create their sites, instead relying on their excellent technology. And this is where I disagree.

Now don't get me wrong, I'm told that Squarespace is a fantastic service, but at the end of the day it is lacking in a number of things. Firstly what's with he lack of themes? I mean it's all very well and good either being a noob and just using a default template, but what happens when someone wants to create something totally different? Now I know that their examples page features an array of interesting sites that look professional, but I think the lack of some sort of theme marketplace is a terrible missed opportunity. On top of this, although they boast the up most customization, you are still restricted to a grid system, and despite what many say, when I visit a website I can, in most cases, instantly tell if it is powered by Squarespace.

But the thing which annoys me the most is this. If they are to take over the blogging world and replace WordPress, are they going to stay on their own hosting? Because if they do, then they're just plain stupid. Their best package has a monthly bandwidth limit of 400GB. Now to put this into perspective let me show you some stats from a popular web design blog - Spoon Graphics - which is really fantastic, has a monthly bandwidth of 940GB. So that's the $50/month package out of the window.

One way in which the service does excel is when it comes to comparing it to similar services, i.e. WordPress.com and Blogger. There's no denying that the guys have done a fantastic job on the who visual editor and I think the design is really slick. But to be quite honest I feel that the claim that they will soon be ubiquitous is outrageous.

So just to finish, let's create a simple situation. You want a blog, and in our case there are two solution. Number one, Squarespace, and number two WordPress self-hosted.

Squarespace

$600 for 5GB storage and 400GB bandwidth. Great. You can then edit the theme as you choose.

WordPress

$240 for hosting + $32 for a really cool theme from ThemeForest, and WordPress is a free download. And we'll add $100 to account for the setup time just to be nice. That's $372. And you get to customize every aspect of everything ever anywhere 🙂 Obviously you have to know code, but if you've got a cool enough theme, you should be alright.

I know which one I'm going to pick, every time.

How about you? Have you had a really go experience with Squarespace? I'm genuinely interested to know.

Replacing the […] in WordPress

Some of you might be wondering what I mean by the [...], well I am of course referring to the symbol generated by WordPress upon calling the function the_excerpt(). Now personally I really dislike the symbol which is generated as it often doesn't fit with my design, and I always prefer to have an ellipse - ... followed by a link to continue reading - but how on earth could we go about doing this? Does the answer lie in using jQuery to find and replace this horrendous symbol? Perhaps we need to add some arguments to the the_excerpt() function?

No, it's far simpler than that.

All that needs to be done is the addition of some code to the functions.php file in your theme directory. So head over to this file (if it doesn't exist, create it) and go to your next free line, and copy and paste the code from below.

function new_excerpt_more($post) {
	return '...</p><a href="'. get_permalink($post->ID) . '">' . 'Continue Reading...' . '</a>';
}
add_filter('excerpt_more', 'new_excerpt_more');

So the above code replaces the default [...] with something that looks like "... Continue Reading...", where the continue reading text is a link to the article itself. You could replace this with whatever code you like and have bundles of fun if you like that kind of thing. Just remember to not leave any blank lines at the bottom of your functions.php file as this can cause errors later down the line.

Making dynamic dropdowns in WordPress

Note: This article has been marked for a quality review and will soon be updated.

The latest craze which is sweeping across WordPress theme development is that of adding drop-down menus to menu items to display sub-pages. Now while this is all very simple if we take a couple of unordered-lists and stick them in the header, making this process dynamic is a little more complex. For this we are going to use jQuery and WordPress's parent and child allocation feature within pages (don't worry, that's just a fancy way of saying it ;)).

So to begin with we are going to need to set up our pages. To do this, head over into the page admin section of your site, and create a page that you would like to have sub-pages of. So for instance I created a page called "About". Then repeat this process and create another page that you want to be in the drop-down under your main page. But before you hit "Publish", you will need to head down to "Attributes", just below the "Publish" button. Under parent, select the main page that you just created from the drop-down box, and then hit "Publish". You can do this as many times as you like, but when you are happy with your structure, head over to you blog's home-page and have a look at the menu.



Now as I have already styled my menu items with some basic CSS, it looks very odd indeed. Yours should look similar, but depending on your CSS, looks will differ. Anyhow, let's think about how we are going to get around this issue of aesthetic dismay! We need to apply the same sort of menu styling to our sub menus, but to avoid odd issues later on we could do with having a class applied to our sub-menu (you could do it with pure CSS, but this way makes it look cleaner). And for that we are going to use some nifty JavaScript. So copy and paste the code below the code that creates your menu.

$("li.page_item ul").addClass("sub-menu"); 
$(".sub-menu").parent().addClass("parent");                

So now we have a class of "sub-menu" applied to all the sub-menus that are present on our page and we are free to manipulate them how we like. Now bear in mind that we could use a selector that just got all unordered lists within unordered lists to access our sub-menus, but this way is far cleaner in my opinion. And now that we have this class applied we are free to manipulate the look and fee of the sub-menus. For this we will use some simple CSS, now some of this CSS will be style-specific, but bear in mind that things like the position property are core to this effect working.

.sub-menu {
	display:none;
	left:0;
	position:absolute;
	top:26px;
}
	
.parent {
	position:relative;
}

.sub-menu li {
	float:none !important;
	margin:5px 0 0 !important;
	opacity:0.8;
	width:140px;
}

Now you should have an invisible sub-menu that is set to appear below the parent item. Notice that I lowered the opacity so that we get a nice overlaying effect.

Next we will use a JavaScript plug-in to determine when the user hovers over our menu item. The reason we are using a plug-in is because it really simplifies the code and makes it more efficient, trust me I tried to do it without the plug-in, and it isn't as simple as you may think! The plugin we will be using is HoverIntent - which is a handy little thing based upon jQuery's hover() event. So go ahead and stick that script into your header and then go below the menu items to add some more JavaScript.

$(function(){

    	var config = {    
         	sensitivity: 3, // number = sensitivity threshold (must be 1 or higher)    
         	interval: 100,  // number = milliseconds for onMouseOver polling interval    
         	over: doOpen,   // function = onMouseOver callback (REQUIRED)    
         	timeout: 200,   // number = milliseconds delay before onMouseOut    
         	out: doClose    // function = onMouseOut callback (REQUIRED)    
    	};
    
    	function doOpen() {
        	$(this).addClass("hover");
        	$('ul:first',this).fadeIn();
    	}
 
    	function doClose() {
       		$(this).removeClass("hover");
       		$('ul:first',this).fadeOut();
    	}

    	$("ul#nav li").hoverIntent(config);
    
});

Lastly let's attend to that class we added there with some nifty CSS which will ensure that the drop-down will always be on-top, unless you use something like a light-box plug-in later on.

.hover {
	z-index:9999;
}

And that should just about do it! After implementing that code and applying your own styling you should have a menu that looks something like the one below.