London Dog Calling

I’m really excited to be making my first trip ever to London next month (too late to meet up with Scott or Brian) for a few days of NMC meetings. I have set aside a few extra days to be a tour dog.

But I am a total n00b in my London knowledge– so I am asking to crowdsource my free days here (August 19-21). Give me some ideas what to see/do, where to stay, etc, or maybe arrange a meetup? Leave me some tips over at

http://cogdoghouse.wikispaces.com/LondonCalling

/me wags in appreciation.

It’s All Cat Videos

If I was teaching a class in logic, I would frequently use the Chronicle of Higher Education as a rich resource– of faulty logic. Hardly a day passes in the feed reader without some preaching headline that one cannot get from point A to B without a psychic leap of thinking.

Try this one on.

YouTube Better at Funny Cat Videos Than Educational Content, Professors Say
While many students turn to YouTube when looking for help with their homework, it can be hard to find good-quality educational clips there, according to two professors who did a preliminary analysis of several video search engines.

The research was typing the word “mitosis” into various video search sites, and analyzing the top 20 results. And thus, in finding not prime source materials, ergo, everything is Cat Videos.

Or, Because You Can Find Some Crap in a Large Pile, the Whole Pile Smells Like Crap.

“You go into YouTube and you put in “mitosis,” you’re going to get 3,000 videos back,” said Mr. Bell. “But no one looks at all of that. You’re only going to look at the top 10, so the ranking algorithm is really important.”

This feels like a sentiment repeated often enough that people assume its true. Sure, there is data on general search activity that many people dont go past the first few, but do we truly know that students seeking resources fall that short? If I have to learn something about mitosis, and I come up with 20 Funny Cat Videos, am I really going to shrug and say, “Oh well, better see the latest Lady Gaga vid?”

And even if this is the dominant search pattern, this “research” says nothing about the value of web video- it says more about the shortcomings of a shotgun search strategy- toss one key word and pull the slot machine lever.

Furthermore I can’t find anything to support the professors even mentioning Cat Videos (Actually, I cannot find much on them at all, no links in the Chron’s web page).

Let’s see…Jeffery Bell’s research expertise is “molecular mechanisms that control development of animals, the role that these molecular mechanisms have played in evolution, and the genetic diversity and structure of local animal populations” and Jim Bidlack has been working on “Weed Control in Pigeon Pea – Wheat Cropping Systems”. Apparently, this is the forefront of web search mechanics and informatics?

Two experts in biology looked at web videos for keywords in their discipline, and they found it wanting. Therefore, the only thing YouTube is Funny Cat Videos.

In their estimate, the researchers suggest student made videos are less valuable than ones their profs made– “perhaps because those videos attracted more comments than professionally made ones”. Or could it be the ones their professors made… suck?

The Chronicle laps up the opportunity to be perpetuating stupid stereotypes that support their downward peering viewpoint.

So besides Funny Cat Videos.. hmmm, what do we have?

Well there is the virally spinning Old Spice Guy, if you have been living in a media cave, this commercial turns the old whistling guy in the raincoat inside out

16,000,000 views and climbing, as a carefully planned and executed media campaign, it hits the modern message square on. I like its swagger. And.. hmmm, no funny cats.

But what people like old fuddies in the Chronicle Tower miss is that this is not just broadcast. It is a participatory media.

So there are parodies. And I would be that the Chronicle types would look down their noses and snipe how shallow it is to redo an existing piece. “There is no creativity nor originality any more, its just more Funny Cat Videos.”

There are many flavors of creativity, and if you look a little more carefully about many parodies, and what it takes to produce an effective one, its hardly flicking on the camera on Sweet Kitty and waiting for her to fall in the toilet.

Look into the eyes of New Spice: Study Like a Scholar, Scholar and tell me this is the equivalent of Funny Cat Videos:

The video celebrates a swagger in the Harold B. Lee Library… at Brigham Young State University. The team that produced it, two employees and a 10 student team, documented the behind the scenes in a blog (is there anything more perfect for a succinct web site than a free blog platform?).

The production quality here is on par with the original. Check out the production photos on that blog again. There had to have been an incredible amount of planning, coordination, editing, team effort to pull it off. No simple feat, No cat in sight.

Nothing but Funny Cat Videos, my arse, Chronicle.

The best thing about mocking the Chronicle is… they never respond. Unlike the rest of the internet when a company, product, brand is mentioned and people respond to a snarky blog post… The Chronicle stands aloof. They never wade into the comment sludge their posts generate. They in fact, do not get the participatory nature of the Second Web. It’s just pronouncement. They remain up in their towers, arms crossed, peering deep and far into the abyss we all live in… and cast their Funny Cat Video conclusions on the waves.

And besides… some of those cat videos are pretty damned funny. At least they make more logical sense the the writings at the Chronicle.

Amazing Stories Took a Wrong Turn At Albuquerque

I’m going to leave it to John Ittelson to tell the full story, but I am a bit embarrassed to all my friends and colleagues who responded to my call for More Amazing Stories of Sharing.

Like the wascally wabbit, there was a mixup, and the event at which this new version was supposed to be presented… did not get us in the schedule.

Eeeek. Will this be the last time I can pull out the Tom Sawyer Paint My Presentation Fence trick?

I don’t think so. You see… I got this great new collection of stories, they are really good, and I can still share them with you. In fact, you, me, and everyone else does not need a conference to present something- we can share these anytime, without the bad conference hall fluorescent lights, ugly test pattern hotel carpet, and without the Dreaded Conference Chicken.


cc licensed flickr photo shared by MrGluSniffer

