<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>DQuinn.net &#187; WordPress</title>
	<atom:link href="http://www.dquinn.net/topics/wordpress/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.dquinn.net</link>
	<description>Daniel J. Quinn&#039;s journal of WordPress, electronic publishing, and general geek culture.</description>
	<lastBuildDate>Thu, 22 Jul 2010 23:46:09 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Scrape Shared Notes from Your Google Reader Feed into WordPress</title>
		<link>http://www.dquinn.net/shared-notes-google-reader-wordpress/</link>
		<comments>http://www.dquinn.net/shared-notes-google-reader-wordpress/#comments</comments>
		<pubDate>Wed, 28 Oct 2009 02:13:24 +0000</pubDate>
		<dc:creator>Daniel Quinn</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[domdocument]]></category>
		<category><![CDATA[google reader]]></category>
		<category><![CDATA[google shared notes]]></category>
		<category><![CDATA[php 5]]></category>
		<category><![CDATA[shared notes]]></category>

		<guid isPermaLink="false">http://www.dquinn.net/?p=2105</guid>
		<description><![CDATA[If you love Google Reader and regularly create "Shared Notes" as you skim through your daily dose of RSS feeds, then this quick tutorial will help put those notes on your website. Forget fiddling with plugins for this one—by using the DOMDocument class in PHP 5, you can scrape your Google Shared Notes feed to display your latest shared notes directly on a page within WordPress.]]></description>
			<content:encoded><![CDATA[<p>If you love Google Reader and regularly create "Shared Notes" as you skim through your daily dose of RSS feeds, then this quick tutorial will help put those notes on your website.</p>
<p>Forget fiddling with plugins for this one—by using the DOMDocument class in PHP 5, you can scrape your Google Shared Notes feed to display your latest shared notes directly on a page within WordPress.</p>
<p>See the finished result: <a href="http://www.dquinn.net/notes/">http://www.dquinn.net/notes/</a></p>
<p>It's actually really easy. First create a template called "page-notes.php." Then, make a page in WordPress and call it "Notes" or something similar, and assign your new page template to it. Here is the code that goes in your template:</p>
<pre class="brush: php;">
&lt;ul class=&quot;google-reader&quot;&gt;
&lt;?php
$doc = new DOMDocument();
$doc-&gt;load('PUT YOUR FEED URL HERE');
$titles = array();
$content = array();
foreach ($doc-&gt;getElementsByTagName('entry') as $node) {
     $titles[] = $node-&gt;getElementsByTagName('title')-&gt;item(0)-&gt;nodeValue;
     $links[] = $node-&gt;getElementsByTagName('link')-&gt;item(0)-&gt;getAttribute('href');
     $quote[] = $node-&gt;getElementsByTagName('annotation')-&gt;item(0)-&gt;nodeValue;
}
for ($i=0; $i&lt;count($titles); $i++) {
     echo &quot;&lt;li&gt;&quot;;
     echo '&lt;a href=&quot;'.$links[$i].'&quot;&gt;';
     echo $titles[$i];
     echo '&lt;/a&gt;';
     if ($quote[$i]) {
          echo '&lt;span class=&quot;shared-note&quot;&gt;';
          echo '&lt;span class=&quot;shared-avatar&quot;&gt;&lt;img width=&quot;40&quot; height=&quot;40&quot; alt=&quot;YOUR NAME&quot; src=&quot;http://www.gravatar.com/avatar/PUT YOUR GRAVATAR ID HERE?s=40&quot;/&gt;&lt;/span&gt;';
          echo '&lt;span class=&quot;shared-quote&quot;&gt;&lt;span class=&quot;shared-pip&quot;&gt;&lt;/span&gt;&lt;em&gt;';
          echo str_replace(&quot;YOUR GOOGLE READER USERNAME&quot;,&quot;&quot;,$quote[$i]);
          echo '&lt;/em&gt;&lt;/span&gt;';
          echo '&lt;span class=&quot;shared-follow&quot;&gt;&lt;a href=&quot;PUBLIC URL TO YOUR GOOGLE READER PAGE&quot;&gt;Follow Me on Google Reader »&lt;/a&gt;&lt;/span&gt;';
          echo '&lt;/span&gt;';
     }
     echo &quot;&lt;/li&gt;&quot;;
}
?&gt;
&lt;/ul&gt;
</pre>
<p>You'll need to fill in the following values where noted above:</p>
<p>"PUT YOUR FEED URL HERE." This one is tricky to find. Go to your <a href="http://www.google.com/reader/shared/djamesquinn">public profile</a> and then click on the link to your <a href="http://www.google.com/reader/public/atom/user%2F10574788495602308731%2Fstate%2Fcom.google%2Fbroadcast">Atom Feed</a>. This is the RSS that the script will parse.</p>
<p>"PUT YOUR GRAVATAR ID HERE." I like to have my gravatar appear next to each note (if I've left one). Go to <a href="http://www.gravatar.com">Gravatar</a> to get your encrypted email ID (it's a really long sequence of numbers/letters). You could, of course, substitute this with any image.</p>
<p>"YOUR GOOGLE READER USERNAME." Mine is "alkah3st." The script looks for your username in the XML nodes to parse the note, so this is case-sensitive.</p>
<p>"PUBLIC URL TO YOUR GOOGLE READER PAGE." Mine looks like this: <a href="http://www.google.com/reader/shared/djamesquinn">http://www.google.com/reader/shared/djamesquinn</a></p>
<p>This will generate the latest items in your Shared Notes feed in an unordered list. For items that you shared but didn't write a note for, it will generate the following markup:</p>
<pre class="brush: xml;">
&lt;li&gt;
&lt;a href=&quot;http://volokh.com/2009/10/27/legal-scholarship-in-the-internet-age/&quot;&gt;Legal Scholarship in the Internet Age&lt;/a&gt;
&lt;/li&gt;
</pre>
<p>If you <em>did</em> write a note, then it will generate this markup:</p>
<pre class="brush: xml;">
&lt;li&gt;
&lt;a href=&quot;http://feeds.gawker.com/~r/gawker/full/~3/eynAol1tBZI/french-convict-the-church-of-scientology-of-fraud-almost-ban-it&quot;&gt;French Convict the Church of Scientology of Fraud, Almost Ban It [Scandal]&lt;/a&gt;
&lt;span class=&quot;shared-note&quot;&gt;
     &lt;span class=&quot;shared-avatar&quot;&gt;
           &lt;img width=&quot;40&quot; height=&quot;40&quot; src=&quot;http://www.gravatar.com/avatar/8c35d8ee142dbe5101cf9314236a87fc?s=40&quot; alt=&quot;Daniel Quinn&quot;/&gt;
     &lt;/span&gt;
     &lt;span class=&quot;shared-quote&quot;&gt;
          &lt;span class=&quot;shared-pip&quot;&gt;&lt;/div&gt;
          &lt;em&gt;Nice.&lt;/em&gt;
     &lt;/span&gt;
     &lt;span class=&quot;shared-follow&quot;&gt;&lt;a href=&quot;http://www.google.com/reader/shared/djamesquinn&quot;&gt;Follow Me on Google Reader »&lt;/a&gt;&lt;/span&gt;
&lt;/span&gt;
&lt;/li&gt;
</pre>
<p>Last, but not least, you can style the markup however you like, but if you want the neat talk bubble like I have, you'll want CSS that goes something like this:</p>
<pre class="brush: css;">
ul.google-reader {
	margin-left: 0px;
}

ul.google-reader li {
	border-top:1px dotted #CCCCCC;
	padding-top: 15px;
}

.shared-note {
	display:block;
	margin-top:15px;
	overflow:hidden;
	padding-bottom:20px;
	position:relative;
}

.shared-avatar {
	display: block;
	float: left;
}

.shared-avatar img {
	border:1px solid #C2D9FF;
	padding: 2px;
}

.shared-quote {
	float: left;
	width: 380px;
	margin-left:20px;
	position: relative;
	background-color: #E1ECFE;
	border: 1px solid #c2d9ff;
	-moz-border-radius: 5px;
	-webkit-border-radius: 5px;
	padding: 10px;
}

.shared-quote em {
	font-size: 12px;
	font-style: normal;
}

.shared-quote .shared-pip {
	display: block;
	position: absolute;
	top: 10px;
	width: 16px;
	height: 16px;
	left: -9px;
	background: url(images/pip.gif) no-repeat;
}

.shared-follow {
	bottom:0px;
	font-family:arial;
	font-size:10px;
	font-style:italic;
	left:80px;
	position:absolute;
	width:300px;
}
</pre>
<p>You can download the "pip" image here: <a href="http://www.dquinn.net/wp-content/themes/sneakers/images/pip.gif">http://www.dquinn.net/wp-content/themes/sneakers/images/pip.gif</a></p>
<p><strong>Note</strong>: Keep in mind that I have Eric Meyer's Reset CSS in my stylesheet. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.dquinn.net/shared-notes-google-reader-wordpress/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Flutter is Not Dead Says Navid, Matt Mullenweg Takes Notice</title>
		<link>http://www.dquinn.net/flutter-is-not-dead-says-navid-matt-mullenweg-takes-notice/</link>
		<comments>http://www.dquinn.net/flutter-is-not-dead-says-navid-matt-mullenweg-takes-notice/#comments</comments>
		<pubDate>Tue, 06 Oct 2009 12:31:40 +0000</pubDate>
		<dc:creator>Daniel Quinn</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[custom write panel]]></category>
		<category><![CDATA[dashboard]]></category>
		<category><![CDATA[flutter]]></category>
		<category><![CDATA[freshout]]></category>
		<category><![CDATA[fringe magazine]]></category>
		<category><![CDATA[GPL]]></category>
		<category><![CDATA[gui]]></category>
		<category><![CDATA[harvard common press]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[magic fields]]></category>
		<category><![CDATA[Matt Mullenweg]]></category>
		<category><![CDATA[media library]]></category>
		<category><![CDATA[navid safabakhsh]]></category>
		<category><![CDATA[tinymce]]></category>
		<category><![CDATA[wordpress 2.9]]></category>

		<guid isPermaLink="false">http://www.dquinn.net/?p=2074</guid>
		<description><![CDATA[We're heard <a href="http://www.google.com/#hl=en&#38;source=hp&#38;fkt=420&#38;fsdt=2316&#38;q=flutter+wordpress&#38;aq=f&#38;aqi=g-p1g6g-m2&#38;oq=&#38;fp=7d15299a959dbb33">a lot</a> about Flutter. The Flutter homepage has accumulated something like <a href="http://flutter.freshout.us/?wpc=all#comments">1,592 comments</a> since its release—a bewildering array of bug reports, praise, and feature requests—and the now defunct support forum was a mire of temporary solutions and fixes until it was abandoned by its developers and replaced with a <a href="http://groups.google.com/group/flutter-support">Google Group</a>. The only public place that exists for WP hacks like myself to confer about the plugin in its current state is this group, which has recently been beset by spammers. The Freshout guys occasionally post there, but we’ve heard little about progress on the next release of Flutter, even while bug fixes circulate among members of the community.]]></description>
			<content:encoded><![CDATA[<p>If there's one thing I'm looking forward to when it comes to WordPress other than <a href="http://wordpress.org/development/2009/07/vote-for-2-9-media-features/">2.9's new Media Library</a>, it's <a href="http://freshout.us/">Freshout</a>'s next release of <a href="http://flutter.freshout.us/">Flutter</a>, the WordPress CMS plugin.</p>
<div id="attachment_2079" class="wp-caption aligncenter" style="width: 500px"><img class="size-large wp-image-2079" title="Using Flutter at Harvard Common Press" src="http://www.dquinn.net/images/book-fields-490x395.gif" alt="Using Flutter to Establish Book-Author Relationships" width="490" height="395" /><p class="wp-caption-text">Using Flutter to Establish Book-Author Relationships</p></div>
<p>We've heard <a href="http://www.google.com/#hl=en&amp;source=hp&amp;fkt=420&amp;fsdt=2316&amp;q=flutter+wordpress&amp;aq=f&amp;aqi=g-p1g6g-m2&amp;oq=&amp;fp=7d15299a959dbb33">a lot</a> about Flutter. The Flutter homepage has accumulated something like <a href="http://flutter.freshout.us/?wpc=all#comments">1,592 comments</a> since its release—a bewildering array of bug reports, praise, and feature requests—and the now defunct support forum was a mire of temporary solutions and fixes until it was abandoned by its developers and replaced with a <a href="http://groups.google.com/group/flutter-support">Google Group</a>. The only public place that exists for WP hacks like myself to confer about the plugin in its current state is this group, which has recently been beset by spammers. The Freshout guys occasionally post there, but we’ve heard little about progress on the next release of Flutter, even while bug fixes circulate among members of the community.</p>
<div id="attachment_2081" class="wp-caption alignright" style="width: 89px"><img class="size-full wp-image-2081" title="Navid Safabakhsh" src="http://www.dquinn.net/images/1246486020navid.jpg" alt="Navid Safabakhsh" width="79" height="79" /><p class="wp-caption-text">Navid Safabakhsh</p></div>
<p>But we can’t criticize Freshout for being slow about progress, or for the hackiness of Flutter. What VP of Production and Principal of the design house Freshout Navid Safabakhsh has been up to with his team has the potential to transform WordPress into a fully fledged CMS, with content types, custom write panels, and swanky GUI’d custom fields. Even if Freshout abandoned the plugin today and left us with Flutter as is, we should be eternally grateful. <a href="http://freshout.us/notebook/path-of-flutter/">In a blog post on Freshout</a>, Navid explains how Flutter evolved from a fork of <a href="http://wordpress.org/extend/plugins/custom-write-panel/">Custom Write Panel</a> into Fresh Page, and ultimately into Flutter, not as an open source project, but as a real-time solution to Freshout’s clients’ needs. “We have been criticized quite a lot in the past year or so for being slow with support and lack of transparency with the product plan of Flutter. There is a good reason for that,” Navid writes, “It’s because there isn’t a clear product plan that’s centered around the community. The product plan is centered around what our clients ask us to build since that’s our source of revenue.” Navid remains skeptical about releasing a final version of Flutter into the GPL partly because of all the zaniness that erupted from Flutter’s overnight community, and partly because his 25-person team has a business to run and can’t deal with providing support all night for free. But that doesn’t mean Navid and Freshout aren’t open to getting the job done. “Over the next few weeks, we’re getting in touch with anyone who wants to help us put some serious energy back into Flutter. If you’re one of these people, hit me up.”</p>
<p>Now here’s the really cool news: in his post, Navid confirms the rumor that Freshout’s got the attention of Matt Mullenweg, the official king-god of WordPress. On <a href="http://groups.google.com/group/flutter-support/msg/6f9eea74f34a06c6">a post in the Google Group</a> entitled “Is Flutter dead?” (to which Navid replies enigmatically, “No, it’s not. We’ll communicate our plans soon”), Google groupie Tammy Hart writes:</p>
<blockquote><p>Matt Mullenweg was here at WordCamp Birmingham this past weekend where there ended up being a big buzz about Flutter. As he was leaving and saying a final goodbye to me with a handshake, he said, “I really like what you're doing with Flutter, but I don't like how the plugin works... So I'm gonna make it better.”</p></blockquote>
<p><img class="aligncenter size-full wp-image-2082" style="border: none;" title="post" src="http://www.dquinn.net/images/post.gif" alt="post" width="484" height="362" /></p>
<p>Wow. Could you imagine CMS functionality on the roadmap? I can’t, but I won’t lose hope. <a href="http://core.trac.wordpress.org/milestone/2.9">WordPress 2.9 is due out October 31</a> though the release date looks a little too optimistic for me (there are 623 of 776 active tickets, which sets Milestone 2.9 at 20% completion as of today). Navid writes that we could hear about the game plan for Flutter as early as “the end of October”  or see a release by “Nov 7<sup>th</sup>, which will include fixes to the most urgent bugs.” Sounds too good to be true.</p>
<div id="attachment_2084" class="wp-caption alignright" style="width: 166px"><img class="size-full wp-image-2084" title="Using Custom Write Panels" src="http://www.dquinn.net/images/write-panels.gif" alt="Custom Write Panels" width="156" height="420" /><p class="wp-caption-text">Custom Write Panels</p></div>
<p>And what about all the Flutter clones out there, borne most likely out of frustration with Freshout’s unresponsiveness or itching anticipation for what can be done with GUI’d custom fields in WordPress? Navid isn’t too pleased with dividing up the potential for open source labor: “There are a number of other CMS plugins that were released after Flutter and directly ‘compete’ with us [see <a href="http://magicfields.org/">Magic Fields</a>, developed by a couple of ex-Flutterers]. This is a concept that I just don’t understand in the GPL world. We’re not competing with any of you. We’re just sharing some of our code for other people that want to use it. That’s really it.”</p>
<p>It’s all very interesting.</p>
<p>Here’s the thing, though, for all you whining WP masses out there: There is already a lot you can do with Flutter, as buggy as it is today. If you troll through all the posts in the Google Group, you’ll find enough fixes to make Flutter usable for the time being. In a version I’ve been patching, I’ve got image uploads working reliably (cropping disabled), my categories don’t disappear, jQuery plays nicely with the Dashboard, and TinyMCE behaves in HTML mode. I’ve also created stable relationships between post “types” through Flutter fields that wouldn’t be manageable for the end user without the grouping capabilities that Flutter’s GUI allows for (see <a href="http://www.harvardcommonpress.com">Harvard Common Press</a>, for example—books and authors are intimately related thanks to Flutter. This situation is similar at <a href="http://www.fringemagazine.org">Fringe Magazine</a>).</p>
<p>So let's not lose hope or beleaguer Navid any more than we already have. I'll see you in November.</p>
<p><strong>UPDATE:</strong> Attached is <a href="http://www.dquinn.net/images/fresh-page.zip">my less buggy version of Flutter</a>, per request. I offer no support for this, as I plan to document the changes I made in a later post.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dquinn.net/flutter-is-not-dead-says-navid-matt-mullenweg-takes-notice/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>Replacing Search in WordPress with Google&#8217;s Custom Search Engine</title>
		<link>http://www.dquinn.net/replace-wordpress-search-with-google-custom-search/</link>
		<comments>http://www.dquinn.net/replace-wordpress-search-with-google-custom-search/#comments</comments>
		<pubDate>Fri, 04 Sep 2009 17:36:41 +0000</pubDate>
		<dc:creator>Daniel Quinn</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[dashboard]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[google cse]]></category>
		<category><![CDATA[google custom search engine]]></category>
		<category><![CDATA[harvard common press]]></category>
		<category><![CDATA[joy of pregnancy]]></category>
		<category><![CDATA[not your mothers cookbooks]]></category>
		<category><![CDATA[relevanssi]]></category>
		<category><![CDATA[search reloaded]]></category>
		<category><![CDATA[search unleashed]]></category>

		<guid isPermaLink="false">http://www.dquinn.net/?p=1936</guid>
		<description><![CDATA[If you have a ring of web properties that are powered by WordPress, why not link them all together to drive traffic through a custom Google search? WordPress's search engine is notoriously unhelpful because it sorts search results by date instead of relevancy. If you use Google Custom Search, when you search using your souped-up Google Custom Search box, you'll land on the new search template, and Google will load the results (almost instantaneously) in a paginated iframe.]]></description>
			<content:encoded><![CDATA[<p>If you have a ring of web properties that are powered by WordPress, why not link them all together to drive traffic through a custom Google search?</p>
<p>WordPress's search engine is notoriously unhelpful because it sorts search results by date instead of relevancy. Few plugins out there solve the problem adequately, and those that do must replace the WordPress search engine altogether. (Some time ago, we had a free plugin called The Search Reloaded that sorted results by relevancy, but now it's part of a <a href="http://www.semiologic.com/software/search-reloaded/">commercial package</a>. <a href="http://urbangiraffe.com/plugins/search-unleashed/">Search Unleashed</a> and <a href="http://wordpress.org/extend/plugins/relevanssi/">Relevanssi</a> are two other solutions, but they have a tendency—in my experience—to interfere with heavily customized themes that employ complex loops.)</p>
<p>Part of overhauling the websites owned by Harvard Common Press (HCP) was the process of converting them to WordPress. You'll notice that <a href="http://www.harvardcommonpress.com">The Harvard Common Press</a> website and its microsite, <a href="http://www.notyourmotherscookbook.com">Not Your Mother's Cookbooks</a> (NYMC), search across indexed pages in the following domains:</p>
<ul>
<li>http://www.harvardcommonpress.com</li>
<li>http://www.thejoyofpregnancy.com</li>
<li>http://www.notyourmotherscookbook.com</li>
<li>http://www.nursingmotherscompanion.com</li>
</ul>
<p>So if you search for the book "The Joy of Pregnancy" you will get results from all of these sites, and Google will even suggest the other domains before calling results from within the HCP website. Potentially, we could even add Tori Kropp's personal website to these results (she is the author of the book), even though we don't control that domain.</p>
<p>(I'm still working on converting The Joy of Pregnancy and The Nursing Mother's Companion to WordPress, so those don't use Google Custom Search just yet.)</p>
<p>If your sites are already well-indexed by Google, the custom search offers a vast improvement over WordPress' built-in search (at least for the time being). Users are already accustomed to using Google's services, so the custom search will be a welcomed addition to your site, and it's free if you don't mind the ads. So let's look at integrating the search into our theme.</p>
<h2>Installing Google CSE in WordPress</h2>
<p>Go to Google Custom Search  and sign up for an account.</p>
<div style="overflow: hidden;">
<div id="attachment_1939" class="wp-caption alignleft" style="width: 420px"><img src="http://www.dquinn.net/images/hcp-sites.jpg" alt="Search Across Multiple Sites" title="CSE Sites" width="410" height="293" class="size-full wp-image-1939" /><p class="wp-caption-text">Search Across Multiple Sites</p></div>
</div>
<p>What you'll need to do is create a custom search engine on your CSE site profile for each website in your ring. So I created CSE for both the HCP website and NYMC. I then had each of these engines search across all four websites listed above in the CSE Control Panel by entering in their domains. For our purposes, we want to embed the CSE as an iframe on our site, so choose that option when you get the CSE code.</p>
<p>You can customize the "Look and Feel" for each engine to your liking, as well as the search results' box width (but keep in mind that if you position ads to the right, the search results box will force a width greater than 780 pixels even if you set the width to something smaller. The best position for ads if you want to control the width is "top and bottom").</p>
<p>Next, I created a template called "searchform.php" in my theme to override the default search bar. The default code for this template is as follows:</p>
<pre class="brush: xml;">
&lt;li id=&quot;search&quot;&gt;
  &lt;label for=&quot;s&quot;&gt;Search:&lt;/label&gt;
    &lt;form id=&quot;searchform&quot; method=&quot;get&quot; action=&quot;/index.php&quot;&gt;
      &lt;div&gt;
         &lt;input type=&quot;text&quot; name=&quot;s&quot; id=&quot;s&quot; size=&quot;15&quot; /&gt;&lt;br /&gt;
         &lt;input type=&quot;submit&quot; value=&quot;Search&quot; /&gt;
      &lt;/div&gt;
     &lt;/form&gt;
&lt;/li&gt;
</pre>
<p>Google will provide you with the following code for the search box:</p>
<pre class="brush: xml;">
&lt;form action=&quot;http://www.yourwebsite.com/search/&quot; id=&quot;cse-search-box&quot;&gt;
  &lt;div&gt;
    &lt;input type=&quot;hidden&quot; name=&quot;cx&quot; value=&quot;YOUR UNIQUE CODE HERE&quot; /&gt;
    &lt;input type=&quot;hidden&quot; name=&quot;cof&quot; value=&quot;YOUR AD POSITION HERE&quot; /&gt;
    &lt;input type=&quot;hidden&quot; name=&quot;ie&quot; value=&quot;UTF-8&quot; /&gt;
    &lt;input type=&quot;text&quot; name=&quot;q&quot; size=&quot;31&quot; /&gt;
    &lt;input type=&quot;submit&quot; name=&quot;sa&quot; value=&quot;Search&quot; /&gt;
  &lt;/div&gt;
&lt;/form&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;http://www.google.com/jsapi&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;&gt;google.load(&quot;elements&quot;, &quot;1&quot;, {packages: &quot;transliteration&quot;});&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;http://www.google.com/coop/cse/t13n?form=cse-search-box&amp;t13n_langs=en&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;http://www.google.com/coop/cse/brand?form=cse-search-box&amp;lang=en&quot;&gt;&lt;/script&gt;
</pre>
<p>To merge the two, you need to:</p>
<ul>
<li>Remove the method='get' attribute</li>
<li>Ensure the cse-search-box id is on the form tag</li>
<li>Swap out the URL for the action attribute to where you'd like the search results to appear on your site (see below)</li>
<li>Add the hidden input fields</li>
<li>Add the javascript</li>
<li>Change/add the name attributes on the submit and text inputs to match Google's</li>
</ul>
<p>Here is an example:</p>
<pre class="brush: php;">
&lt;li id=&quot;search&quot;&gt;
&lt;label for=&quot;s&quot;&gt;Search:&lt;/label&gt;
&lt;form id=&quot;cse-search-box&quot; action=&quot;&lt;?php bloginfo('url'); ?&gt;/search/&quot;&gt;
    &lt;div&gt;
        &lt;input type=&quot;hidden&quot; name=&quot;cx&quot; value=&quot;PUT YOUR GOOGLE VALUE HERE&quot; /&gt;
        &lt;input type=&quot;hidden&quot; name=&quot;cof&quot; value=&quot;PUT YOUR AD POSITION HERE&quot; /&gt;
        &lt;input type=&quot;hidden&quot; name=&quot;ie&quot; value=&quot;UTF-8&quot; /&gt;
        &lt;input type=&quot;text&quot; name=&quot;q&quot; id=&quot;s&quot; size=&quot;15&quot; /&gt;
        &lt;input type=&quot;submit&quot; name=&quot;sa&quot; value=&quot;Search&quot; /&gt;
        &lt;input type=&quot;text&quot; name=&quot;q&quot; id=&quot;s&quot; /&gt;
    &lt;/div&gt;
&lt;/form&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;http://www.google.com/jsapi&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;&gt;google.load(&quot;elements&quot;, &quot;1&quot;, {packages: &quot;transliteration&quot;});&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;http://www.google.com/coop/cse/t13n?form=cse-search-box&amp;amp;t13n_langs=en&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;http://www.google.com/coop/cse/brand?form=cse-search-box&amp;amp;lang=en&quot;&gt;&lt;/script&gt;
&lt;/li&gt;
</pre>
<p>Great. If you did this properly, you should see Google's logo overlay on your search box. You cab modify how you want this to look in your CSE account.</p>
<p>Now for the search results template and Google' second chunk of code. In your search.php template, we need to remove the loop, the pagination, and the if/else conditionals that handle the search results in WordPress, then put in Google's second chunk of code. If you are using the Default theme, for example, your code would resemble the following:</p>
<pre class="brush: php;">
&lt;?php
/**
 * @package WordPress
 * @subpackage Default_Theme
 */
/*
Template Name: Search
*/
get_header(); ?&gt;

&lt;div id=&quot;content&quot; role=&quot;main&quot;&gt;

   &lt;h2&gt;Search Results&lt;/h2&gt;

   &lt;div id=&quot;cse-search-results&quot;&gt;&lt;/div&gt;
   &lt;script type=&quot;text/javascript&quot;&gt;
     var googleSearchIframeName = &quot;cse-search-results&quot;;
     var googleSearchFormName = &quot;cse-search-box&quot;;
     var googleSearchFrameWidth = 710; // PUT YOUR DESIRED WIDTH HERE
     var googleSearchDomain = &quot;www.google.com&quot;;
     var googleSearchPath = &quot;/cse&quot;;
   &lt;/script&gt;
   &lt;script type=&quot;text/javascript&quot; src=&quot;http://www.google.com/afsonline/show_afs_search.js&quot;&gt;&lt;/script&gt;

&lt;/div&gt;

&lt;?php get_sidebar(); ?&gt;
&lt;?php get_footer(); ?&gt;
</pre>
<p>Finally, you need to create a top-level page in the Dashboard called "Search" with the slug "http://www.yourwebsite.com/search/" and assign the Search template to this page via its Page Attributes.</p>
<p>Once this is complete, when you search using your souped-up Google Custom Search box, you'll land on the new search template, and Google will load the results (almost instantaneously) in a paginated iframe!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dquinn.net/replace-wordpress-search-with-google-custom-search/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Extending User Profiles in WordPress</title>
		<link>http://www.dquinn.net/extending-user-profiles-wordpress/</link>
		<comments>http://www.dquinn.net/extending-user-profiles-wordpress/#comments</comments>
		<pubDate>Fri, 28 Aug 2009 17:44:43 +0000</pubDate>
		<dc:creator>Daniel Quinn</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[gravatar]]></category>
		<category><![CDATA[members list]]></category>
		<category><![CDATA[peter westwood]]></category>
		<category><![CDATA[pjw user meta]]></category>
		<category><![CDATA[user photo]]></category>
		<category><![CDATA[user profile]]></category>

		<guid isPermaLink="false">http://www.dquinn.net/?p=1846</guid>
		<description><![CDATA[In this series, I'm going to show you how to display a paginated archive of all your WordPress users, as well as extend user profiles to include custom user meta on both the front end of your WordPress theme and in the Dashboard.]]></description>
			<content:encoded><![CDATA[<p>In this series, I'm going to show you how to display a paginated archive of all your WordPress users, as well as extend user profiles to include custom user meta on both the front end of your WordPress theme and in the Dashboard.</p>
<p>As it stands, there are no filters in WordPress that allow you to dramatically alter the way the user profile fields (or user meta) are displayed when you visit your Profile in the Dashboard.<a href="#footnote">*</a> The existing profile fields are more or less hard-coded into the WordPress core, and so there's no easy way to add more fields without hacking the core.</p>
<p>Instead, we have to turn to several plugins to get the desired functionality.</p>
<p>First, we need to display a list of all registered users:</p>
<blockquote><p><a href="http://wordpress.org/extend/plugins/members-list/">Members List</a> will display a paginated list of registered users on a page in WordPress. It lets us sort the list by Last Name, First Name, Registration Date, and Email and search users by some of the default user meta fields. And when you click individual users, it will link to the Author template so we can handle individual user profiles on the front end.</p></blockquote>
<p>So far so good.</p>
<p>Now, we want to let users upload their own photos for use throughout the site. But we also want gravatars to work if users have them, and additionally we want WordPress to generate a random avatar for users if they don't have a gravatar and they haven't uploaded a photo. (Uploaded avatars should take precedence over all others.)</p>
<blockquote><p><a href="http://wordpress.org/extend/plugins/user-photo/">User Photo</a> is the only plugin that does the job.</p></blockquote>
<p>Finally, we need to be able to add custom user meta without hacking the core, and have these new fields appear in the Dashboard so users can fill them out.</p>
<blockquote><p>In <a href="http://blog.ftwr.co.uk/archives/2009/07/19/adding-extra-user-meta-fields/">PJW User Meta</a>, Peter Westwood demonstrated how we could add extra fields to the Profile and process them in a sample plugin he wrote. We can use his code as a basis for writing theme-specific plugins that add sets of custom user meta without hacking the core.</p></blockquote>
<h2>Setbacks</h2>
<p>While the good news is that all this stuff will work up to 2.8.4, we still need to hack the plugins to meet our requirements.</p>
<ul>
<li>Members List doesn't know that we're letting users upload their own photos, and so it can't show avatars conditionally like User Photo does. We'll have to give it the necessary code to behave like we want when it shows our list of registered users;</li>
<li>User Photo has a bug that requires every uploaded photo to be approved by an admin, even if you turn that feature off. We'll have fix that. We also need to make it so that the function that <em>echoes </em>the conditionally selected avatar can optionally <em>return </em>the avatar for use in a variable, in order for it to play nicely with Members List;</li>
<li>We need to write an Author template to display profiles for individual users.</li>
</ul>
<p>With that, let's start by creating the Members List archive.</p>
<p>You can view the finished (albeit unstyled) product here:</p>
<p><a href="http://dev.dquinn.net/guest/members/">http://dev.dquinn.net/guest/members/</a></p>
<p>Next up, <a href="http://www.dquinn.net/creating-directory-registered-users-wordpress/">Creating a Directory of Registered Users in WordPress »</a></p>
<p><a href="#footnote" id="footnote">*</a> There are <a href="http://core.trac.wordpress.org/changeset/11784">developments on the horizon</a> as we approach WordPress 2.9 that may make this whole process easier, but for now, we'll have to rely on plugins and hiding fields with CSS as this series prescribes.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dquinn.net/extending-user-profiles-wordpress/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Creating a Directory of Registered Users in WordPress</title>
		<link>http://www.dquinn.net/creating-directory-registered-users-wordpress/</link>
		<comments>http://www.dquinn.net/creating-directory-registered-users-wordpress/#comments</comments>
		<pubDate>Thu, 27 Aug 2009 17:46:29 +0000</pubDate>
		<dc:creator>Daniel Quinn</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[author template]]></category>
		<category><![CDATA[members list]]></category>
		<category><![CDATA[user photo]]></category>

		<guid isPermaLink="false">http://www.dquinn.net/?p=1853</guid>
		<description><![CDATA[First of all, create about 6 users under Users --&#62; Add Users in WordPress, so we have some faces to work with. Then go ahead an install <a href="http://wordpress.org/extend/plugins/members-list/">Members List</a>. Quickest instructions for setting it up.]]></description>
			<content:encoded><![CDATA[<p>First of all, create about 6 users under Users -&gt; Add Users in WordPress, so we have some faces to work with. Then go ahead an install <a href="http://wordpress.org/extend/plugins/members-list/">Members List</a>. Quickest instructions for setting it up:</p>
<ol>
<li>Download and install the plugin</li>
<li>Create a template in your theme called members.php. Put the following code in that template:</li>
</ol>
<pre class="brush: php;">
&lt;?php
/**
 * @package WordPress
 * @subpackage Name_of_Your_Theme
 */
/* Template Name: Members */
get_header(); ?&gt;

&lt;div id=&quot;content&quot; class=&quot;narrowcolumn&quot; role=&quot;main&quot;&gt;

&lt;?php
$members = new tern_members;
$members-&gt;members(array('search'=&gt;true,'pagination'=&gt;true,'sort'=&gt;true));
?&gt;

&lt;/div&gt;

&lt;?php get_footer(); ?&gt;
</pre>
<p>Finally, create a page in WordPress called "Members." Assign the "Members" template to that page and Publish.</p>
<p>Okay, great, now you should see your members list:</p>
<p><a href="http://dev.dquinn.net/guest/members/">http://dev.dquinn.net/guest/members/</a></p>
<p>Of course, 2 problems remain:</p>
<ul>
<li>When you click on individual users, you go to the Author archive for that user, instead of an individual profile for the user.</li>
<li>It's not yet integrated with the User Photo plugin.</li>
</ul>
<p>Let's fix problem #1 first.</p>
<p>Next up, <a href="http://www.dquinn.net/creating-author-template-wordpress/">Creating an Author Template in WordPress »</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.dquinn.net/creating-directory-registered-users-wordpress/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Creating an Author Template in WordPress</title>
		<link>http://www.dquinn.net/creating-author-template-wordpress/</link>
		<comments>http://www.dquinn.net/creating-author-template-wordpress/#comments</comments>
		<pubDate>Wed, 26 Aug 2009 17:47:44 +0000</pubDate>
		<dc:creator>Daniel Quinn</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[author template]]></category>
		<category><![CDATA[members list]]></category>

		<guid isPermaLink="false">http://www.dquinn.net/?p=1862</guid>
		<description><![CDATA[Each user needs a landing page that displays all the user meta from her profile. Thankfully, <a href="&#60;a href=&#34;http://codex.wordpress.org/Author_Templates&#34;&#62;">WordPress has already accounted for this</a>, because when the application requests an author by ID (?author=#), it looks for the following templates in this order: author.php, archive.php, index.php.]]></description>
			<content:encoded><![CDATA[<p>Each user needs a landing page that displays all the user meta from her profile. Thankfully, <a href="http://codex.wordpress.org/Author_Templates">WordPress has already accounted for this</a>, because when the application requests an author by ID (?author=#), it looks for the following templates in this order:</p>
<ol>
<li>author.php</li>
<li>archive.php</li>
<li>index.php </li>
</ol>
<p>All we need to do is make an Author template:</p>
<pre class="brush: php;">
&lt;?php get_header(); ?&gt;

&lt;div id=&quot;content&quot; class=&quot;narrowcolumn&quot;&gt;

    &lt;?php
    if(isset($_GET['author_name'])) :
        $curauth = get_userdatabylogin($author_name);
    else :
        $curauth = get_userdata(intval($author));
    endif;
    ?&gt;

    &lt;h2&gt;About: &lt;?php echo $curauth-&gt;nickname; ?&gt;&lt;/h2&gt;
    &lt;dl&gt;
        &lt;dt&gt;Website&lt;/dt&gt;
        &lt;dd&gt;&lt;a href=&quot;&lt;?php echo $curauth-&gt;user_url; ?&gt;&quot;&gt;&lt;?php echo $curauth-&gt;user_url; ?&gt;&lt;/a&gt;&lt;/dd&gt;
        &lt;dt&gt;Profile&lt;/dt&gt;
        &lt;dd&gt;&lt;?php echo $curauth-&gt;user_description; ?&gt;&lt;/dd&gt;
    &lt;/dl&gt;

    &lt;h2&gt;Posts by &lt;?php echo $curauth-&gt;nickname; ?&gt;:&lt;/h2&gt;

    &lt;ul&gt;

    &lt;!-- The Loop --&gt;

    &lt;?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?&gt;
        &lt;li&gt;
            &lt;a href=&quot;&lt;?php the_permalink() ?&gt;&quot; rel=&quot;bookmark&quot; title=&quot;Permanent Link: &lt;?php the_title(); ?&gt;&quot;&gt;
            &lt;?php the_title(); ?&gt;&lt;/a&gt;,
            &lt;?php the_time('d M Y'); ?&gt; in &lt;?php the_category('&amp;amp;');?&gt;
        &lt;/li&gt;

    &lt;?php endwhile; else: ?&gt;
        &lt;p&gt;&lt;?php _e('No posts by this author.'); ?&gt;&lt;/p&gt;

    &lt;?php endif; ?&gt;

    &lt;!-- End Loop --&gt;

    &lt;/ul&gt;
&lt;/div&gt;
&lt;?php get_sidebar(); ?&gt;
&lt;?php get_footer(); ?&gt;
</pre>
<p>Pretty nifty, huh? It even has the kindness to display a loop of posts authored by the user. All this thing is doing is dumping the user's meta into $curauth, so that you can request individual profile fields by echoing<br />
"$curauth->name_of_your_field;"&emsp;this will come in handy later when we make our own custom meta. </p>
<p>Next up, <a href="http://www.dquinn.net/integrating-user-photo-with-members-list">Integrating User Photo with Members List &raquo;</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.dquinn.net/creating-author-template-wordpress/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Integrating User Photo with Members List</title>
		<link>http://www.dquinn.net/integrating-user-photo-with-members-list/</link>
		<comments>http://www.dquinn.net/integrating-user-photo-with-members-list/#comments</comments>
		<pubDate>Tue, 25 Aug 2009 17:50:10 +0000</pubDate>
		<dc:creator>Daniel Quinn</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[author template]]></category>
		<category><![CDATA[avatar]]></category>
		<category><![CDATA[gravatar]]></category>
		<category><![CDATA[identicons]]></category>
		<category><![CDATA[members list]]></category>
		<category><![CDATA[monsterIDs]]></category>
		<category><![CDATA[user photo]]></category>
		<category><![CDATA[wavatars]]></category>

		<guid isPermaLink="false">http://www.dquinn.net/?p=1866</guid>
		<description><![CDATA[What WordPress does with avatars is already fairly cool—you have the option of allowing Gravatars as well as implementing randomly generated Wavatars, Identicons or MonsterIDs. The <a href="http://wordpress.org/extend/plugins/user-photo/">User Photo plugin</a> lets users upload a photo of their choice via their Profile. If users don't upload a photo, we can have the avatar "fall back" to the user's gravatar, or, optionally, generate a random avatar according to WordPress' Discussion settings. This guarantees that users will always have avatars.]]></description>
			<content:encoded><![CDATA[<p>What WordPress does with avatars is already fairly cool—you have the option of allowing Gravatars as well as implementing randomly generated Wavatars, Identicons or MonsterIDs. The <a href="http://wordpress.org/extend/plugins/user-photo/">User Photo plugin</a> lets users upload a photo of their choice via their Profile. If users don't upload a photo, we can have the avatar "fall back" to the user's gravatar, or, optionally, generate a random avatar according to WordPress' Discussion settings. This guarantees that users will always have avatars.</p>
<p>We want the cascade of fallbacks to work with Members List and in our Author template. We also need to make the plugin automatically approve new user photos (because, most likely, you don't want to manually approve every user's photo, and the plugin's option to turn this off doesn't work). So go download and install <a href="http://wordpress.org/extend/plugins/user-photo/">User Photo</a>, and check off both "Serve Avatar as Fallback" and "Override Avatar with User Photo" in its settings. Then add the following code to your functions.php template (thanks to <a href="http://wordpress.org/support/topic/195815">this forum post</a>):</p>
<pre class="brush: php;">
// auto approval in user photo plugin
add_action( 'profile_update' , 'auto_approve_photo' , 1000 );
function auto_approve_photo() {
	global $current_user;
	if ( defined( 'IS_PROFILE_PAGE' ) ) {
		update_usermeta( $current_user-&gt;ID , 'userphoto_approvalstatus' , USERPHOTO_APPROVED );
	}
}
</pre>
<p>All right, perfect—now users can add photos without our intervention. Next, we need to be able to call the plugin's main function without echoing it, so that we can make it play nicely with Members List. We'll need to add an extra parameter to the function to do this. Crack open user-photo.php in the plugin's folder:</p>
<p>Find line 285:</p>
<pre class="brush: php; wrap-lines: true;">
function userphoto($user, $before = '', $after = '', $attributes = array(), $default_src = ''){
</pre>
<p>And add a new "echo" parameter:</p>
<pre class="brush: php; wrap-lines: true;">
function userphoto($user, $before = '', $after = '', $attributes = array(), $default_src = '', $echo=TRUE) {
</pre>
<p>Find line 298:</p>
<pre class="brush: php; wrap-lines: true;">
echo userphoto__get_userphoto($userid, USERPHOTO_FULL_SIZE, $before, $after, $attributes, $default_src);
</pre>
<p>Replace with this:</p>
<pre class="brush: php;">
if ($echo == TRUE) {
     echo userphoto__get_userphoto($userid, USERPHOTO_FULL_SIZE, $before, $after, $attributes, $default_src);
} else {
     return userphoto__get_userphoto($userid, USERPHOTO_FULL_SIZE, $before, $after, $attributes, $default_src);
}
</pre>
<p>Last but not least, you might want to make some of the GUI stuff more user friendly. Between lines 358 and 376, you'll find the error messages that get displayed to the user for various failed actions. In my version, I also cleaned up the markup involved, and removed the "full size" photo from displaying (since users tend to upload enormous photos).</p>
<p>Next, we need to stop the plugin from emailing us every time a user uploads a photo. Strangely, the plugin will still email us even though the photo is automatically approved:</p>
<p>Find line 449 and comment it out:</p>
<pre class="brush: php; wrap-lines: true;">
//@wp_mail($admin-&gt;user_email, &quot;User Photo for &quot; . $userdata-&gt;display_name . &quot; Needs Approval&quot;,        get_option(&quot;home&quot;) . &quot;/wp-admin/user-edit.php?user_id=&quot; . $userdata-&gt;ID . &quot;#userphoto&quot;);
</pre>
<p>Great. Now all we need to do is fix the relevant portion of Members List so that it makes a call to User Photo.</p>
<h2>Make Members List call User Photo</h2>
<p>Open up "tern_wp_members.php" in the Members List plugin, and find line 799:</p>
<pre class="brush: php; wrap-lines: true;">
$s .= '&lt;a class=&quot;tern_wp_member_gravatar&quot; href=&quot;'.get_bloginfo('url').'/?author='.$u-&gt;ID.'&quot;&gt;'.&quot;\n        &quot;.get_avatar($u-&gt;ID,60).&quot;\n    &quot;.'&lt;/a&gt;'.&quot;\n    &quot;;
</pre>
<p>And replace with the following:</p>
<pre class="brush: php;">
$s .= '&lt;a class=&quot;tern_wp_member_gravatar&quot; href=&quot;'.get_bloginfo('url').'/?author='.$u-&gt;ID.'&quot;&gt;';
if(userphoto_exists($u-&gt;ID)) {
	$s .= userphoto($u, '','',array(),'',FALSE);
} else {
	$s .= get_avatar($u-&gt;ID, 64);
}
$s .= '&lt;/a&gt;';
</pre>
<p>Awesome. We gained both the conditionality that User Photo provides and Members List's highly customizable archive. I tend to prevent plugins from spewing their own stylesheets and scripts into the headers of my themes, so feel free at this point to remove Member List's CSS and apply your own. Search for ".css" in tern_wp_members.php to remove its default stylesheet.</p>
<p>If you would like to use my User Photo and Members list install, you can simply download <a href="http://www.dquinn.net/images/user-photo.zip">user-photo.php</a> and <a href="http://www.dquinn.net/images/tern-wp-members.zip">tern_wp_members.php</a>.</p>
<p>At this point, you can go back to your Author archive template and display the user's photo/gravatar/identicon. In the definition list, add the following code:</p>
<pre class="brush: php;">
echo &quot;&lt;dt&gt;Photo&lt;/dt&gt;&quot;;
if(userphoto_exists($curauth-&gt;ID)) {
     echo &quot;&lt;dd&gt;&quot;.userphoto($curauth).&quot;&lt;/dd&gt;&quot;;
} else {
     echo &quot;&lt;dd&gt;&quot;.get_avatar($curauth-&gt;ID, 64).&quot;&lt;/dd&gt;&quot;;
}
</pre>
<p>Next up, <a href="http://www.dquinn.net/adding-custom-user-meta-profile-fields-wordpress/">Adding Custom User Meta Fields to the WordPress Profile »</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.dquinn.net/integrating-user-photo-with-members-list/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>Adding Custom User Meta to WordPress User Profiles</title>
		<link>http://www.dquinn.net/adding-custom-user-meta-profile-fields-wordpress/</link>
		<comments>http://www.dquinn.net/adding-custom-user-meta-profile-fields-wordpress/#comments</comments>
		<pubDate>Mon, 24 Aug 2009 17:52:51 +0000</pubDate>
		<dc:creator>Daniel Quinn</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[author template]]></category>
		<category><![CDATA[custom user meta]]></category>
		<category><![CDATA[members list]]></category>
		<category><![CDATA[register plus]]></category>
		<category><![CDATA[rokkyuu]]></category>

		<guid isPermaLink="false">http://www.dquinn.net/?p=1887</guid>
		<description><![CDATA[So far, you've got a nice, <a href="http://dev.dquinn.net/guest/members/">browsable archive of your registered users</a> thanks to <a href="http://wordpress.org/extend/plugins/members-list/">Members List</a>, with each user's profile being more or less infinitely customizable through <a href="http://www.dquinn.net/creating-author-template-wordpress/">the Author template</a>. Plus users can upload their own photos. Naturally, the next step is to extend user profiles with own custom user meta.]]></description>
			<content:encoded><![CDATA[<p><strong>UPDATE: Hi. If you're running WordPress 2.9, reconsider this approach, as there is now a way to add custom user meta via core functions. Visit <a href="http://justintadlock.com/archives/2009/09/10/adding-and-using-custom-user-profile-fields">Justin Tadlock's blog</a> for a short and sweet summary of how to do this.</strong></p>
<p>So far, you've got a nice, <a href="http://dev.dquinn.net/guest/members/">browsable archive of your registered users</a> thanks to <a href="http://wordpress.org/extend/plugins/members-list/">Members List</a>, with each user's profile being more or less infinitely customizable through <a href="http://www.dquinn.net/creating-author-template-wordpress/">the Author template</a>. Plus users can upload their own photos. Naturally, the next step is to extend user profiles with our own custom user meta.</p>
<p>On (the very hacky) <a href="http://www.rokkyuu.com">Rokkyuu.com</a>, I used an ancient plugin called <a href="http://wordpress.org/extend/plugins/register-plus/">Register Plus</a> to create new user meta, and had to hack the core to display the new Profile fields in the Dashboard. Hacking the WordPress core sucks, and Register Plus is more or less an abandoned plugin, with very unstable innards. Since we've come this far, we want something more reliable.</p>
<p><a href="http://www.dquinn.net/extending-user-profiles-wordpress/#footnote">As I mentioned before</a>, we're still waiting on WordPress 2.9 (or later) to provide us with the necessary filters to alter the core profile template in the Dashboard. In the meantime, we can create a plugin that will add new fields to the Profile. The plugin you create would be specific to your theme/project, but since it's a plugin, it wouldn't involve hacking the core. We start with a proof of concept from Peter Westwood with a few of my changes:</p>
<pre class="brush: php;">
&lt;?php
/*
Plugin Name: Custom User Meta
Plugin URI: http://blog.ftwr.co.uk/archives/2009/07/19/adding-extra-user-meta-fields
Description: Allows users to configure extra user meta values.
Author: Peter Westwood, Daniel Quinn
Version: 0.02
Author URI: http://www.dquinn.net

Add new custom user meta fields to the user's Profile in the WordPress Dashboard.

*/

class custom_user_meta {

function custom_user_meta() {
    if ( is_admin() ) {
        add_action('show_user_profile', array(&amp;$this,'action_show_user_profile'));
        add_action('edit_user_profile', array(&amp;$this,'action_show_user_profile'));
        add_action('personal_options_update', array(&amp;$this,'action_process_option_update'));
        add_action('edit_user_profile_update', array(&amp;$this,'action_process_option_update'));
    }
}

function action_show_user_profile($user) {
    ?&gt;
    &lt;h3&gt;&lt;?php _e('Other Contact Info') ?&gt;&lt;/h3&gt;

    &lt;table class=&quot;form-table&quot;&gt;
    &lt;tr&gt;
        &lt;th&gt;&lt;label for=&quot;extra1&quot;&gt;&lt;?php _e('Extra Value'); ?&gt;&lt;/label&gt;&lt;/th&gt;
        &lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;extra1&quot; id=&quot;extra1&quot; value=&quot;&lt;?php echo esc_attr(get_the_author_meta('extra1', $user-&gt;ID) ); ?&gt;&quot; /&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;/table&gt;
    &lt;?php
}

function action_process_option_update($user_id) {
    update_usermeta($user_id, 'extra1', ( isset($_POST['extra1']) ? $_POST['extra1'] : '' ) );
}

}

/* Initialise outselves */
add_action('plugins_loaded', create_function('','global $custom_user_meta_instance; $custom_user_meta_instance = new custom_user_meta();'));
?&gt;
</pre>
<p>Save this as "my-custom-user-meta.php" in the plugins folder under /custom-usermeta/. Activate the plugin.</p>
<p>You should now see an extra area in the Profile called "Other Contact Info" with a single new custom user meta field: Extra Value. All users now have access to this new value. The best part is that you can call this value in your Author template as you would any other user meta. To add it to your definition list:</p>
<pre class="brush: php;">
&lt;dt&gt;Extra Custom Value&lt;/dt&gt;
&lt;dd&gt;&lt;?php echo $curauth-&gt;something; ?&gt;&lt;/dd&gt;
&lt;dt&gt;Twitter&lt;/dt&gt;
&lt;dd&gt;&lt;?php echo $curauth-&gt;twitter; ?&gt;&lt;/dd&gt;
&lt;dt&gt;Textarea&lt;/dt&gt;
&lt;dd&gt;&lt;?php echo $curauth-&gt;bio2; ?&gt;&lt;/dd&gt;
</pre>
<p>You can add any fields you want, first by simply adding new table rows (or entire tables)...</p>
<pre class="brush: php;">
&lt;table class=&quot;form-table&quot;&gt;
    &lt;tr&gt;
        &lt;th&gt;&lt;label for=&quot;extra1&quot;&gt;&lt;?php _e('Extra Value'); ?&gt;&lt;/label&gt;&lt;/th&gt;
        &lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;extra1&quot; id=&quot;extra1&quot; value=&quot;&lt;?php echo esc_attr(get_the_author_meta('extra1', $user_id) ); ?&gt;&quot; /&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;th&gt;&lt;label for=&quot;twitter&quot;&gt;&lt;?php _e('Twitter Username'); ?&gt;&lt;/label&gt;&lt;/th&gt;
        &lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;twitter&quot; id=&quot;twitter&quot; value=&quot;&lt;?php echo esc_attr(get_the_author_meta('twitter', $user_id) ); ?&gt;&quot; /&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;th&gt;&lt;label for=&quot;bio2&quot;&gt;&lt;?php _e('Bio2'); ?&gt;&lt;/label&gt;&lt;/th&gt;
        &lt;td&gt;&lt;textarea name=&quot;bio2&quot; cols=&quot;10&quot; rows=&quot;10&quot; id=&quot;bio2&quot;&gt;&lt;?php echo esc_attr(get_the_author_meta('bio2', $user_id) ); ?&gt;&lt;/textarea&gt;&lt;/td&gt;
    &lt;/tr&gt;
&lt;/table&gt;
</pre>
<p>...and second, by processing them:</p>
<pre class="brush: php;">
update_usermeta($user_id, 'extra1', ( isset($_POST['extra1']) ? $_POST['extra1'] : '' ) );
update_usermeta($user_id, 'twitter', ( isset($_POST['twitter']) ? $_POST['twitter'] : '' ) );
update_usermeta($user_id, 'bio2', ( isset($_POST['bio2']) ? $_POST['bio2'] : '' ) );
</pre>
<p>If you want to display each value only if the user has filled it out, you could do something like:</p>
<pre class="brush: php;">
&lt;?php if ($curauth-&gt;something) { ?&gt;
    &lt;dt&gt;Extra Custom Value&lt;/dt&gt;
    &lt;dd&gt;&lt;?php echo $curauth-&gt;something; ?&gt;&lt;/dd&gt;
&lt;?php } ?&gt;
&lt;?php if ($curauth-&gt;twitter) { ?&gt;
    &lt;dt&gt;Twitter&lt;/dt&gt;
    &lt;dd&gt;&lt;?php echo $curauth-&gt;twitter; ?&gt;&lt;/dd&gt;
&lt;?php } ?&gt;
&lt;?php if ($curauth-&gt;bio2) { ?&gt;
    &lt;dt&gt;Textarea&lt;/dt&gt;
    &lt;dd&gt;&lt;?php echo $curauth-&gt;bio2; ?&gt;&lt;/dd&gt;
&lt;?php } ?&gt;
</pre>
<p>Simple stuff. And thanks for the snippet, Peter.</p>
<p><strong>UPDATE: </strong>Some of you asked how you would handle radio buttons, dropdowns, and checkboxes. It's no different than you would normally do these types of input boxes in any PHP form. Remember that with checkboxes, the idea is that the user is choosing one or more items in your list (and the $_POST values from the checkboxes are added to a checkbox array), and with radio buttons, the user is choosing one of the available options. The latter is true of dropdowns too:</p>
<pre class="brush: php;">
&lt;tr&gt;
     &lt;th&gt;&lt;label for=&quot;penguins&quot;&gt;&lt;?php _e('Favorite Penguin'); ?&gt;&lt;/label&gt;&lt;/th&gt;
     &lt;td&gt;
          &lt;select name=&quot;penguins&quot; id=&quot;penguins&quot;&gt;
               &lt;option value=&quot;&quot; &lt;?php if (esc_attr(get_the_author_meta('penguins',$user-&gt;ID)) == &quot;&quot;) { ?&gt;selected&lt;?php } ?&gt;&gt;- Choose a Penguin -&lt;/option&gt;
               &lt;option value=&quot;Happy Penguin&quot; &lt;?php if (esc_attr(get_the_author_meta('penguins',$user-&gt;ID)) == &quot;Happy Penguin&quot;) { ?&gt;selected&lt;?php } ?&gt;&gt;Happy Penguin&lt;/option&gt;
               &lt;option value=&quot;Sad Penguin&quot; &lt;?php if (esc_attr(get_the_author_meta('penguins',$user-&gt;ID)) == &quot;Sad Penguin&quot;) { ?&gt;selected&lt;?php } ?&gt;&gt;Sad Penguin&lt;/option&gt;
               &lt;option value=&quot;Ugly Penguin&quot; &lt;?php if (esc_attr(get_the_author_meta('penguins',$user-&gt;ID)) == &quot;Ugly Penguin&quot;) { ?&gt;selected&lt;?php } ?&gt;&gt;Ugly Penguin&lt;/option&gt;
          &lt;/select&gt;
     &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;th&gt;&lt;?php _e('Potatoes I Like'); ?&gt;&lt;/th&gt;
    &lt;td&gt;
        &lt;?php
          $potato_array = get_the_author_meta('potatoes',$user-&gt;ID);
        ?&gt;
        &lt;ul&gt;
          &lt;li&gt;&lt;input value=&quot;Hot Potato&quot; id=&quot;hot_potato&quot; name=&quot;potatoes[]&quot; &lt;?php if (is_array($potato_array)) { if (in_array(&quot;Hot Potato&quot;,$potato_array)) { ?&gt;checked=&quot;checked&quot;&lt;?php } }?&gt; type=&quot;checkbox&quot; /&gt; Hot Potato&lt;/li&gt;
          &lt;li&gt;&lt;input value=&quot;Cold Potato&quot; id=&quot;cold_potato&quot; name=&quot;potatoes[]&quot; &lt;?php if (is_array($potato_array)) { if (in_array(&quot;Cold Potato&quot;,$potato_array)) { ?&gt;checked=&quot;checked&quot;&lt;?php } } ?&gt; type=&quot;checkbox&quot; /&gt; Cold Potato&lt;/li&gt;
          &lt;li&gt;&lt;input value=&quot;Salty Potato&quot; id=&quot;salty_potato&quot; name=&quot;potatoes[]&quot; &lt;?php if (is_array($potato_array)) { if (in_array(&quot;Salty Potato&quot;,$potato_array)) { ?&gt;checked=&quot;checked&quot;&lt;?php } } ?&gt; type=&quot;checkbox&quot; /&gt; Salty Potato&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;th&gt;&lt;?php _e('Monkeys'); ?&gt;&lt;/th&gt;
    &lt;td&gt;
         &lt;?php
           $monkeys = get_the_author_meta('monkeys',$user-&gt;ID);
         ?&gt;
        &lt;ul&gt;
            &lt;li&gt;&lt;input value=&quot;Blue Monkey&quot; id=&quot;blue_monkey&quot; name=&quot;monkeys&quot; &lt;?php if ($monkeys == &quot;Blue Monkey&quot;) { ?&gt;checked=&quot;checked&quot;&lt;?php } ?&gt; type=&quot;radio&quot; /&gt; Blue Monkey&lt;/li&gt;
            &lt;li&gt;&lt;input value=&quot;Red Monkey&quot; id=&quot;red_monkey&quot; name=&quot;monkeys&quot; &lt;?php if ($monkeys == &quot;Red Monkey&quot;) { ?&gt;checked=&quot;checked&quot;&lt;?php } ?&gt; type=&quot;radio&quot; /&gt; Red Monkey&lt;/li&gt;
            &lt;li&gt;&lt;input value=&quot;Yellow Monkey&quot; id=&quot;yellow_monkey&quot; name=&quot;monkeys&quot; &lt;?php if ($monkeys == &quot;Yellow Monkey&quot;) { ?&gt;checked=&quot;checked&quot;&lt;?php } ?&gt; type=&quot;radio&quot; /&gt; Yellow Monkey&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/td&gt;
&lt;/tr&gt;
</pre>
<p>In the case of the dropdowns or the radio button, we are checking to see if the variable already exists, and if it does, we add "checked" for radio buttons to the appropriate button, or "selected" for options in a dropdown. In the case of the checkboxes, we need to add the "checked" attribute to any checkboxes that exist in the checkbox array. <strong>I've added these values to my dev area, so you can try it for yourself.</strong></p>
<p><strong>UPDATE: </strong>Apparently the variables you use need to be all lowercase. Rose (a commenter below) had a problem with fields in the profile not saving if the variables were camelCase. Can anyone else confirm? WP does recommend all-lowercase  variables in its <a href="http://codex.wordpress.org/WordPress_Coding_Standards">coding standards</a> with underscores for spaces, but I didn't realize camelCase would simply not be saved in the db by WP? Server config? Dunno.</p>
<p><strong>UPDATE:</strong> Check out Vlad's sweet implementation of this plugin: <a href="http://prospace.superfreelancer.com">http://prospace.superfreelancer.com</a>. Of course, for pre-2.9 extended user profiles, we should thank <a href="http://blog.ftwr.co.uk/archives/2009/07/19/adding-extra-user-meta-fields">Peter Westwood</a> for having originally written this script... I just made some modifications and answered a few questions <img src='http://www.dquinn.net/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p><strong>UPDATE:</strong> A commenter named Ruben below has shared how he figured out sorting the custom meta fields outside the profile. Check it out in Dutch: <a href="http://rubenwoudsma.nl/wordpress-gebruikersprofiel-uitbreiden/">http://rubenwoudsma.nl/wordpress-gebruikersprofiel-uitbreiden/</a></p>
<p><strong>UPDATE:</strong> Peter made an update to the plugin, replacing the call to global $user_id with $user-&gt;ID. This is reflected in the updated code.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dquinn.net/adding-custom-user-meta-profile-fields-wordpress/feed/</wfw:commentRss>
		<slash:comments>164</slash:comments>
		</item>
		<item>
		<title>Sort Posts by Last Name Using Nate Olsen&#8217;s WP Snap Plugin for WordPress</title>
		<link>http://www.dquinn.net/sort-posts-by-last-name-using-nate-olsens-wp-snap-plugin-for-wordpress/</link>
		<comments>http://www.dquinn.net/sort-posts-by-last-name-using-nate-olsens-wp-snap-plugin-for-wordpress/#comments</comments>
		<pubDate>Thu, 20 Aug 2009 12:57:39 +0000</pubDate>
		<dc:creator>Daniel Quinn</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[emerson college]]></category>
		<category><![CDATA[fringe magazine]]></category>
		<category><![CDATA[nateomedia]]></category>
		<category><![CDATA[nathan olsen]]></category>
		<category><![CDATA[redivider]]></category>
		<category><![CDATA[sort by last name]]></category>
		<category><![CDATA[wp snap]]></category>

		<guid isPermaLink="false">http://www.dquinn.net/?p=1812</guid>
		<description><![CDATA[I’ve used <a href="http://www.nateomedia.com/">Nateomedia.com</a>’s <a href="http://www.nateomedia.com/wares/downloads/wordpress/wp-snap/">WP Snap plugin</a> for quite awhile now, whether it was to sort through encyclopedia  entries, organize archives of contributor bios, or simulate a dictionary in WordPress. On Nathan Olsen’s website, <a href="http://www.nateomedia.com/wares/downloads/wordpress/wp-snap/?cp=all#comment-14651">one commenter mentioned</a> how he had managed to make WP Snap organize an archive of bios, but sorted by last, middle, and then first name. Unfortunately, the sample code the commenter provided got mangled by Nate’s comments sanitizer, so I decided to muck through the plugin myself and hack together a solution.]]></description>
			<content:encoded><![CDATA[<p>I’ve used <a href="http://www.nateomedia.com">Nateomedia.com</a>’s <a href="http://www.nateomedia.com/wares/downloads/wordpress/wp-snap/">WP Snap plugin</a> for quite awhile now, whether it was to sort through encyclopedia  entries, organize archives of contributor bios, or simulate a dictionary in WordPress. On Nathan Olsen’s website, <a href="http://www.nateomedia.com/wares/downloads/wordpress/wp-snap/?cp=all#comment-14651">one commenter mentioned</a> how he had managed to make WP Snap organize an archive of bios, but sorted by last, middle, and then first name. Unfortunately, the sample code the commenter provided got mangled by Nate’s comments sanitizer, so I decided to muck through the plugin myself and hack together a solution. This is a screenshot of what Nate’s plugin can do, from his website:</p>
<div id="attachment_1789" class="wp-caption aligncenter" style="width: 497px;"><img class="size-full wp-image-1789 " src="http://www.dquinn.net/images/wp-snap_screen.gif" alt="" width="487" /></p>
<p class="wp-caption-text">WP Snap Demo</p>
</div>
<p>I first used <a href="http://www.redividerjournal.org/contributors/">WP Snap on Redivider</a>, the literary journal for Emerson College. But for <a href="http://www.fringemagazine.org/contributors/">Fringe Magazine</a>, I needed to organize contributor bios by last name. And at Harvard Common Press, I needed to do the same thing with <a href="http://www.harvardcommonpress.com/archives/authors/">author bios </a><em>and </em>the <a href="http://www.harvardcommonpress.com/archives/titles/">publisher’s title list</a>. So the first thing I did was cordon off Nate’s original WP Snap function in the plugin, so that I could still sort posts as the plugin normally does:</p>
<p>On line 168, change:</p>
<pre class="brush: php;">$nav = new wp_snap_core();</pre>
<p>To:</p>
<pre class="brush: php;">
if ($snapqueryarray['ordertype'] == &quot;names&quot;) {
    $nav = new wp_snap_core_names();
} else {
    $nav = new wp_snap_core();
}
</pre>
<p>This allows us to make two different calls to the plugin:</p>
<pre class="brush: php;">
// and if we want to sort posts by last, middle, and then first name
&lt;?php  if (function_exists('wp_snap')) { echo wp_snap('&amp;ordertype=names); } ?&gt;

// if we want to sort posts by the title normally:
&lt;?php  if (function_exists('wp_snap')) { echo wp_snap(); } ?&gt;
</pre>
<p>Now all we need to do is install the section wp_snap_core_names() function into the plugin. Search for “$all_posts = $wpdb-&gt;get_results($request);” and insert the following code on the line below it:</p>
<pre class="brush: php;">
for ($i=0; $i &lt; count($all_posts); $i++) {
    $name_set[$i] = preg_replace('/^(' . $exclude[1] . ')+((' . $exclude[2] . ')[\s]+)*|^(' . $exclude[2] . ')[\s]+/i', '', wp_snap_core::accents($all_posts[$i]-&gt;post_title));
}
for ($k=0; $k &lt; count($name_set); $k++) {
    $word_parts = explode(&quot; &quot;, $name_set[$k]);
    $number_of_names = count($word_parts);
    $the_name = &quot;&quot;;
for ($x=$number_of_names; $x&gt;=0; $x--) {
    $the_name .= $word_parts[$x].' ';
}
unset($name_set[$k]);
$name_set[$k] = trim($the_name);
}
</pre>
<p>What we’re doing here is going through the array of post titles and reversing each word in the string, so that the order is last name, first name, and then middle name. This should work for any number of words in the post title.</p>
<p>Now search for this preg_replace, which is just below the above code:</p>
<pre class="brush: php;">
$word_results[$i] = preg_replace('/^(' . $exclude[1] . ')+((' . $exclude[2] . ')[\s]+)*|^(' . $exclude[2] . ')[\s]+/i', '', wp_snap_core::accents($all_posts[$i]-&gt;post_title));
</pre>
<p>Replace this with:</p>
<pre class="brush: php;">$word_results[$i] = $name_set[$i];</pre>
<p>Finally, search for “// Resorts $wp_snap_posttitles, taking excluded words into account” and add the following code just above that line:</p>
<pre class="brush: php;">
for ($i=0; $i&lt;count($all_posts); $i++) {
    $word_parts = explode(&quot; &quot;, $all_posts[$i]-&gt;post_title);
    $number_of_names = count($word_parts);
    $the_name = &quot;&quot;;
for ($x=$number_of_names; $x&gt;=0; $x--) {
    $the_name .= $word_parts[$x].' ';
}
unset($all_posts[$i]-&gt;post_title);
$all_posts[$i]-&gt;post_title = trim($the_name);
}
</pre>
<p>Okay, now the plugin is all set to display these posts sorted by last name first. When you call &lt;?php  if (function_exists('wp_snap')) { echo wp_snap('&amp;ordertype=names); } ?&gt; in your template (following &lt;a&gt;Nate’s regular instructions for using the plugin&lt;/a&gt;), you’ll notice that when you click on a letter, you’ll only get posts where the last name begins with that letter:</p>
<pre class="brush: plain;">
C

Callaway William
Chau François
Cullen Peter
Cummings R. Brian
</pre>
<p>Great, this means the posts are actually being sorted by last name first. The only problem now is that because we altered the post titles in the loop, the names are being <em>displayed</em> last name first, which we don’t want. So we add a bit of code to our template to rearrange the post title back to the original order of the words in the string, so that they display first name first:</p>
<pre class="brush: php;">
&lt;?php  if (function_exists('wp_snap')) { echo wp_snap('cat=4'); } ?&gt;
    &lt;?php $wp_query-&gt;is_archive = true; ?&gt;
    &lt;?php while (have_posts()) : the_post(); ?&gt;
        &lt;?php $author_name = get_the_title(); ?&gt;
        &lt;a href=&quot;&lt;?php the_permalink() ?&gt;&quot; rel=&quot;bookmark&quot; title=&quot;&lt;?php the_title_attribute(); ?&gt;&quot;&gt;
        &lt;?php // we need to put the names back in the correct order
            $word_parts = explode(&quot; &quot;, get_the_title());
            $the_name = &quot;&quot;;
            $number_of_names = count($word_parts);
            for ($x=$number_of_names; $x&gt;=0; $x--) {
               $the_name .= $word_parts[$x].' ';
            }
            echo trim($the_name); ?&gt;
         &lt;/a&gt;
</pre>
<p>And that’s it. Now our names should display normally: William Callaway, François Chau, Peter Cullen, Brian R. Cummings.</p>
<p>For the sake of posterity (and laziness), you can download version 0.8.6 of WP Snap (the one I tweaked) as well as my modified plugin file below:</p>
<p>Original WP Snap Plugin, version 0.8.6: <a href="http://www.dquinn.net/images/wp-snap.zip">wp-snap.zip</a></p>
<p>Modified WP Snap Plugin: <a href="http://www.dquinn.net/images/wp-snap-dquinn.zip">wp-snap-dquinn.zip</a></p>
<p>Enjoy.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dquinn.net/sort-posts-by-last-name-using-nate-olsens-wp-snap-plugin-for-wordpress/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Autoupdate Thunderbird Signature with Your Latest WordPress Post</title>
		<link>http://www.dquinn.net/autoupdate-thunderbird-signature-with-latest-blog-post/</link>
		<comments>http://www.dquinn.net/autoupdate-thunderbird-signature-with-latest-blog-post/#comments</comments>
		<pubDate>Tue, 18 Aug 2009 05:00:47 +0000</pubDate>
		<dc:creator>Daniel Quinn</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[batch file]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[rss]]></category>
		<category><![CDATA[rss parser]]></category>
		<category><![CDATA[thunderbird]]></category>
		<category><![CDATA[vb]]></category>

		<guid isPermaLink="false">http://www.dquinn.net/?p=1788</guid>
		<description><![CDATA[So this is what we're going to do: First, we'll write a quick local PHP script that parses the RSS feed of your blog, to get the latest blog post's URL and title. Then, we'll save that information to a .txt file, which you will set as your signature in Thunderbird. Finally, we'll write a .vb file that will open your script, update the .txt file, and then close itself when your computer boots.]]></description>
			<content:encoded><![CDATA[<p>Here's dirty hack for sh*ts and giggles. Ever get bored of having the same old signature line in Thunderbird? Instead of a stale link back to your blog, why not have a link to the latest post on your blog?</p>
<p><em>Note: In order for this setup to work, you need to have PHP installed locally. If you webdev, this will be easy.</em></p>
<p>So this is what we're going to do: First, we'll write a quick local PHP script that parses the RSS feed of your blog, to get the latest blog post's URL and title. Then, we'll save that information to a .txt file, which you will set as your signature in Thunderbird. Finally, we'll write .vbs and .bat files that will open your script, update the .txt file, and then close themselves as your computer boots. All you need is a text editor to do this.</p>
<p>First, download this <a href="http://apptools.com/phptools/downloads/rssreader.zip">RSS parser</a> and drop it in a folder in your webdev directory. Next, create a file in the same folder called signature-get.php, with the following code:</p>
<pre class="brush: php;">
&lt;?php
$doc = new DOMDocument();
$doc-&gt;load('http://www.dquinn.net/feed/');
$titles = array();
$permalink = array();
foreach ($doc-&gt;getElementsByTagName('item') as $node) {
    $titles[] = $node-&gt;getElementsByTagName('title')-&gt;item(0)-&gt;nodeValue;
    $permalink[] = $node-&gt;getElementsByTagName('link')-&gt;item(0)-&gt;nodeValue;
}
$titles[0] = str_replace(&quot;’&quot;,&quot;'&quot;,$titles[0]);
$titles[0] = str_replace(&quot;“&quot;,'&quot;',$titles[0]);
$titles[0] = str_replace(&quot;”&quot;,'&quot;',$titles[0]);
$signature .= $titles[0] . &quot;\n&quot;;
$signature .= $permalink[0] . &quot;\n\n&quot;;
$signature .= &quot;read more @ http://www.dquinn.net&quot;.&quot;\n&quot;;
$sigfile = &quot;Signature.txt&quot;;
$fh = fopen($sigfile, 'w') or die(&quot;can't open file&quot;);
$sigtext = $signature;
fwrite($fh, $sigtext);
fclose($fh);
?&gt;
</pre>
<p>Be sure to replace my URL and feed with your own. This was written for a WordPress feed, but with minimal tweaking it should work with any valid RSS. Next, make a blank signature file—mine is called "Signature.txt"—in the same folder. This is what the PHP script will write to. You must assign this file as your signature in Thunderbird, like so:</p>
<div id="attachment_1789" class="wp-caption aligncenter" style="width: 484px"><img class="size-full wp-image-1789 " title="Thunderbird account settings" src="http://www.dquinn.net/images/sig.jpg" alt="Thunderbird account settings" width="474" height="445" /><p class="wp-caption-text">Thunderbird account settings</p></div>
<p>At this point, if you run the script from your local webserver, you should find that your Signature.txt gets updated with the latest blog post, like so:</p>
<pre class="brush: plain;">
District 9 is Good Science Fiction; Neill Blomkamp Raises the Bar

http://www.dquinn.net/district-9-neill-blomkamp-raises-the-bar/

read more @ http://www.dquinn.net
</pre>
<p>Now we need to run this guy whenever we start our comp, because we are lazy. We don't want a browser window to open up and stay open when we start up the computer (because that's annoying), so we'll command Internet Explorer to open the URL of our script in the background (I do love ordering IE around to do mundane, non-webpage-related tasks. Since the web is clearly not it's specialty...):</p>
<p>Create a .vbs file in the same folder, called "IE.vbs." (I scrubbed this code from a <a href="http://bytes.com/topic/javascript/answers/424647-launching-url-batch-file">forum</a>.) Put the following in it:</p>
<pre class="brush: vb;">
Option Explicit
Dim objIEA
Set objIEA = CreateObject(&quot;InternetExplorer.Application&quot;)
objIEA.Navigate &quot;http://localhost/thunderbird/signature-get.php&quot;
While objIEA.Busy
Wend
Set objIEA = Nothing
</pre>
<p>Okay, so far so good. Make sure that the path "http://localhost/thunderbird/signature-get.php" matches the path to your script on your local webserver. Next, let's run  IE.vb in a batch file. Call this guy "update.bat" and save it in the same folder you've saved everything else:</p>
<pre class="brush: bash;">
@ECHO OFF
:1
echo &gt;wait.vbs wscript.sleep 30000
cscript wait.vbs
del wait.vbs
cscript.exe IE.vbs
exit
</pre>
<p>The "exit" may or may not be necessary. Too lazy to double-check. What's happening here is that we create a .vbs script that waits for 30 seconds and then gets deleted after the wait, effectively delaying our setup long enough for your webserver to kick in, before our PHP script runs.</p>
<p>Finally, drag and drop a shortcut to update.bat into your Startup folder in the Start Menu, and you're good to go. At startup, the command window will stay open for a few seconds while the script runs, and then go away by itself.</p>
<p>Obviously, there are better ways to go about doing this, but this works great for me, so I thought I'd share.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dquinn.net/autoupdate-thunderbird-signature-with-latest-blog-post/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Speed Up Your WordPress: Mastering Yahoo!&#8217;s Thirteen Performance Rules</title>
		<link>http://www.dquinn.net/mastering-yahoos-13-performance-rules/</link>
		<comments>http://www.dquinn.net/mastering-yahoos-13-performance-rules/#comments</comments>
		<pubDate>Fri, 24 Apr 2009 12:39:53 +0000</pubDate>
		<dc:creator>Daniel Quinn</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[.htaccess]]></category>
		<category><![CDATA[blogs]]></category>
		<category><![CDATA[cache-control headers]]></category>
		<category><![CDATA[content delivery network]]></category>
		<category><![CDATA[dns lookups]]></category>
		<category><![CDATA[etags]]></category>
		<category><![CDATA[expires header]]></category>
		<category><![CDATA[facelift plugin]]></category>
		<category><![CDATA[firebug]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[gzip components]]></category>
		<category><![CDATA[http requests]]></category>
		<category><![CDATA[mediatemple]]></category>
		<category><![CDATA[minify]]></category>
		<category><![CDATA[wp super cache]]></category>
		<category><![CDATA[yslow]]></category>

		<guid isPermaLink="false">http://www.dquinn.net/?p=1439</guid>
		<description><![CDATA[The problem is that while the info is definitely out there, it's not all in one place (at least as far as I've browsed). Moreover, there are a couple of specific applications of the speed tricks that haven't been clearly laid out before (particularly, applying Cache-Control headers to dynamic images generated by the WordPress Facelift plugin, or the ideal .htaccess settings if your host is MediaTemple). In the interest of time (and laziness, our one true virtue), I've compiled an easy-to-apply series on YSlow that will get your WordPress sped up in no time.]]></description>
			<content:encoded><![CDATA[<p>All right guys, I know there are already countless articles about speeding up WordPress all over the Google. We've all vied for speed when it comes to preventing our fatass blogs from choking our readers' browsers. The problem is that while the info is definitely out there, it's not all in one place (at least as far as I've browsed). Moreover, there are a couple of specific applications of the speed tricks that haven't been clearly laid out before (particularly, applying cache-control headers to dynamic images generated by the WordPress Facelift plugin, or the ideal .htaccess settings if your host is MediaTemple). In the interest of time (and laziness, our one true virtue), I've compiled an easy-to-apply series on YSlow that will get your WordPress sped up in no time.</p>
<p>First thing's first:</p>
<p>Download <a href="https://addons.mozilla.org/en-US/firefox/addon/5369">YSlow for Firebug</a> if you haven't already, then skim over <a href="http://developer.yahoo.com/performance/rules.html">Yahoo!'s article</a> about the thirteen best practices for speeding up your website:</p>
<ol>
<li><strong>Minimize HTTP Requests</strong> - (<em>Don't make me download a lot of crap</em>.)</li>
<li><strong>Use a Content Delivery Network</strong> (<em>Have someone else serve your shit</em>.)</li>
<li><strong>Add an Expires or Cache-Control Header</strong> (<em>Stale bread is best for french toast. Really</em>.)</li>
<li><strong>GZip Components </strong>(<em>Zip it up!</em>)</li>
<li><strong>Put Stylesheets at the Top </strong>(<em>I need to see your site before I click on stuff, dumbass</em>.)</li>
<li><strong>Put Scripts at the Bottom </strong>(<em>See above</em>.)</li>
<li><del>Avoid CSS Expressions</del> (<em>Who uses them anyway?</em>)</li>
<li><del>Make Javascript and CSS External</del> (<em>Duh.</em>)</li>
<li><strong>Reduce DNS Lookups</strong> (<em>Don't be a social media slut</em>.)</li>
<li><strong>Minify Javascript and CSS </strong>(<em>Nobody wants to see your whitespace</em>.)</li>
<li><del>Avoid Redirects</del> (<em>I came to your site, not theirs.</em>)</li>
<li><del>Remove Duplicate Scripts</del> (<em>Duh</em>.)</li>
<li><strong>Configure ETags</strong> (<em>Yeah, I didn't know what these were either.</em>)</li>
</ol>
<p>I also recommend setting up WP Super Cache after all is said and done. So here we go:</p>
<ul>
<li><a href="http://www.dquinn.net/dont-make-me-download-a-lot-of-crap-yslow">The Unavoidables: Don't Make Me Download a Lot of Crap; or, Sometimes You Just Deserve an F From YSlow, You Shameless Self-Promoter</a></li>
<li><a href="http://www.dquinn.net/htaccess-adding-etags-gzip-expires-headers">Three Sexy Performance Rules for .htaccess on WordPress: Configure ETags, Gzip Compression, and Expires Headers</a></li>
<li><a href="minify-css-javascript-yui-compressor">Nobody Wants to See Your Whitespace: Minify CSS and Javascript using Yahoo!’s UI Compressor</a></li>
</ul>
<p>*<em> Full disclosure</em>: Where do I stand? My front page gets a big fat B (88%) for making you download a lot of crap:</p>
<div id="attachment_1441" class="wp-caption aligncenter" style="width: 404px"><img class="size-full wp-image-1441" title="YSlow Score: DQuinn.net" src="http://www.dquinn.net/images/yslow-rating.gif" alt="YSlow Score: DQuinn.net Home Page" width="394" height="396" /><p class="wp-caption-text">YSlow Score: DQuinn.net Home Page</p></div>
<p>YSlow gleefully reports that 32 CSS background images is downright <em>sinful</em>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dquinn.net/mastering-yahoos-13-performance-rules/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Unavoidables: Don’t Make Me Download a Lot of Crap; or, Sometimes You Just Deserve an F From YSlow, You Shameless Self-Promoter</title>
		<link>http://www.dquinn.net/dont-make-me-download-a-lot-of-crap-yslow/</link>
		<comments>http://www.dquinn.net/dont-make-me-download-a-lot-of-crap-yslow/#comments</comments>
		<pubDate>Thu, 23 Apr 2009 12:39:26 +0000</pubDate>
		<dc:creator>Daniel Quinn</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[cdn]]></category>
		<category><![CDATA[content delivery network]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[lastfm]]></category>
		<category><![CDATA[minified]]></category>
		<category><![CDATA[minimize http requests]]></category>
		<category><![CDATA[netflix]]></category>
		<category><![CDATA[picasa]]></category>
		<category><![CDATA[stylesheets]]></category>
		<category><![CDATA[viacom]]></category>
		<category><![CDATA[yslow]]></category>

		<guid isPermaLink="false">http://www.dquinn.net/?p=1445</guid>
		<description><![CDATA[In all seriousness, however, Yahoo! recommends some (semi-doable) solutions. One idea is to combine all your CSS background images into one enormously fat image, and then use background-position to display portions of that image in different visual areas of the page.]]></description>
			<content:encoded><![CDATA[<p>Rule #1: <strong>Minimize HTTP Requests</strong> (<em>Don't make me download a lot of crap.</em>)</p>
<p>I'm guilty of this one, I admit: I get a nasty F from YSlow for this trespass. On my front page (we shall not speak of the horror that goes on behind the scenes, once you leave my front page), I make you download 32 CSS background images in order to see all the graphics on my website. Is there a better way to go about doing this? Absolutely! Am I too damned lazy to redesign my graphics to appease Rule #1? You bet!</p>
<p>In all seriousness, however, Yahoo! recommends some (semi-doable) solutions. One idea is to combine all your CSS background images into one enormously fat image, and then use background-position to display portions of that image in different visual areas of the page.</p>
<p>Quite frankly, this is an insane suggestion for a site with any degree of design complexity, but it can be done. You just have to be crazy enough.</p>
<p>Another way is to merge your stylesheets into a single .css file. Same for your scripts (you <a href="http://www.ejeliot.com/blog/72"><em>can</em> use a server-side language to combine them on the fly</a>, for example). Really, you shouldn't need to apply multiple stylesheets to a small-scale blog (or even a medium-sized website). The argument is that, if you can get your reader to download and cache all your styles up front (<a href="http://www.dquinn.net/minify-css-javascript-yui-compressor">minified and compressed</a>), her browsing experience across your entire site will be breezier, since that single CSS file encompasses all your selectors. If she's a good girl she doesn't empty her cache often, and we <a href="http://www.dquinn.net/htaccess-adding-etags-gzip-expires-headers">tell her browser to do so on a weekly or monthly basis</a>.</p>
<p>Closing recommendations:</p>
<ul>
<li>Use 1 stylesheet for the whole site. Minify and compress it.</li>
<li>Merge as many of your javascripts into one file as you can, then minify and compress that file. Some of them can be tricky to merge, due to the way they need to load on a page (such as Shadowbox or prototype setups), but if you can turn 5 scripts calls into 2, it's better than doing nothing at all.</li>
</ul>
<h2>Rule #2: I am my own CDN, goddamn it!</h2>
<p>Well, the truth is simply that if we weren't all talentless self-promoting hacks, we'd have the cash to shell out for our very own CDN (Content Delivery Network) and ace YSlow's number two performance rule: Use a Content Delivery Network. Too bad we subsist on Frosted Flakes and other people's half-baked marketing schemes. Rule #2 is an "unavoidable," yet another grim reminder that YSlow is just better than us, and there's nothing we can do about it.</p>
<p>Except cheat, of course. To "ace" rule #2, simply tell Firefox that your server is in fact a CDN, and YSlow will be none the wiser.</p>
<ol>
<li>Type about:config into Firefox.</li>
<li>Type "cdn" into the Filter search field.</li>
<li>You'll see extensions.firebug.yslow.cdnHostnames pop up; double-click on the Value field and then add your domain "mydomain.com" to the list. If there's domains in the list, separate them with commas and put a space before each domain: dquinn.net, mydomain.com, lame.com; etc.</li>
</ol>
<p>Refresh a lot, close Firefox, reboot your computer, take a shower, mow the lawn. Eventually YSlow will begrudgingly concede that your server counts as a CDN and give you much-deserved praise.</p>
<h2>Rule #9: Don't be a social media slut: Reduce DNS Lookups</h2>
<p>This one classifies among the unavoidables because, well, if you really want to integrate social media with your site, you're going to increase DNS lookups. Every lookup for a resource on a server that's not where your website is causes parallel downloading, which in turn slows everything down. On some pages, for example, I hook up with Google's Picasa, various investors' Netflix, and Viacom's Lastfm simultaneously to insert feed data into my pages (scandalous!).</p>
<p>My benefit is that these services help manage my activity so that <em>I</em> don't have to (yes, I realize that sounds very Orwellian), but the problem is that I'm passing <em>my</em> laziness off on <em>your</em> browser.</p>
<p><strong>Conclusion</strong>: Some sacrifices must be made. Try to connect to social media on inner pages, rather than landing pages, so as to speed up load times and reduce your bounce rate.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dquinn.net/dont-make-me-download-a-lot-of-crap-yslow/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Three Sexy Performance Rules for .htaccess on WordPress: Configure ETags, Gzip Compression, and Expires Headers</title>
		<link>http://www.dquinn.net/htaccess-adding-etags-gzip-expires-headers/</link>
		<comments>http://www.dquinn.net/htaccess-adding-etags-gzip-expires-headers/#comments</comments>
		<pubDate>Wed, 22 Apr 2009 15:40:15 +0000</pubDate>
		<dc:creator>Daniel Quinn</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[.htaccess]]></category>
		<category><![CDATA[animalcules]]></category>
		<category><![CDATA[cache-control header]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[dynamic images]]></category>
		<category><![CDATA[etags]]></category>
		<category><![CDATA[facelift image replacement]]></category>
		<category><![CDATA[flir]]></category>
		<category><![CDATA[gzip]]></category>
		<category><![CDATA[homunculi]]></category>
		<category><![CDATA[ie6]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[mediatemple]]></category>
		<category><![CDATA[mod_deflate]]></category>
		<category><![CDATA[mod_gzip]]></category>
		<category><![CDATA[netscape]]></category>
		<category><![CDATA[opera]]></category>
		<category><![CDATA[sifr 3]]></category>
		<category><![CDATA[wp super cache]]></category>
		<category><![CDATA[yahoo]]></category>
		<category><![CDATA[yslow]]></category>

		<guid isPermaLink="false">http://www.dquinn.net/?p=1450</guid>
		<description><![CDATA[<p>For those of us cheapskates on shared servers, our greatest weapon against the admonitions of YSlow is .htaccess, that innocuous text file that has the capacity to blow up your website if you mistreat it. To defeat rules #3: Add an Expires or Cache-Control Header, #4 GZip Components, and #13 Configure ETags, we need the following .htaccess swank.</p>]]></description>
			<content:encoded><![CDATA[<p>For those of us cheapskates on shared servers, our greatest weapon against the admonitions of YSlow is .htaccess, that innocuous text file that has the capacity to blow up your website if you mistreat it.</p>
<p>To defeat rules #3: <strong>Add an Expires or Cache-Control Header</strong>, #4 <strong>GZip Components</strong>, and #13 <strong>Configure ETags</strong>, we need the following .htaccess swank (thanks to <a href="http://www.reelseo.com">Matt Robertson</a> for noticing that the rules I had here were not compressing CSS or JS):</p>
<pre class="brush: plain;">
# MOD_DEFLATE COMPRESSION
SetOutputFilter DEFLATE

# 1-WEEK EXPIRES HEADER
ExpiresActive On
ExpiresDefault A0
ExpiresDefault A604800
Header append Cache-Control &quot;public&quot;

# PUT YOUR WP SUPER CACHE RULES HERE

# KILL THEM ETAGS
FileETag none

# YOUR WORDPRESS PRETTY PERMALINK RULES GO HERE
</pre>
<h2>GZip Compression</h2>
<p>In the above, I use mod_deflate compression because I'm hosted on MediaTemple, which doesn't offer gzip compression. The rules turn on mod_deflate for my CSS and Javascript because I'm also using <a href="http://wordpress.org/extend/plugins/wp-super-cache/">WP Super Cache</a>, which handles compression for everything else. In tandem with WP Super Cache, everything on my site is gzipped, and therefore YSlow gives me an A for rule #4.</p>
<p>If you don't have the mod_deflate module on your shared space, you likely have mod_gzip enabled, so use that:</p>
<pre class="brush: plain;">
# IF YOU CAN'T USE MOD_DEFLATE...
mod_gzip_on Yes
mod_gzip_dechunk Yes
mod_gzip_item_include file .(html?|txt|css|js|php|pl)$ mod_gzip_item_include handler ^cgi-script$
mod_gzip_item_include mime ^text/.* mod_gzip_item_include mime ^application/x-javascript.*
mod_gzip_item_exclude mime ^image/.* mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.*
</pre>
<p>This won't work on a variety of ancient browsers (pre-IE6, Opera 5, and Netscape, for example), but of course, who the hell cares.</p>
<h2>Expires Headers</h2>
<p>The idea here is that if you tell the browser the lifespan of your assets, the browser will keep them in its cache longer, which means your readers will be able to browse faster, from page to page, after they've downloaded your assets after the initial page load. Sounds a bit sketchy at first, but then I remembered that most people never CTRL+click Refresh or bother clearing their cache, so we can rely on their laziness.</p>
<p>My example above expires just about any kind of asset 1 week after it's downloaded, but keep in mind that you have <a href="http://www.askapache.com/htaccess/speed-up-your-site-with-caching-and-cache-control.html">a lot of options</a> when it comes to assigning these lifespans. It really depends on how often you change your content on your end.</p>
<h3>Assigning Dynamic Images Cache Control Headers in FLIR</h3>
<p>After much Interweb soul-searching, I decided that FLIR, the <a href="http://facelift.mawhorter.net/detailed-examples/">Facelift Image Replacement Method</a>, is the best image replacement method out there (for my purposes, at least). I used <a href="http://novemberborn.net/sifr3">sIFR 3</a> for a long time to render fancy fonts on my site, but every day when I looked at myself in the mirror, I was ashamed, among other things, for having to resort to Flash for such a trivial task. I intend to write an article about image replacement methods and the reason why I ultimately decided upon FLIR, so more on this later, but the point of my bringing this up is that the <a href="http://wordpress.org/extend/plugins/facelift-image-replacement/">Facelift Image Replacement WordPress Plugin</a> (which forks off the real FLIR) generates dynamic images for fonts, but doesn't assign them cache-control headers.</p>
<p>Hours of Googling landed me on <a href="http://forums.mawhorter.net/viewtopic.php?id=157">this page</a>. Here the author provides a solution to the problem. He writes:</p>
<blockquote><p>New user visits a brand new uncached image, it is generated.  They refresh the page, another request is probably made and a 304 not modified is returned.  You're right, this is unnecessary.</p>
<p>I think by adding a cache-control to the output_file function the images would then get cached by the browser without causing an extra call to verify that it hasn't been modified.  This should stop a lot of unnecessary trips to the server.</p></blockquote>
<p>The corresponding file in the Facelift plugin is inc-flir.php, located in the plugin's /facelift/ folder. Scroll down to line 395, and add the following:</p>
<pre class="brush: php;">
/* add this line */
header('Cache-Control: max-age=1209600, public, must-revalidate');

/* before the following lines */
header('Last-Modified: '.gmdate('D, d M Y H:i:s GMT', $ts));
header('ETag: &quot;'.md5($ts).'&quot;');
</pre>
<p>Adjust the expiration time to your liking. Now YSlow won't complain that the dynamic images generated by FLIR have no cache-control headers.</p>
<h2>ETags</h2>
<p>Last but not least (well yes, maybe least), the mystical "entity tags." These little things creep me out like Leeuwenhoek's animalcules or <em>FMA</em>'s homunculi. To paraphrase Yahoo, Etags are just doodads that servers and browsers use to check if the assets in the browser cache match up with original assets from the server. In the <a href="http://developer.yahoo.net/blog/archives/2007/07/high_performanc_11.html">performance rules</a>, Yahoo gripes about ETags because they don't quite do what they're supposed to do if your site pulls its assets from multiple servers. Of course, the vast majority of websites aren't doing this because the vast majority of website owners are cheapskates. Nevertheless, YSlow will give us a big fat F if we try to actually configure ETags "correctly." Since there's little space left in our brains to debate such nonsense, Yahoo instructs us to simply turn the little entities off. And frankly, my dear, I don't give a damn.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dquinn.net/htaccess-adding-etags-gzip-expires-headers/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>Nobody Wants to See Your Whitespace: Minify CSS and Javascript using Yahoo!&#8217;s UI Compressor</title>
		<link>http://www.dquinn.net/minify-css-javascript-yui-compressor/</link>
		<comments>http://www.dquinn.net/minify-css-javascript-yui-compressor/#comments</comments>
		<pubDate>Tue, 21 Apr 2009 12:41:07 +0000</pubDate>
		<dc:creator>Daniel Quinn</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[comments]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[minification]]></category>
		<category><![CDATA[minified]]></category>
		<category><![CDATA[minify]]></category>
		<category><![CDATA[obfuscated]]></category>
		<category><![CDATA[open source community]]></category>
		<category><![CDATA[yahoo!'s ui compressor]]></category>

		<guid isPermaLink="false">http://www.dquinn.net/?p=1477</guid>
		<description><![CDATA[Beating rule #10 is easy. We want to serve CSS and Javascript that has been minified (and obfuscated, if you please) to our readers, because that's less overhead for them to download. We also want to do it without screwing up our code, so I recommend using Yahoo!'s UI Compressor.]]></description>
			<content:encoded><![CDATA[<p>Beating rule #10 is easy. We want to serve CSS and Javascript that has been minified (and obfuscated, if you please) to our readers, because that's less overhead for them to download. We also want to do it without screwing up our code, so I recommend using <a href="http://developer.yahoo.com/yui/compressor/">Yahoo!'s UI Compressor</a>.</p>
<p>Now, would-be ultra-"l33t" programmers might enjoy using a command line, but I sure don't. It's a waste of the time Darwinian evolution spent on developing my eyeballs. Instead, swing on by to this cool guy's website, <a href="http://refresh-sf.com/yui/">http://refresh-sf.com/yui/</a>, where you can just copy paste your CSS or JS into a text field and get it minified/obfuscated without fiddling with Stone Age command prompts.</p>
<p>What happens when we have to make changes to our files after they've been minified/obfuscated? Since I don't use a fancy development environment to handle my files, I just minify/obfuscate the files that are up on the server and leave my local files alone. If I need to make a quick CSS change, I make them locally and just find/replace the same lines on the server. Janky? Yes. Not ideal? Sure. But it works.</p>
<p>* <em>Keep one thing in mind when you minify/obfuscate</em>: comments get stripped out entirely, and usually the software license or developer credit for freeware is contained in those comments. After some meditation on this matter, I decided that it's silly to keep the comments in after minification; that would be doing it half-assed and ultimately it defeats the purpose. As a compromise, we should have a page in our website that credits the creator of source code we borrow from the open source community. This provides even more visibility for our open source colleagues while allowing us to fully minify our files.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dquinn.net/minify-css-javascript-yui-compressor/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Make WP Super Cache Play Nice with &#8220;Preview Draft&#8221; and &#8220;Update Profile&#8221; in WordPress</title>
		<link>http://www.dquinn.net/wp-super-cache-preview-draft-update-profile-wordpress/</link>
		<comments>http://www.dquinn.net/wp-super-cache-preview-draft-update-profile-wordpress/#comments</comments>
		<pubDate>Wed, 15 Apr 2009 13:49:38 +0000</pubDate>
		<dc:creator>Daniel Quinn</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[digg effect]]></category>
		<category><![CDATA[donncha o caoimh]]></category>
		<category><![CDATA[draft post]]></category>
		<category><![CDATA[edit_user_profile_update]]></category>
		<category><![CDATA[rokkyuu magazine]]></category>
		<category><![CDATA[save preview]]></category>
		<category><![CDATA[simple_edit_form]]></category>
		<category><![CDATA[update profile]]></category>
		<category><![CDATA[wp cache]]></category>
		<category><![CDATA[wp super cache]]></category>
		<category><![CDATA[wp_cache_no_postid()]]></category>

		<guid isPermaLink="false">http://www.dquinn.net/?p=1409</guid>
		<description><![CDATA[This is all fine and good, and works beautifully.* One small problem with WP Super Cache, however, is that if users update the information in their profiles, that information won't appear on the site until WP Cache gets cleared. Also, the second time you Preview a saved draft, you'll be seeing your last saved draft because it got cached.]]></description>
			<content:encoded><![CDATA[<p><a href="http://wordpress.org/extend/plugins/wp-super-cache/">WP Super Cache</a> is one of those magical plugins that does all the work for us without our having to think. We like plugins like this. We all know WordPress is a fat, resource intensive hogbeast because it has to make so many queries to the database, so when we're hit with a spike in traffic (see: "<a href="http://en.wikipedia.org/wiki/The_Digg_Effect">The Digg Effect</a>"), chances are that the whole thing might implode.</p>
<p>How do we get around this? Well, WP Super Cache creates static html files of our posts so that repeat visitors in a short time span don't force WordPress to engage the database in order to serve posts and pages. Donncha O Caoimh, the creator, describes the plugin's functionality best:</p>
<blockquote><p>99% of your visitors will be served static html files. Those users who don't see the static files will still benefit because they will see regular WP-Cache cached files and your server won't be as busy as before. This plugin will help your server cope with a front page appearance on digg.com or other social networking site.</p></blockquote>
<p>This is all fine and good, and works beautifully.* One small problem with WP Super Cache, however, is that if users update the information in their profiles, that information won't appear on the site until WP Cache gets cleared. Also, the second time you Preview a saved draft, you'll be seeing your last saved draft because it got cached.</p>
<p>So the caching drafts is a problem, but why should we care about the cached profile? Well, I ran into this problem on <a href="http://www.rokkyuu.com">Rokkyuu Magazine</a>, because users can change the color scheme of the site by setting an option in their profile. So even though they may have updated their profile, when they returned to the site, they were seeing a cached version (and their previously chosen color scheme). Moreover, at Rokkyuu, what users enter in their profile while logged in to the Dashboard appears in a members directory on the public site, which also gets cached.</p>
<p>To get around this, and with <a href="http://wordpress.org/support/topic/261798?replies=6">a bit of Donncha's help</a>, I added the following to functions.php:</p>
<pre class="brush: php;">/********* WP-CACHE: CLEAR CACHE ON UPDATE PROFILE ***/
add_action('edit_user_profile_update',wp_cache_no_postid(0));</pre>
<p>What this does is hook the wp_cache_no_postid(0); function, which clears WP Cache, to the function that gets called when a user updates her profile.</p>
<h2>As for the Drafts...</h2>
<p>To fix the drafts, we do a similar thing. I couldn't figure out how to hook into the functions that get called when you click "Preview" post or "Save Draft," but I did find a hook that does the job.</p>
<pre class="brush: php;">/********* WP-CACHE: CLEAR CACHE FOR DRAFTS ***/
add_action('simple_edit_form', wp_cache_no_postid(0));</pre>
<p>Adding this to functions.php clears the cache whenever I click Preview post, thereby enabling me to see my latest edits with WP Super Cache enabled.</p>
<p><em>* Plugins that display up-to-the-minute information using PHP like WP-UserOnline, for example, won't necessarily "not work" as Donncha notes on the plugin page: they'll just be displaying information that's 3600 seconds old.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.dquinn.net/wp-super-cache-preview-draft-update-profile-wordpress/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>35 WordPress Plugins that Get the Job Done: Freelancing Favorites</title>
		<link>http://www.dquinn.net/35-wordpress-plugins-that-get-the-job-done-freelancing-favorites/</link>
		<comments>http://www.dquinn.net/35-wordpress-plugins-that-get-the-job-done-freelancing-favorites/#comments</comments>
		<pubDate>Tue, 14 Apr 2009 04:29:20 +0000</pubDate>
		<dc:creator>Daniel Quinn</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[.htaccess]]></category>
		<category><![CDATA[404s]]></category>
		<category><![CDATA[ad minister]]></category>
		<category><![CDATA[advanced category excluder]]></category>
		<category><![CDATA[advanced excerpt]]></category>
		<category><![CDATA[all in one seo pack]]></category>
		<category><![CDATA[codesnippet]]></category>
		<category><![CDATA[dashboard]]></category>
		<category><![CDATA[disable wordpress core update]]></category>
		<category><![CDATA[disable wordpress plugin update]]></category>
		<category><![CDATA[email users]]></category>
		<category><![CDATA[feed]]></category>
		<category><![CDATA[gd star rating]]></category>
		<category><![CDATA[google sitemap generator]]></category>
		<category><![CDATA[google webmaster tools]]></category>
		<category><![CDATA[lifestream]]></category>
		<category><![CDATA[localhost]]></category>
		<category><![CDATA[member access]]></category>
		<category><![CDATA[mod_rewrite]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[new tag cloud]]></category>
		<category><![CDATA[nextgen gallery]]></category>
		<category><![CDATA[page excerpt]]></category>
		<category><![CDATA[popular posts plugin]]></category>
		<category><![CDATA[post plugin library]]></category>
		<category><![CDATA[ps auto sitemap]]></category>
		<category><![CDATA[random posts plugin]]></category>
		<category><![CDATA[recent posts plugin]]></category>
		<category><![CDATA[redirection plugin]]></category>
		<category><![CDATA[register plus]]></category>
		<category><![CDATA[rokkyuu magazine]]></category>
		<category><![CDATA[search and replace]]></category>
		<category><![CDATA[seo]]></category>
		<category><![CDATA[similar posts plugin]]></category>
		<category><![CDATA[sitemap generator]]></category>
		<category><![CDATA[social media]]></category>
		<category><![CDATA[spiders]]></category>
		<category><![CDATA[subscribe to comments]]></category>
		<category><![CDATA[subscribe2]]></category>
		<category><![CDATA[the_excerpt()]]></category>
		<category><![CDATA[user photo]]></category>
		<category><![CDATA[viper's video quicktags]]></category>
		<category><![CDATA[visual editor]]></category>
		<category><![CDATA[wordpress 2.6]]></category>
		<category><![CDATA[wordpress plugins]]></category>
		<category><![CDATA[wp-ban]]></category>
		<category><![CDATA[wp-commentnavi]]></category>
		<category><![CDATA[wp-db-backup]]></category>
		<category><![CDATA[wp-pagenavi]]></category>
		<category><![CDATA[wp-useronline]]></category>
		<category><![CDATA[xml]]></category>
		<category><![CDATA[youtube]]></category>

		<guid isPermaLink="false">http://www.dquinn.net/?p=1383</guid>
		<description><![CDATA[Here's quick list of my favorite WordPress plugins that I've come back to time and time again on client projects. Each of these plugins have withstood the test of time (when it comes to new versions of WordPress), have diligent support in the community, and remain stable to date. I'll be returning to this post from time to time to provide hacks wherever mentioned.]]></description>
			<content:encoded><![CDATA[<p>Here's quick list of my favorite WordPress plugins that I've come back to time and time again on client projects. Each of these plugins have a) withstood the test of time (when it comes to new versions of WordPress), b) have excellent support in the community, and c) remain stable to date. I'll be returning to this post from time to time to provide hacks wherever mentioned.</p>
<ol>
<li><a href="http://wordpress.org/extend/plugins/ad-minister/">Ad Minister</a>. The best tool for serving banner ads I've come across.</li>
<li><a href="http://wordpress.org/extend/plugins/advanced-excerpt/">The Advanced Excerpt</a>. WordPress' built-in excerpt function, the_excerpt() leaves a lot to be desired because it strips out HTML by default.</li>
<li><a href="http://wordpress.org/extend/plugins/advanced-category-excluder/">Advanced Category Excluder</a>. Sometimes I just don't want to go through all the trouble of making sure a particular category doesn't show up in search results or the feed. This little plugin is great because it does all the work for you.</li>
<li><a href="http://wordpress.org/extend/plugins/all-in-one-seo-pack/">All in One SEO Pack.</a> Can't live without this one. SEO-friendly page titles + automatically using post and page excerpts as meta descriptions + automatically using tags as meta keywords = better visibility on Google. It's one of the reasons why my website is on the first page of results in Google if you search for "Boston freelance web designer."</li>
<li><a href="http://wordpress.org/extend/plugins/disable-wordpress-core-update/">Disable WordPress Core Update</a>. Now now, before you chastise me: I recommend disabling WordPress' Core Update nag only if you're diligent about updating yourself. As I <a href="http://www.dquinn.net/wordpress365/">said before</a>, one of the difficulties with WordPress is that if your plugins get out of sync with your version of WordPress, this means trouble for the stability of your installation. I check <a href="http://www.wordpress.org">WordPress.org</a> regularly, and prefer to do an update and compatibility check for my plugins all at once, so the nag only ends up annoying me.</li>
<li><a href="http://wordpress.org/extend/plugins/disable-wordpress-plugin-updates/">Disable WordPress Plugin Update</a>. Same here. I often have to modify plugins to suit my needs, so this one's an eyesore.</li>
<li><a href="http://wordpress.org/extend/plugins/email-users/">Email Users</a>. A great tool to send out a quick message to all registered users.</li>
<li><a href="http://wp.gdragon.info/plugins/gd-star-rating/">GD Star Rating</a>. The slickest of the "star ratings" plugins I've seen, since it comes with sweet icon themes and scores via Ajax.</li>
<li><a href="http://www.arnebrachhold.de/projects/wordpress-plugins/google-xml-sitemaps-generator/">Google Sitemap Generator.</a> A must-have for SEO purposes. The plugin generates a fully customizable XML sitemap of all your content so spiders can crawl you more easily.</li>
<li><a href="http://wordpress.org/extend/plugins/lifestream/">Lifestream</a>. A lovely way to vomit all your social media activity in one place.</li>
<li><a href="http://wordpress.org/extend/plugins/new-tag-cloud/">New Tag Cloud</a>. A classic. This plugin gives <em>just</em> a bit more granular control over the tag cloud than the default one allows.</li>
<li><span style="text-decoration: line-through;"><a href="http://alexrabe.boelinger.com/wordpress-plugins/nextgen-gallery/">NextGen Gallery</a>. I personally find the Dashboard for NextGen Gallery unintuitive, but as far as galleries hosted on-site go, it's the best option available. I've hacked NextGen to suit my purposes at <a href="http://www.rokkyuu.com/fashion/galleries">Rokkyuu Magazine</a>, but out-of-box the plugin combines many of the features that I find lacking in its competition.</span> <strong>*updated 8/22/09* As of 2.7, just use WordPress' built in gallery shortcodes. You can upload a whole set of images and "Insert as Gallery," then with a bit of filtering, remove the default CSS for the gallery and use Shadowbox to display the full image as a lightbox. This way thumbnails get automatically created, and if you dump galleries into their own category of posts, you can handle a gallery as you would any other post.</strong></li>
<li><a href="http://blog.ftwr.co.uk/wordpress/page-excerpt/">Page Excerpt</a>. Why this was removed from WordPress still baffles me (<a href="http://wordpress.org/extend/ideas/topic.php?id=247">among others</a>)—in conjunction with All in One SEO Pack, Page Excerpt allows you to provide better meta descriptions for your pages, as well as prettier excerpts in search results and archives.</li>
<li><a href="http://www.web-strategy.jp/wp_plugin/ps_auto_sitemap/">PS Auto Sitemap</a>. A fancy, automagically generated sitemap with fancy icons.</li>
<li><a href="http://wordpress.org/extend/plugins/redirection/">Redirection</a>. This one's indispensable. I'm no good at writing rules for mod_rewrite in my .htaccess, so this plugin is a lifesaver. If you use <a href="http://www.google.com/webmasters/tools/">Google's Webmaster Tools</a> in conjunction with this plugin, you can have a pretty cleanly running site with no loose ends, as far as 404s and errors in your sitemap are concerned. Would be perfect if it weren't for the fact that its log files, which can't be turned off, eventually get enormous and bloat your MySQL database.</li>
<li><a href="http://subscribe2.wordpress.com/">Subscribe2</a>. The Dashboard is very clunky, but as a site-wide subscription manager, Subscribe2 does the job.</li>
<li><span style="text-decoration: line-through;"><a href="http://wordpress.org/extend/plugins/register-plus/">Register Plus</a>. After extensive experimentation with the plugins out there that extend the functionality of the user profile in WordPress, Register Plus appears to be the key to making it work without resorting to writing your own plugins. I'll be writing an article about extending the user profile (a la <a href="http://www.rokkyuu.com/subscribers/?subscriber=alkah3st">Rokkyuu Magazine</a>) to include custom fields arranged in a preferred order and user-selected color themes. Great when combined with the <a href="http://wordpress.org/extend/plugins/user-photo/">User Photo</a> plugin. (Albeit, other than for this purpose, Register Plus is somewhat useless; half of its functionality expired with WordPress 2.6.).</span><strong>*updated 8/22/09* </strong><strong>There are a few plugins out there that may make this whole setup even more interesting, such as logging in and editing your profile from the front end. <span style="text-decoration: line-through;">More to come</span>. Read my new series <a href="http://www.dquinn.net/extending-user-profiles-wordpress/">Extending User Profiles in WordPress</a> for more on this. (added *8/29/2009*)</strong></li>
<li><a href="http://wordpress.org/extend/plugins/search-and-replace/">Search and Replace.</a> Useful if you need to migrate your WordPress installation from a local environment, to a testing server, and then to its final live host. Simply search and replace http://localhost/a-temporary-path/ with the final domain path and you're done.</li>
<li><a href="http://wordpress.org/extend/plugins/subscribe-to-comments/">Subscribe to Comments</a>. A really great way to enable users to follow your comment thread without subscribing to its feed.</li>
<li><span style="text-decoration: line-through;"><a href="http://wordpress.org/extend/plugins/codesnippet-20/">Codesnippet</a>. An easier method to displaying markup or code in posts, although you'll need to hack the plugin to make it standards-compliant. Normally the plugin generates a &lt;pre&gt; with two &lt;div&gt;'s inside of that, which in turn get squashed inside of &lt;p&gt; tags; I replaced these &lt;div&gt;s with &lt;spans&gt; and then styled the &lt;span&gt;s to be <em>display: block</em>. Of course, then you still have to deal with the fact that WordPress will invariably mangle your inline code if you switch to the Visual Editor.</span> <strong>*updated 8/22/09* </strong><strong>An even better option is <a href="http://wordpress.org/extend/plugins/syntaxhighlighter/">Syntax Highlighter Evolved</a> by ViperBond.</strong></li>
<li><a href="http://wordpress.org/extend/plugins/sitemap-generator/">Sitemap Generator.</a> If you're looking for a plugin that generates a simple, unordered list of all your posts, pages, etc in a hierarchical fashion, this is it. All you do is create a page template for it and plop it in.</li>
<li><a href="http://wordpress.org/extend/plugins/member-access/">Member Access</a>. The best way to make your WordPress members-only.</li>
<li><a href="http://wordpress.org/extend/plugins/user-photo/">User Photo</a>. A wonderful enhancement for the user profile. If you don't want to approve each user when he/she changes her photo, though, you'll need to cripple the plugin to remove this functionality, and then also rip out the chunk of code that sends you an email (even after you've disabled the moderation feature). More on this later.</li>
<li><a href="http://wordpress.org/extend/plugins/vipers-video-quicktags/">Viper's Video Quickags</a>. Simply the best way to insert YouTube videos.</li>
<li><a href="http://wordpress.org/extend/plugins/wp-ban/">WP-Ban</a>. Easy as pie. You can ban by IP, referrer, or host name, and display a custom page to blocked users.</li>
<li><a href="http://wordpress.org/extend/plugins/wp-commentnavi/">WP-Commentnavi</a>. Lester "Gamerz" Chan is one of the great plugin masters. I've had to alter his plugin's markup a bit to suit my purposes (which I'll be sure to share), but otherwise his plugins are almost prescient when it comes to much-needed WordPress functionality.</li>
<li><a href="http://wordpress.org/extend/plugins/wp-db-backup/">WP-DB-Backup</a>. Nothing beats having your WordPress database delivered to you by email once a week.</li>
<li><a href="http://wordpress.org/extend/plugins/wp-pagenavi/">WP-Pagenavi</a>. Another of Lester's, which I use in almost every project.</li>
<li><a href="http://wordpress.org/extend/plugins/wp-polls/">WP-Polls</a>. A nice, ajax-powered polling system (also Lester's). I'll discuss the related tw-sack.js problem later, but otherwise a solid piece of code.</li>
<li><a href="http://wordpress.org/extend/plugins/wp-useronline/">WP-UserOnline</a>. Displays a list of spiders and users (anonymous as well as logged in) who are currently browsing your site (as well as what page[s] they're viewing).</li>
<li><a href="http://wordpress.org/extend/plugins/post-plugin-library/">Posts Plugin Library</a>. And finally, one of the sweetest plugins out there: bypass dealing with multiple loops in a template by making single-line calls to the Posts Plugin Library, which grabs exactly the posts you need. And the great news is, there's a whole suite of options:
<ul>
<li><a href="http://rmarsh.com/plugins/similar-posts/">Similar Posts</a></li>
<li><a href="http://rmarsh.com/plugins/random-posts/">Random Posts Plugin</a></li>
<li><a href="http://rmarsh.com/plugins/popular-posts-plugin/">Popular Posts Plugin</a></li>
<li><a href="http://rmarsh.com/plugins/recent-comments/">Recent Comments Plugin</a></li>
</ul>
</li>
</ol>
<p>That's all, folks! Should I come across some other sweet plugins, or if you recommend them, I'll add them here. Stay tuned.</p>
<h2>Addendum</h2>
<p>So here are a number of plugins I forgot:</p>
<ol>
<li><strong><a href="http://wordpress.org/extend/plugins/lastfm-rps/">Last.fm RPS</a>. *added 8/22/09* </strong>After trying out numerous Last.fm plugins, this is without a doubt the best out there. Allows you to display information from your latest tracks/albums on Last.fm. Used in conjunction with <a href="http://www.last.fm/download">Last.fm's Scrobbler for iTunes/Windows Media Player</a>.</li>
<li><strong><a href="http://sourceforge.net/projects/role-manager/">Role Manager</a>. </strong><strong>*added 8/22/09*</strong><strong> </strong>Sometimes you need more granular control over what users can do in the back-end of WordPress, and that's where Role Manager comes in. What's great is that when used in conjunction with Flutter, you can restrict access to Custom Write Panels you create on a user level basis.</li>
<li><strong><a href="http://urbangiraffe.com/plugins/search-unleashed/">Search Unleashed</a>. </strong><strong>*added 8/22/09*</strong><strong> </strong>Use this plugin to beef up the relevancy of the WordPress search function. Since <a href="http://www.semiologic.com/software/search-reloaded/">Search Reloaded</a> went commercial, this is the only plugin left that will allow you to search by relevancy reliably.</li>
<li><strong><a href="http://yoast.com/wordpress-search/">Search Excerpt</a>. </strong><strong>*added 8/22/09*</strong><strong> </strong>To further beef up WordPress' search function, why not use Yoast's quick Search Excerpt plugin to return excerpts on the search results page that highlight only the relevant portion of the post that the user requested.</li>
<li><strong><a href="http://www.nateomedia.com/wares/downloads/wordpress/wp-snap/">WP Snap</a>.</strong><strong>*added 8/22/09*</strong><strong> </strong>I use this plugin when I need to display posts in an alphabetical index. Great for glossaries, indexes, and encyclopedias. Also check out my post about <a href="http://www.dquinn.net/sort-posts-by-last-name-using-nate-olsens-wp-snap-plugin-for-wordpress/">sorting by last name</a> when using this plugin.</li>
<li><strong><a href="http://wordpress.org/extend/plugins/picasa-images-express/">Picasa Images Express</a>. </strong><strong>*added 8/22/09*</strong><strong> </strong>The alternative to storing all your photo albums on your web server is hosting them off-site, at Picasa or Flickr. Most people prefer Flickr because of its enormous community and sweet photo management features, but I use Picasa because it allows me to create unlimited albums of my photos and the feed for each album is unlimited, as opposed to limited to 200 photos (for free). So if Picasa is the way to go for you, this plugin will integrate with TinyMCE and provide its own upload management library like the Media Library. Then with one click, you can dump linked thumbnails to all your Picasa photos (an album at a time, or photo at a time, whichever you prefer) into your posts.</li>
<li><strong><a href="http://wordpress.org/extend/plugins/netflix-x2/installation/">Netflix</a></strong> plugin for WordPress. <strong>*added 8/22/09* </strong>While I'm using <a href="http://www.albertbanks.com/2006/01/04/wordpress-netflix-plugin-2/">the original Netflix plugin</a> by Albert Banks, Eric VanBergen made a reimplementation of the plugin with new features. The plugin can display your various Netflix feeds, such as images of the movies in your queue (see my footer throughout the site).</li>
<li><strong><a href="http://wordpress.org/extend/plugins/facelift-image-replacement/">Facelift Image Replacement</a></strong> plugin, or FLIR, (<strong>*added 8/22/09*</strong>) is an image-replacement technique I use on my site to display headings in a specific font that end-users won't have on their computer. This is an alternative to the popular Flash-based image-replacement technique, sIFR. It's a bit complicated to use, in that your stylesheet needs to match up with the settings in FLIR, but it works great (and now actually functions on a local installation too!).</li>
<li><strong><a href="http://wordpress.org/extend/plugins/excerpt-editor/">Excerpt Editor</a>.</strong><strong>*added 8/22/09*</strong><strong> </strong>A very simple tool that will call up the excerpts of all posts and pages on your site, allowing you to check whether or not you made excerpts for these posts. This is especially useful if you use your excerpt as a meta description through the <a href="http://wordpress.org/extend/plugins/all-in-one-seo-pack/">All in One SEO Pack</a> plugin.</li>
<li><a href="http://wordpress.org/extend/plugins/wp-super-cache/">WP Super Cache</a>. Can't believe I left this one off the list! WP Super Cache turns dynamic WordPress pages into static html files, without using PHP resources to serve the files. That way WordPress (hopefully) won't implode when you're squashed by the "Digg Effect." Setup can be tricky when applying the .htaccess rules, but the plugin is otherwise very friendly.</li>
<li><strong><a href="http://wordpress.org/extend/plugins/wp-cms-post-control/">WP CMS Post Control</a>. </strong><strong>*added 8/22/09*</strong><strong> </strong>If you need to hide certain portions of the Dashboard for whatever reason, this is the easiest way to do it, short of attaching your own stylesheet and using display: none.</li>
<li><strong><a href="http://flutter.freshout.us/">Flutter</a>. </strong><strong>*added 8/22/09*</strong><strong> </strong>There's a lot to be said about this amazing plugin, which is slowly being transformed into "Breeze" by Freshout. While it requires a lot of hacks to use in production, I still use a modified version of it in most of my client projects. Flutter "styles" the GUI of custom fields, so that if you're making a WP site for clients, they won't have to deal with WordPress's custom field variable/value pairs. We definitely need to keep an eye on new developments on Flutter's end, as it has the potential to transform WP into a real CMS.</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.dquinn.net/35-wordpress-plugins-that-get-the-job-done-freelancing-favorites/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Geocoordinates for All 50 States and Japanese Prefectures</title>
		<link>http://www.dquinn.net/geocoordinates-for-all-50-states-and-japanese-prefectures/</link>
		<comments>http://www.dquinn.net/geocoordinates-for-all-50-states-and-japanese-prefectures/#comments</comments>
		<pubDate>Mon, 13 Apr 2009 02:30:12 +0000</pubDate>
		<dc:creator>Daniel Quinn</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[all japanese prefectures]]></category>
		<category><![CDATA[geocoordinates]]></category>
		<category><![CDATA[google maps]]></category>
		<category><![CDATA[japanese prefecture]]></category>

		<guid isPermaLink="false">http://www.dquinn.net/?p=1375</guid>
		<description><![CDATA[While I'm not going to show you how to build the Google Maps application in WordPress just yet, I <em>am</em> going to provide you with the fruits of my hard-earned labor: a complete list of all the geocoordinates for the 50 states <em>and</em> each Japanese prefecture.]]></description>
			<content:encoded><![CDATA[<p>Building a Google Maps application? I had to do just the same thing when I put together <a href="http://www.rokkyuu.com">Rokkyuu Magazine</a>'s <a href="http://www.rokkyuu.com/reviews/">reviews section</a>, which enabled subscribers to locate articles geographically by browsing through a single Google Map.</p>
<p>While I'm not going to show you how to build the Google Maps application in WordPress just yet, I <em>am</em> going to provide you with the fruits of my hard-earned labor: a complete list of all the geocoordinates for the 50 states <em>and</em> each Japanese prefecture.</p>
<p>My girlfriend and I sat for a couple hours and determine the best zoom level for each state/prefecture (that's the number in curly braces) after determining the optimal geocoordinates using <a href="http://www.livephysics.com/ptools/location-to-geo-coordinates.php">this wonderful location to geocoordinate tool</a> from <a href="http://www.livephysics.com/">LivePhysics.com</a>.</p>
<h3>Geocoordinates for the 50 United States</h3>
<pre class="brush: plain;">Alabama (AL) : 32.614471, -86.680740 {8}
Alaska (AK) : 62.890301, -149.054077 {4}
Arizona (AZ) : 34.168091, -111.930344 {5}
Arkansas (AR) : 34.751888, -92.131348 {7}
California (CA) : 37.271832, -199.270203 {5}
Colorado (CO) : 38.997841, -105.550911 {6}
Connecticut (CT) : 41.515572, -72.757477 {8}
Delaware (DE) : 39.145199, -75.418610 {7}
Florida (FL) : 27.9756639, -81.541183 {6}
Georgia (GA) : 32.678131, -83.222931 {7}
Hawaii (HI) : 19.589640, -155.434036 {6}
Idaho (ID) : 45.494419, -114.1432219 {5}
Illinois (IL) : 39.739281, -89.504128 {6}
Indiana (IN) : 39.766201, -86.441254 {6}
Iowa (IA) : 41.938221, -93.389900 {6}
Kansas (KS) : 38.49058, -98.320213 {6}
Kentucky (KY) : 37.822399, -85.691101 {7}
Louisiana (LA) : 30.972260, -91.521797 {7}
Maine (ME) : 45.262379, -69.008301 {6}
Maryland (MD) : 38.823399, -75.923759 {8}
Massachusetts (MA) : 42.163891. -71.717941 {8}
Michigan (MI) : 43.742691, -84.621620 {6}
Minnesota (MN) : 46.441929, -93.365471 {6}
Mississippi (MS) : 32.585159, -89.876381
Missouri (MO) : 38.304611, -92.436653 {6}
Montana (MT) : 46.679440, -110.044472 {5}
Nebraska (NE) : 41.500839, -99.680771 {6}
Nevada (NV) : 38.502460, -117.022720 {6}
New Hampshire (NH) : 44.001301, -71.632828 {7}
New Jersey (NJ) : 40.142780, -74.726723 {7}
New Mexico (NM) : 34.166161, -106.026123 {6}
New York (NY) : 40.714550, -74.007124 {8}
North Carolina (NC) : 35.219410, -80.018333 {7}
North Dakota (ND) : 47.467731, -100.301712 {6}
Ohio (OH) : 40.190269, -82.669403 {6}
Oklahoma (OK) : 35.308960, -98.716942 {6}
Oregon (OR) : 44.114552, -120.514908 {5}
Pennsylvania (PA) : 40.994640, -77.604507 {7}
Rhode Island (RI) : 41.661171, -71.555771 {9}
South Carolina (SC) : 33.624981, -80.947441 {7}
South Dakota (SD) : 44.212391, -100.247101 {6}
Tennessee (TN) : 35.830620, -85.978554 {7}
Texas (TX) : 31.168989, -100.076790 {5}
Utah (UT) : 39.499611, -111.547050 {6}
Vermont (VT) : 43.871769, -72.451218 {7}
Virginia (VA) : 38.003349, -79.771446 {7}
Washington (WA) : 38.890370, -77.031959 {6}
Washington, DC (DC) : 38.890370, -77.031959 {11}
West Virginia (WV) : 38.920101, -80.181808 {7}
Wisconsin (WI) : 44.727242, -90.101562 {6}
Wyoming (WY) : 43.000320, -107.554626 {6}</pre>
<h3>Geocoordinates for All Prefectures of Japan</h3>
<pre class="brush: plain; highlight: [1,10,27,42];">- North -
Hokkaido : 43.460388, 142.791718 {7}
Aomori : 40.822118, 141.273544 {8}
Iwate : 39.598911, 141.362823 {9}
Akita : 39.692009, 140.344177 {9}
Miyagi : 38.387989, 140.975266 {9}
Yamagata : 38.433571, 140.092804 {9}
Fukushima : 37.383968, 140.104156 {9}

- Central -
Ibaraki : 36.342159, 140.269928 {9}
Tochigi : 36.677341, 139.809494 {9}
Gunma : 36.521950, 139.033539 {9}
Chiba : 35.501732, 140.311783 {9}
Saitama : 36.018481, 139.305725 {9}
Tokyo : 35.699791, 139.430954 {10}
Kanagawa : 35.404469, 139.357513 {9}
Niigata : 37.645111, 138.767456 {9}
Toyama : 36.627071, 137.265945 {9}
Ishikawa : 36.800350, 136.802399 {9}
Nagano : 36.11410, 138.031982 {9}
Gifu : 35.799351, 136.964691 {9}
Fukui : 35.819550, 136.140884 {9}
Yamanashi : 35.570011, 138.657257 {9}
Shizuoka : 35.120281, 138.311462 {9}

- West -
Aichi : 35.001369, 137.254517 {9}
Shiga : 35.247169, 136.109406 {9}
Kyoto : 35.242569, 135.454666 {9}
Hyogo : 35.149441, 134.860657 {9}
Mie : 34.490238, 136.390717 {10}
Nara : 34.657829, 135.892136 {11}
Osaka : 34.661579, 135.419846 {9}
Wakayama : 33.908810, 135.533966 {9}
Tottori : 35.336170, 133.825729 {9}
Shimane : 34.953468, 132.497421 {9}
Okayama : 34.891079, 133.839996 {9}
Hiroshima : 34.649590, 132.746521 {9}
Yamaguchi : 34.256390, 131.555557 {9}

- South -
Kagawa : 34.206249, 133.998749 {9}
Tokushima : 33.892609, 134.205490 {9}
Ehime : 33.520290, 132.852783 {9}
Kochi : 33.302269, 134.149185 {9}
Fukuoka : 33.484959, 130.615128 {9}
Saga : 33.253571, 130.150696 {9}
Nagasaki : 32.984489, 129.967224 {9}
Oita : 33.214211, 131.455093 {9}
Kumamoto : 32.645000, 130.844879 {9}
Miyazaki : 32.099789, 131.294632 {9}
Kagoshima : 31.590900, 130.656036 {9}
Okinawa : 26.474991, 127.982109 {9}</pre>
<p>Okay, so this one wasn't exactly a <em>WordPress</em> tutorial, but for anyone working with Google Maps and WordPress, you'll thank me later.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dquinn.net/geocoordinates-for-all-50-states-and-japanese-prefectures/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