Nope, we dont need no stinkin’ conference…

So, I am here to present to you, the newest set of Amazing Stories of Sharing, the 2010 version, which like last year’s, you can watch individually or explore them all in the CoolIris format.

I really want o thank the following folks for sharing their stories, all are worth sitting down and listening to… and then picking yourself up and doing something similar.

  • Dean Shareski and Darren Kuropatwa who shared a pair of stories on the tail end of their trip to the BLC10 Conference
  • Students in led by Dave Cormier’s class on Educational Technology and the Adult Learner (ed366). Be sure to see the group document the class wrote on this topic
  • Rod Lucier (aka The Clever Sheep) for just sending a story that is not only Amazing for how hos resource got shared in Sweden and back again, but also for the rich way he shot his video.
  • Robin Neal (Beaver Country Day School, MA) and
    Darren Kuropatwa (a two-fer) for their story on how one wiki influenced another.
  • Tim Lauer, the most Amazing principal a scholl could dream of, for his story of Ted’s bee sting, in the very early web days, becoming a point of connection between his elementary school students and a bee expert in Arizona.
  • Martin Weller cites the case of “Everyday Amazingness” where as one of presentations became “made of openness” through the power of sharing.

Thanks again, and all of you have the ticket to call me in for a return favor.

Now, about that turn in Albuquerque…. I Tawt I Saw a Puddy Cat….

Dominoe’s Day


cc licensed flickr photo shared by cogdogblog

Today (July 24) is my day to honor my first and most special dog, Dominoe, who left this world in 1993. Is it really 17 years? That’s a full generation. And it was long after that that I told her story like 50 million times.


cc licensed flickr photo shared by cogdogblog

It’s been a long way too since Rossridge Apartments, in Baltimore, the place I was living when I took her in, when my room-mate Kevin literally called me and said, “do you want a dog?” This was a cusp of time in many ways, leaving the life of a place I grew up in and hardly left, and turning that whole leaf less than 10 monts later, by packing all my stuff, including Dominoe, into a 1973 Ford Maverick and driving it all the way to Arizona.

You should never forget your first dog. Or your last. Or all the ones in between. I know I don’t.


cc licensed flickr photo shared by cogdogblog

Keeping the memories flickering (and flickring).

Thanks again, Dominoe….

A Non Crappy WordPress Audio Player

There are tons of plugins available to embed audio/video in your blog.

The things I don’t like with many of them are (a) they usually use “short codes”- things you hand write in brackets to indicate the location and source for the media (plus some options. Writing these means have to remember the structure, but more so, if you ever have to change to a different plugin down the road, you are left with short codes that might not mean anything.

For years I had use Anarchy Media Player for the simplicity that all you had to was create a normal hyperlink to your media, and Anarchy would replace it with the suitable player. However, I had some major conflict issues with Anarchy last year, I noticed its javascript was hanging on loading, and in term hung my entire blog. I zapped it.

For some reason I was thinking today about a new project where I wanted to have a simple embeddable audip player. Long ago I had used Taragana’s player, which makes use of the delciious.com PlayTagger. It too was simple, it replaced any hypertext link to an MP# with a small svelte player.

But I poked around the WordPress Plugins site, and landed on the WPaudio MP3 player- and got grabbed at the lead in:

All the other WordPress audio players were crappy or ugly so I made a better one.

Plugin with attitude, bring it on! It works great, you can make it so any href tag that points to an MP3 uses the plugin (which is what I did), or you can make it so any links with a special css class are displayed with the player. I also modified the CSS a little to match my styles.

So for the blog post where I have audio of me explaining Twitter to my Mom, the hyperlink for this is written like regular HTML

<a href="http://cogdogblog.com/wp-content/audio/cowboy-glimmer.mp3">
Cowboy Glimmer)</a>

So if I ever get rid of the plugin at least I have valid code. And It Just Works. Here’s a little sample, I think this is just some quick track I made in GarageBand- just give the player a click.

Cowboy Glimmer

I am sure someone will comment with some other solution or better approach! But I like this one so far.

Roundup WordPress 3.0 Custom Content Type


cc licensed flickr photo shared by prettywar-stl

Oh what a tangled blog I weave mangle. I thought it would take a few posts and days to document the work I started in April to use the then beta features of WordPress 3 to develop the NMC’s MIDEA web site. And just trying to write up the last few, I can see it is a heap.

So while I have maybe two more to write up, I wanted to make this to be the hub post to all the others. You can also find these (and whatever comes in the future) tagged here as wp3 http://cogdogblog.com/tag/wp3/.

Also, since the code got long in the posts and because someone nicely asked, I packaged up all the template files described into a single collection. A few non-essential layout elements are removed, but functionally, it is ripped from my themes directory. You can get the most up to date version at
http://cogdogblog.com/code/wp3-midea-sample.zip

This is complex stuff; I just kept banging my head against the keyboard until it worked. I’m sorry but I cant really debug your specific projects- but am putting all my work here on the freebie table.


cc licensed flickr photo shared by BrittneyBush

Pluto Gets No Respect

After a bunch of lead weight code riddled posts, let’s lighten it up. I can always count on GraphJam for some laughs, but also for the clever ways people find to represent ideas, thoughts, jokes, in graph form.

Yes, when I was a kid, Pluto was a planet, but scientists have kicked the cold rock out of the planet club.

And as the post cites, the best comment (or as GraphJam lists them, “TPS Reports”).

Graphite Mickey Mouse says, “Of course he’s not a planet! He’s my DOG!”

I WANT YOU TO MAKE ME A PLANET!


cc licensed flickr photo shared by cogdogblog

Pinning WordPress 3 Custom Content to the Map (b)


cc licensed flickr photo shared by QualityFrog

In a previous long winding post, Dressing up and Displaying WordPress 3 Custom Post Content (a), I tried to document the first part of my WordPress 3 site I manipulated the new Custom Content types. It seems it takes longer to explain that to build, and in the end, I’m wondering if it is even explained.

Leading up to this, I began by overviewing the plans for a new web project, we set up the places to create the new content types, and introduced the benefits using child themes. Then we dove headfirst into the code to create the interface and data elements to add/edit the custom meta data for each of the three content (post) types.

Getting your content onto your site is a matter of manipulating The Loop and then writing new side loops where needed to put things on the sidebar. For this site, MIDEA, the dissected part from the last post was the construct for a gallery page of Project content types and then a display page for a single project.

In this post, I am going to describe what I did about the second Content type, Organizations, in which we track information like web site, Facebook, and twitter urls, street address– and what turned out to be neat, storing a latitude and longitude for each organization so we could generate a dynamic map showing the location of an organization.

I’m not going to detail as much on the template (org.php) that displays all the organizations – there’s not much that is different from the ground covered in the last post. You can explore this page at http://midea.nmc.org/org/

(A) The main part of the page is an A-Z listing of all the organizations, using the same abbreviated format used elsewhere ion the site. Like we did do the A-Z project listing, we will use the custom mySQL call to the database so we can avoid the alphabetizing on organizations whose name starts with “The”.

(B) This block on the sidebar lists to other organization pages that will be described below- one generates a google map showing locations of all organizations, the other links provide a list of all the organizations that have Facebook or twitter presences.

(C) The rest of the sidebar is standard looping stuff for sidebars. One lists 3 blog posts from a category we call “Ideas”, the next is the 2 from “News” category, and the last is a random pul of three projects, using logic covered in the previous post in this series.

So generating the list of organizations follows directly from the work we did on projects.

<?php
global $wpdb;
global $post;

// custom query to get posts of typer org order by trimming the leading "The " in a title
$orgposts = $wpdb->get_results("SELECT wposts.*
FROM $wpdb->posts as wposts
WHERE wposts.post_type = 'org' and wposts.post_status='publish'
ORDER BY TRIM(LEADING 'The ' FROM wposts.post_title)", OBJECT);
?>

<?php if ($orgposts): ?>

		<?php foreach ($orgposts as $post): ?>
		<?php setup_postdata($post); ?>

<h2><a href="<?php the_permalink() ?>" rel="bookmark" title="<?php printf(__('Permanent Link to %s','gpp_i18n'),the_title_attribute('echo=0')); ?>"><?php the_title() ?></a></h2>
<?php get_the_image(); ?>
<?php the_excerpt(); ?><br /><a href="<?php the_permalink() ?>" rel="bookmark" title="<?php printf(__('Permanent Link to %s','gpp_i18n'),the_title_attribute('echo=0')); ?>">Learn more about <?php the_title() ?>...</a>
<div class="clear"></div>
 <?php endforeach; ?>
<?php endif; ?>

Lines (05-09) set up the database query to select all organization content, and do the trick to order it by the title after trimming any leading “The” in the title. We then walk through all the results, and lines (17-20) output the content.

Now we turn to making a template to display a single organization, using as an example, the Amon Carter Museum from Fort Worth, Texas.

(A) This is the main “post” for this content type, whatever we put in the blog editing box. It comes with the built in Loop, so we dont have to doctor it up at all.

(B) As an addition to the main content, we’ll do a second Loop to list all the projects from this museum.

(C) The top end of the sidebar displays the icon associated with the organization/post (using the built-in in WordPress “featured image” functionality). This is followed by links to the organization’s web site, Facebook page, and twitter account, if any of these data fields are present (they are optional, some of the organizations don’t have them all).

(D) Here is the special stuff! For each organization, we have meta data fields for latitude/longitude, and we can generate a google map. The details follow!

First, once we have output the descriptive info for this organization (A), we have some left over information we can use- essentially all the variables used in the last loop.

<h3><?php the_title() ?> Projects</h3>

<?php $proj_query = new WP_Query("post_type=proj&amp;posts_per_page=-1&amp;orderby=title&amp;order=ASC&amp;meta_key=midea-proj-org&amp;meta_value=" . get_the_id()); ?>

<?php if ($proj_query->have_posts()) : while ($proj_query->have_posts()) : $proj_query->the_post(); ?>

<?php get_the_image(); ?>
<h6><a href="<?php the_permalink() ?>"><?php the_title() ?></a></h6>
<?php the_excerpt(); ?><br /><a href="<?php the_permalink() ?>">Learn more about <?php the_title() ?>...</a>
<div class="clear"></div>
<hr />

<?php endwhile; endif; wp_reset_query(); ?>

So for example, in line (01) we can use the_title to create the header for projects that includes the organization’s name. It is in line (03) that we set up the logic to get the projects we want- all of the ones assocated with this organization. So to follow out the query string, we want posts that are of type proj, and we want to list all we find (posts_per_page= -1). They are listed in alphabetical order. And the selection is defined by the projects whose meta data field for the organization id matches the id used to generate the content in (A)– the post_id for this content is the same as the meta-date values we need to match.

We then just crank up our Loop structure to put the output on the screen.

Hey, that was easy, right?

Now let’s dig into the sidebar; which again we call in a custom sidebar via

<?php get_sidebar('single-org') ?>

meaning the template lives in sidebar-single-org.php For the organization info portion (C) we use:

global $post;

$my_fields = midea_org_fields(); // fields for this content type
foreach ($my_fields as $key => $value) {
	// load values into our array
	$my_fields[$key] = get_post_meta($post->ID, 'midea-org-' . $key, true);
}
?>

<?php get_the_image( array( 'link_to_post' => false, 'class' => 'thumbnail' ) ); ?>

<h4><?php the_title() ?> Online</h4>
<?php
if ($my_fields['web'] != '') echo '<p class="biglabel"><a href="' . $my_fields['web'] . '" target="_blank"><img src="' . get_bloginfo('url') .  '/images/world.jpg" width="40" height="40" align="middle" alt=" " /></a> <a href="' . $my_fields['web'] . '" target="_blank">web site</a></p>';

if ($my_fields['facebook'] != '') echo '<p class="biglabel"><a href="' . $my_fields['facebook'] . '" target="_blank"><img src="' . get_bloginfo('url') .  '/images/facebook.jpg" width="40" height="40" align="middle"  alt=" " /></a> <a href="' . $my_fields['facebook'] . '" target="_blank">facebook</a></p>';

if ($my_fields['twitter'] != '') echo '<p class="biglabel"><a href="http://twitter.com/' . $my_fields['twitter'] . '" target="_blank"><img src="' . get_bloginfo('url') .  '/images/twitter.jpg" width="40" height="40" align="middle"  alt=" " /></a> <a href="http://twitter.com/' . $my_fields['twitter'] . '" target="_blank">twitter</a></p>';
?>

Lines (03-07) calls one of our custom functions to set up an array to store the metadata for this organization, and we then use get_post_meta() to load the values from the database into the array we are using. Take a close look at the strategy. My meta data for organizations I refer to as “url”, “facebook”, “lat”, these are the keys to the array I am creating. Inside the meta-data structure of wordpress, they are named “midea-org-”url”, “midea-org-facebook”, “midea-org-lat”.

Lines 10 and 12 then output the icon and a title, again using the still available data items from the original Loop. Lines (14), (16), and (18) then output the organization URL, facebook URL, and twitter URL but only if there are values for the item. Note for facebook, we store a full URL in the database, but for twitter, we only need the username as the twitter URLs follow from a standard pattern.

Now it is map time. Our organization meta-date includes fields for a latitude and longitude. I looked at a number of map plugins, and found that the Inline Google Map one did the trick even though it was last updated at the end of 2008.

To get map to display, all our template has to produce is the data in the form of an html definition list <dl>….</dl> that includes not only the latitude.longitude to pin the center point of the map, with extra <dt><dd> pairings, we can also add pins and labels to the map. And we can use our other metadata to populate the bubble:

Time to see the code!

<?php if ($my_fields['lat'] !== '') : ?>
<h4><?php the_title() ?> on the Map</h4>

<div id="orgmap">
<dl style="margin-bottom:20px;" title="googlemap;w:100%;h:300">
<dt class="map"><a href="http://maps.google.com/?z=14&ll=<?php echo $my_fields['lat']?>,<?php echo  $my_fields['long']?>&om=1"><img src="/images/map-loader.gif" alt="" width="126" height="22" align="middle"><br />(map loading...)</a></dt>
<dt><a href="http://maps.google.com/?ll=<?php echo  $my_fields['lat']?>,<?php echo  $my_fields['long']?>" title="marker">map</a></dt>
<dd><h4><?php the_title(); ?></h4><br /><?php get_the_image(array( 'height' => 60, 'width' => 60,))?><?php echo nl2br($my_fields['address'])?><br />
<a href="<?php echo $my_fields['web']?>">web site</a></dd>
</dl>
</div>
<?php endif?>

<?php if ($my_fields['address'] !='') echo '<p><strong>Address</strong><br />' . nl2br($my_fields['address']) . '</p>'?>

We test in line (01) for a value in out latitude variable to make sure we should eb drawing a map (no coordinates, no map for you!). The structure in line (05) is what the plugin expects to know this is a <dl> list for a map, as defined by the title attribute. I’ve set the map up here to fill 100% of the space it has (the sidebar) and to be 300 pixels high. You get to pick the dimensions of the map here.

The first <dt> with a class=map in line (06) is special to define the parameters for Google maps, meaning the zoom level (14) and the location of the center of the map ll as fed by the values of our latitude, longitude.

The embedded image and “map loading” text is a nice feature because this is what the page displays while the map takes a few seconds to be rendered. Instead of a blank box, this little bit of code will show a progress bar animation:

which disappears once the plugin places the map. Any other subsequent <dt> <dd> pairs define the map pins- <dt> contains the coordinates for the pin with the google map notation, and <dd> defines what is displayed in the bubble for that pin (you could place many pins on a map– we will do that later) – see line (08). We put a small sized version of the organization’s icon, its physical address (we use nl2br because in the metadata this is a multi line entry with carriage returns this function makes sure we use <br /> tags instead on output).

Line (09) ends the map pin bubble with a hyperlink to the organization’s web site– I see here in my code I should have put an if statement there to make sure we dont do output if there is no URL.

After closing out the map data structure in line (10), we also append the physical address below the map in line (14).

I was rather stoked to get this map part working, because it is automatic. One a previous project, I was making google maps by hand and embedding the code into pages. Here it just happens as long as I feed it some coordinates.

But more bells went off as I saw the structure for setting up the map- I could create a dynamic map that put all the organizations on a map– like this http://midea.nmc.org/map/

Not only do I have a map, but using similar approaches to before, on the right, I have a sidebar with an A-Z listgin of all organizations, and since there was empty space below the map, I added some code that would output the info for one organization chosen at random each time the page loads.

Now I could have used the same approach on the big map as the single organization map listed above- to build the <dl> list by hitting the database for all organizations and looping through to find the latitude/longitude, but this seemed a lot of database processing on each page load.

I saw a clever end around- I could generate this content as an external text file, and then I just need to use a PHP include statement to insert the map data into the page for the plugin to process.

This is created as a WordPress Page content type, and I made a special template for it, making it one of the simplest looking Loops

<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
  <h2><?php the_title(); ?></h2>
  <?php include TEMPLATEPATH . '/data/mapdata.inc'?>
  <?php the_content(); ?>

<?php endwhile; endif; ?>

Actually the only “content” on the age is the one sentence that is below the map. The trick was realizing I have code in my functions.php file midea_save_post() that is triggered after any content is saved, namely for my custom content types so it can know to save any meta data added– we did that in the post n=on adding the meta data field editing boxes.

So I only have to update this map data file if there has been an edit to the org (organization) content type- menaning someone may have added or updated thee latitude longitude.

In that function, we just add a new temp variable, $midea_update_map_flag, to track of an org content type was updated:

$midea_update_map_flag = false;

if ($post->post_type == "org") {

	$my_fields = midea_org_fields(); // fields for this content type
	$post_flag = 'org';
	$midea_update_map_flag = true;
   :
   :
   :

And after the code for updating all metadata, we trigger a call to a new function, but only if we need to change the map data. This had to come after the meta-date updates in case one of the updates for an org content type was the latitude/longitude.

// now update the cache file for the map data of all orgs
if ($midea_update_map_flag) {
	midea_update_map_data();
}

The function that updates the map data is going to run its own Loop, keep a running variable with the contents we need to save to our static file, and then write to the file.

It is almost identical to our code above, except we are going to loop through all the data for all organizations in the database.

function midea_update_map_data($zoom=3,$lat=30.2632,$long=-97.7406) {
	/* called on saving of an org post type tp create the map data to chart
	   all museum organization. Default settings are centered on Austin
	*/

	$my_query = 'post_type=org&post_status=publish&posts_per_page=-1';

	$getOrgs = new WP_Query();
	$getOrgs->query($my_query);

	$map_data = '<dl style="visibility: hidden;" title="googlemap;w:590;h:400">
        <dt><a href="http://maps.google.com/?z=' . $zoom . '&ll=' . $lat . ',' . $long . '&om=1"><img src="/images/map-loader.gif" alt="" width="126" height="22" align="middle"><br />(map loading...)</dt>' . "\n";

	while ($getOrgs->have_posts()) : $getOrgs->the_post();
		$id = get_the_ID();

		$my_fields = midea_org_fields(); // fields for this content type

		foreach ($my_fields as $key => $value) {
			// load values into our array
			$my_fields[$key] = get_post_meta($id, 'midea-org-' . $key, true);
		}	

		if ($my_fields['lat'] != '') {
			 $map_data .= '<dt><a href="http://maps.google.com/?ll=' .  $my_fields['lat'] . ',' . $my_fields['long'] . '" title="marker">map</a></dt>' . "\n" . '<dd><h4>' . get_the_title($id) . '</h4>' . get_the_image(array( 'echo' => false, 'height' => 60, 'width' => 60,)) .   nl2br($my_fields['address']) . '<br /><a href="' . $my_fields['web'] . '">web site</a><br /><a href="' . get_permalink($id) . '">MIDEA profile</a></dd>' . "\n";
		 }
	endwhile;

	$map_data .= '</dl>';

	// update the file with the code for the map
	$DATAFILE = fopen(TEMPLATEPATH . '/data/mapdata.inc',"w+");
	fwrite($DATAFILE, $map_data) or die(" failed writing $DATAFILE");
	fclose($DATAFILE);
}

Since the organizations are not going to be updated all that frequently, this ought to reduce some small amount of load on the database, since we only have to do this work when there has been a change in any of the location data.

So that is a taste of the ways I have used WordPress Content types for our organization data. Again, you can attach whatever kinds of data you want/need, and pull it as needed for output (or filter in it using the query structure). I was able to easily make a page that lists all the organizations that have twitter accounts and ones that have facebook pages (and links to them). This pages run a loop to fetch all organizations, but on looping through them, it skips any that lack the data being outputted.

These content types open the skies on what is possible, but as you can see, it take some wrangling to sort out the queries and loops. It ain’t for the feint hearted, and I dont expect anyone to follow my logic or method– but this was really meant to show what is possible.

We can map anything to anything.


cc licensed flickr photo shared by rafolio

The last post would be looking at our event content type, and see how we work with and around date and time.

Keep on pressing words!

Dressing up and Displaying WordPress 3 Custom Post Content (a)


cc licensed flickr photo shared by Thomas Hawk

Yikes, where did the time go? I’ve let slide the next piece in my now fractured series on using the custom post types added in WordPress 3.0. As a recap, what I am sharing is what I learned back in April (using the beta version of WP3) to create the NMC MIDEA web site. This site had a need to create, besides the usual page and blog post types, other content for projects, organizations, and events, each with its own extra custom meta-data.

Before I go crazy with PHP here, I want to note that this will get technical and is written really for myself as a set of notes and others who have no hesitation to roll up their sleeves and muck around with templates and code. This is not the optimal way to use the new WordPress features, and it is my expectation that what I am writing will be done more easily (and probably more efficiently) by plugins. I did it “my way” more to show what was possible.

And also, I am far from a deep WP engineering expert- I just keep tinkering til it works, and you can bet there are better ways to code than what I did.

In this series, I started with an overview of the plans for the MIDEA project, we set up the places to create the new content types, and introduced the benefits using child themes. Then we took it up a notch to dive into the code to create the interface and data elements to add/edit the custom meta data for each of the three content (post) types.

Now I turn to what it took to integrate and display stuff form my custom content into the MIDEA site. This requires a bit of understanding of what is called The Loop in WordPress.


cc licensed flickr photo shared by jayRaz

Understanding a bit of The Loop is a key bit of foundation for understanding templates (see the Loop in Action from the WordPress Codex). This is my take on it.

Just about everything WordPress does starts with it talking to the database, and saying, “get me this kind of stuff” (stuff might be recent blog posts, all posts with a certain tag, the results of a search, a single page, etc). When the database returns something, WordPress then says, “Hmmm, for each one of this, pull these bits out and display them” This is a loop, sometimes The Loop.

Typically you get a built in Loop w/o needing to strictly ask for it- the front page is “give my the 10 most recent blog posts”, and other variations are set up by the context of whatever is being served (e.g. in an archive from December 2009, you get just those posts).

The most basic version of The Loop runs something like:

if (have_posts()) :
   while (have_posts()) :
      the_post();
      // do something for each post
   endwhile;
endif;

In our code “posts” is the placeholder for whatever we are fetching- blog posts, pages, custom content types. We first need to check that we have anything, and them if so, we cycle through them (while…)– the_post() grabs all the info about the item, (title, description, link, date posted, etc). Inside that are, we have a whole series of built in functions we can use to display and wrap formatting around- the_title() , the_author(), the_permalink()

In my MIDEA project, and maybe in all, I used four variations of looping.

(1) The default loop for whatever kind of content we are working with (front page, category page, search results). This uses the structure listed above

(2) Change the condition of the main loop with query_posts. This basically makes a modification to whatever is the default behavior, so you can do things like display a different number of posts, or limit to a category.

//The Query
query_posts('posts_per_page=3');

//The Loop
if ( have_posts() ) : while ( have_posts() ) : the_post();
  // do stuff for each post
endwhile; else:
 // what to do if there is nothing found
endif;

//Reset Query
wp_reset_query();

In this case, query_posts is used to change the number things retrieved from its defaults to be exactly 3. Note the wise use of wp_reset_query() in case we want to use the default loop conditions elsewhere.

(3) Completely customize the parameters of the Loop, or make a second (or third, or fourth loop). In this case, we are not working with the default Loop for the current content, ut we are designing our own. This often happens in sidebars and/or widgets- Little Loops are done to get recent comments, recent posts, etc.

You will see a lot of these below, but the method uses the WP_Query function to set up the database request, and a slightly different variant of the default Loop structure.

An example of this is what I used on some sidebars to get the most recent blog post (setting showposts=1) from the news category:

$my_query = "showposts=1&amp;amp;category_name=news";
$showNews = new WP_Query();
$showNews->query($my_query);

while ($showNews->have_posts()) : $showNews->the_post(); ?>

 // do stuff to display here
endwhile;
wp_reset_query();

The Query_posts() reference page lists all the things you can use ti set up the query.

(4) The get down and dirty call the database query direct method. There are just some things you cannot get to via query_posts(). In the MIDEA site, I had to use this for anything that defined a loop based on the custom content meta data, or another area where I wanted to use some MySQL magic to make sure organization names that started with “The” were not alphabetized in the T”s.

Now I’m going to outline the places I used this and some of the loops used. I’m not going to detail what goes on inside the loops- this is really dictated by your template and your knowledge of how to pull and use the variables you can get for a loop item.

And this post is going to scroll for about 1000 feet.

The Projects Content Type

One of our custom content types represents projects, each with extra meta data of a URL, an id for the organization who it is affiliated with, and a rating of 1-5 (5 being highest). The general page for projects is a gallery, http://midea.nmc.org/proj with the following parts that needed custom code. The right side is a sidebar- the main content is set out by template file proj.php. Our function midea_template_redirect() we added last time, sets up for each content type, proj for projects, org for organizations, event for events, the name for its template (proj.php,org.php,event.php) as well as the templates for a single item of the type- single-proj.php, single-org.php, and single.event.php.

So here is the skeleton of the proj,php display:

(A) Each time the page loads we get 9 projects selected at random, and we want ones that are rated higher than 2 (we have some that are in progress and they get a 1 rating). The display in the squares was just used elsewhere in the Modularity template. But the idea is for a visual gallery puling projects at random.

(B) Each time we reload the page, we pull in the full information for one selected featured project. The way this is done is to select another random project, but only ones that are rated 4 or higher. In addition, we need to track the ones we used in (A) so we don’t repeat.

(C) The sidebar provides an alphabetical list of all projects in the site. This might be the easiest thing to do except for one wrinkle we discovered elsewhere on the project; the problem of projects (and organizations) that start with “The”, like “The Blue Dog” — we do not want to alphabetize on “T” but on “B:. This required a bit of custom mySQL in our loop.

Are you ready to loop?

For (A), the grid of 9 projects, we use the wordpress capability to modify the “stock” selection for the Loop. Even though this is a custom type, WordPress still provides a built in loop that will select projects in reverse chronological order. We don’t want that, so we use the method of modifying the main loop:

query_posts('post_type=proj&amp;orderby=rand&amp;meta_key=midea-proj-rating&amp;meta_value>2&amp;posts_per_page=9');

$randy_projects = array(); // keep a rolling list of projects listed here

This php above the loop logic says, “instead of what you normally do, Loop, I want t make sure I get only content that are of type proj, they should be chosen at random rather than reverse chronologically, and I want you to look at the meta data of rating, and only get me ones with a value of 2 or greater. Oh, and I only want 9 of these”

I also set up a variable to keep track of the 9 that are chosen, and will store these in an array.

We then just run our basic wordpress loop, and use it to display the image for the project and link it. The only thing we add inside the loop is something to track the project ids, using the function get_the_ID(), which in a loop returns the id number for this item.

$randy_projects[] = get_the_ID();

That was easy, eh?

Now we move on to grabbing our featured project. We need to set up arguments to send to the wp_query() function:

$args = array(
	'post_type' => 'proj',
	'posts_per_page' => 1,
	'orderby'=> 'rand',
	'meta_key' => 'midea-proj-rating',
	'meta_value' => '4',
	'meta_compare' => '>=',
	'post__not_in' => $randy_projects,
);
$blog_query = new WP_Query($args);

It is similar but different to the first one we did. On this one, we only want to grab 1, its still random, but in this case we use the options to ask for ones with a rating of 4 or higher, and the trickier part, use post_not_in to make sure it is not among the ones in our 9 item array. Got it? the last line runs the query. From here we can run our loop.

Except… we need to look back at our functions.php file. We need a few utility functions to deal with our project data. The first one, midea_get_project_info($id) is used to fetch the data for a project (identified by $id). Now what our database stores for this content type is a url, an id number for the organization, and an integer rating. We need to fetch this info, but also, we need to look up the actual name of an organization.

function midea_get_project_info($id) {
	$my_proj_fields = midea_proj_fields(); // fields for this content type

	foreach ($my_proj_fields as $key => $value) {
		// load values into our array
		$my_proj_fields[$key] = get_post_meta($id, 'midea-proj-' . $key, true);
	}

	$my_proj_fields['orgname'] = ($my_proj_fields['org'] > 0) ? get_the_title((int)$my_proj_fields['org']) : 'MIDEA';
	$my_proj_fields['id'] = $id;
	return ($my_proj_fields);
}

First we set up an empty array $my_proj_fields to store the data. We can then loop over our meta-data names to fill in their values using get_post_meta(). Next, since all we have is an id for the organization (stored as $my_proj_fields['org']) we can add a string name (‘orgname’) to our data array by using the nifty wordpress function get_the_title() we just pass it the idea of a post or content type, and we get a string back,

Lastly, because we might need ti elsewhere, we add another data element to store the id number of this project.

Now we are back to our proj.php, where we have set up the query to get one featured project. We still run a loop, although it will go through once because we asked only for one item. Below IU will show this code, but it has the template formatting simplified to make it easier to follow

<?php if ($blog_query->have_posts()) : while ($blog_query->have_posts()) :  $blog_query->the_post(); ?>

  <?php $pinfo = midea_get_project_info(get_the_ID());?>

  <p><?php echo $pinfo['orgname']?></p>

  <h2><a href="<?php the_permalink() ?>"><?php the_title(); ?></a></h2>
  <div class="entry">
  <?php the_content(); ?>

  <?php if ($pinfo['url']):?>
  <p>Project URL: <a href="<?php echo $pinfo['url']?>" target="_blank"><?php echo $pinfo['url']?></a></p>
  <?php endif; ?>

  <p><a href="<?php echo get_permalink($pinfo['org'])?>">Learn more about <?php echo $pinfo['orgname']?>...</a></p>

<?php endwhile; endif; wp_reset_query(); ?>

What we have in line (01) is a loop but using the variables defined in our query. In line (3) we get our project info, and in line (5) we echo the organization name as lead in to line (7) where we echo the project title. Line (09) just outputs whatever is written in the body for the project entry (like the body of a blog post). Lines (11-13) echo the URL if there is one. Line 15 adds a link to the organization the project is associated with (note the use of the get_permalink() function, very handy of you know an item’s id).

Lastly, note in line (17) as we end our loops controls, we reset the main query (this is the default query WordPress generates for this content type, this is a good practice to do if other parts of your template need access to its data).

Now we move on to our sidebar. We are using a special sidebar template for the projects page, so we call it via:

<?php get_sidebar('proj'); ?>

which tells WordPress instead fg using the template sidebar.php to use sidebar-proj.php.

This is the one where we want to list all projects in alpha order, but do the special ordering thing to skip alphabetizing on “The”. To do this we need to run the Type 4 variations of The Loop, where we throw it a full mySQL query. To do this you need to have a sense of how the WP database tables are set up.

<ul>
<?php
global $wpdb;
global $post;

// custom query to get posts of type proj in alpha order by trimming the leading "The " in a title
$projposts = $wpdb->get_results("SELECT wposts.*
   FROM $wpdb->posts as wposts
   WHERE wposts.post_type = 'proj' and wposts.post_status='publish'
   ORDER BY TRIM(LEADING 'The ' FROM wposts.post_title)", OBJECT);
?>
<?php if ($projposts): ?>

<?php foreach ($projposts as $post): ?>
<?php setup_postdata($post); ?>
	<li><a href="<?php the_permalink();?>"><?php the_title()?></a></li>
 <?php endforeach;  endif;?>
</ul>

I am not sure why, but I had to declare the global variables in lines (02-03). Lines (07-10) are are raw mySQL query to get content of type proj, only ones that are published, and to list them in alpha order by title, but to trim any “The” from the ordering. I cant explain it, but found it used in some other project. Lines (12-15) set up the loop in the manner you have to do for using this method. Again, thats all I know except it works, and populates our loop with data we can use like any other loop.

In this case we are doing a simple list with a link on a title.

So next we have to code up the content for a single project. The parts of this are shown schematically:

(A) the basic content for this project, we add a few extra bits like the organization name and the URL.

(B) On our sidebar, we list/link the organization this project is associated with, using the icon associated with the organization content type.

(C) We list other projects this organization has on our site.

This template again is single-proj.php.

The main part of it (A) is given by the basic loop, so we dont have to do anything fancy; and the format is pretty much in the same manner we did above for the featured project (B) on the projects gallery above.

We are going to request a custom sidebar template sidebar-single-proj.php. First we do (B) getting the organization information displayed.

<?php
$pinfo = midea_get_project_info(get_the_ID());

// set up query to get org data
$my_query = "post_type=org&p=" . $pinfo['org'] . "&posts_per_page=1";
$showOrg = new WP_Query();
$showOrg->query($my_query);
while ($showOrg->have_posts()) : $showOrg->the_post();
	get_the_image( array( 'link_to_post' => true, 'class' => 'thumbnail' ) );
endwhile;
?>
<p><a href="<?php the_permalink();?>"><?php echo $pinfo['orgname']?></a></p>

In line (02) we again use our function to get the project information, based on the current ID in the main loop. Next in lines (05-08) we run another loop to access the data for the organization associated with this project. This template has a built in function to get the icon image associated with a piece of content, which is what we output via get_the_image() function inside the one item loop. And in line (12) we echo a link to the organization.

Now we move on to (C) to get all other projects associated with this same organization.

<ul>
<?php
$my_query = 'post_type=proj&posts_per_page=-1&orderby=title&order=ASC&meta_key=midea-proj-org&meta_value=' . $pinfo['org'];

$showProj = new WP_Query();
$showProj->query($my_query);
?>

<?php if ($showProj->have_posts()) : while ($showProj->have_posts()) : $showProj->the_post(); ?>

	<?php if (get_the_ID() == $pinfo['id']) : ?>
		<li class="selected">&raquo; <strong><?php the_title();?></strong></li>
	<?php else: ?>
		<li><a href="<?php the_permalink();?>"><?php the_title()?></a></li>
	<?php endif ?>

<?php endwhile; endif; ?>
</ul>

In lines (03-06) we set up a new wp_query() to find all projects (posts_per_page value of -1 means all of ‘em), and we will list them in alpha order by title (I’m lazy and not doing the fancy order by stripping “The”…). The key here is the last bits where we tell the query to select just ones where the meta data for the project matches the organization ID of the main project being displayed. In lines (11-13) we are just doing the output, but if the project id matches the one this page represents, we dont provide a link, and add a CSS class so we can style it to indicate that its the one on this page.

This is just the basic code for one of the three content types I created. I f I write them all up, my poor blog (and body) will fall over. So I will have to come back to talk about the code used for the organizations (and the nifty plugin that inserts a google map based on latitude and longitude custom data) and for the event (where we have fun sorting by dates).

It’s a lot to explain! And this is not even to mention the various sidebars where I do things like list three random projects, but the first one is always one rated 5 and the others are all rated 3 and above. Maybe that’s an exercise for the student.

More to come. I promise/hope.

This is where we’ve been so far

Map My Mayoral Territory

I’ve made my share of snippy jokes about the silliness of foursquare, of tweeting evert burger joint you visit or your latest new badge. That’s not to say there is not some potential in this geolocation app, it may just be waiting to be found.

But take it on a simple level- you carry a device around which can sense where you are, and using foursquare (or its variants) you can “mark” your locations, see others that have been there. I put aside my criticism to last month as we learned from Beth Kanter how some museums were putting it to use (or see this strategy by a NY theater group and more ideas for museums), especially again, the notion of “listening” in social media.

So check this out- in two steps you can generate a google map of your foursquaring.

I had to try.

It works (click for larger view or see it in Google maps)

What it places in a bubble is simple- the name of the place and whatever notes you added. One might bend this as a field mapping project- check in diferent locations in a city, and comment on the architecture? Create a map-based story? I don’t know. I could save this as a MyMap and add more content to it (e.g. edit the bubbles with my photos? notes? field measurements?)

I see foursquare as used still a bit silly. It’s bad you can check into a place when you are not really in the vicinity (I did a back check in from Phoenix to a place I was on a previous trip). And now that you can check in anywhere, at airports you see locations like “Gate 39″, “Gate 38″, “In the Air”. I think I am mayor of a baggage claim, and I even joked about trying to be a mayor of a key place at the Phoenix Airport (I took some fictional liberty- Joe B is not mayor of a stall) (Neither am I) (But there is a Joe who is mayor of Ocotillo Sun, the bar in terminal 2).

This is the pitfall of judging an app, a tool, of the way you see it being used, and not looking a bit broader at the way it is not being used.

Look at what foursquare is offering for feeds – your history as RSS (subscribe to updates), KML (do stuff on maps), and ICS (do stuff with calendars):

The foursquare feeds system allows you to subscribe to RSS, KML and iCal feeds of your data. The feeds platform is still in development and is subject to change at any time (sorry!).

We’ve made the feeds available (using private token URLs) to make it easy for you to construct simple frontends like WordPress plugins and Dashboard widgets without having to use our regular API.

That smells of potential there.

And slap my palm on my head- I had no idea you could just past a KML feed into the search box of google maps and generate a map like this. Hmmmm. Hmmmmmmmmm. Hmmmmmmmmmmmmmmmmmmmmmm.