Cloud Four Blog

Archive for the ‘Blogs and Social Media’ Category

Who Owns Your Retweet?

Tuesday, December 8th, 2009

When you retweet something, do you expect someone else to be able to delete it?

Previously, if you retweeted something, your retweet was your own. Only you had the ability to delete it.

But with Twitter’s new retweet feature, your retweet is tied to the original author’s tweet. And if the original author deletes the tweet, your retweet is deleted from your timeline.

I’m not sure what the proper way to handle this is.

On the one hand, if the original author shared something they wished to retract, it would be nice to honor that.

On the other hand, the tweet didn’t happen in a vacuum. More importantly, the act of retweeting should be tied to the timeline of the person who retweeted it. Someone else shouldn’t be able to scrub that history.

What do you think?

Twitter’s New Retweet is Broken and How to Fix it

Tuesday, December 1st, 2009

When Twitter announced their new retweet feature, I read Twitter founder Ev William’s reasons for the design of the new feature with interest. I understood his points. I didn’t agree with the solution, but was comforted by his closing note that “there’s nothing stopping you from simply quoting another tweet if that’s what you want to do. Also, old-school retweets are still allowed, as well.”

My plan was simply to ignore the new retweet feature until they fixed its shortcomings. However, Loren Brichter released a new version of my favorite Twitter client for the iPhone, Tweetie, that incorporates the new retweet feature and “deprecates” the old way of retweeting.

After spending some time with the new version of Tweetie, it became clear that the new retweet feature and all of its warts are here to stay. Instead of ignoring it, it was more important to document the ways it is broken and try to get Twitter and the developers of Twitter clients to fix it.

What Ev Got Wrong

Ev’s post does an excellent job of outlining the perceived shortcomings of the old way of retweeting. I’m grateful for his explanation. Not only is it helpful to understand the design decisions they made, but it also helps me understand where Ev missed important uses of retweets.

Attribution Confusion vs. Credibility and Reputation

One of the main things that Twitter was trying to solve with the new retweet feature is attribution confusion. “Most notably, the text of the tweet is not written by the person whose picture you’re seeing, nor the username that’s at the beginning.”

The solution to this in the new retweet feature is to show the name and picture of the original person who wrote the tweet and annotate below the tweet the name of the person you are following who retweeted the post.

The problem with this solution to attribution confusion is that it eliminates one of the main values of retweets: the credibility and reputation of the person who is retweeting.

By removing the picture of the person who retweeted and making the name much smaller, it becomes much harder to tell quickly which of the people you are following retweeted the post.

The person who retweeted a link to an article matters a lot. We place different value on the people we follow and the information they share.

In the example above, it is more important to me to know that Dave Winer was the source of the retweet than it is to know that jenny8lee—someone I don’t know—wrote the original tweet.

Tim O’Reilly is someone who I find to have very intelligent takes on technology. When I see his picture in my twitter stream, I stop scanning and pay closer attention. His credibility and reputation is what makes me pay attention to what he tweets or retweets.

This is something that the independent Twitter clients have done a better job of addressing than Twitter itself. Both Tweetie and Tweetdeck have included both the picture of the person who originated the tweet as well as the person who retweeted.

I much prefer the way Tweetie handles the retweet in the screenshot above to the way Twitter handles it. I see both Dave Winer’s name and picture. My only complaint is that the picture of the person retweeting is often too small to recognize quickly.

Redundancy vs. Dipping in the Stream

Another point that Ev makes is that “if five people you follow retweet the same thing, you get five copies, which can be useful but is a lot of noise.”

Ev is right that if you are reading every single tweet having redundant retweets can be a bit of noise. That said, it isn’t something that has ever bothered me.

The multiple retweets has however been something that has alerted me to important information. When you think of Twitter as a stream that you dip your toes into when you have time, important information can be missed if it only shows up in your stream one time. However, the more people retweet it, the more likely you are to encounter it whenever you decide to dip your toes in your Twitter stream.

I have to look no further than this past weekend to see the importance of this. On Saturday, the City of Portland announced that e-coli had been found in some of its water supply.

I happened to be out with the family in one of the affected areas. While waiting in line, I checked Twitter. By the time I checked, it had been several hours since the announcement. Yet, I saw one of the many retweets about the outbreak and was able to advise the people around me what water to avoid.

Let me repeat, the only reason I learned about the e-coli outbreak was because I received multiple retweets.

Another reason multiple retweets are valuable is because of reputation and credibility. A retweet from someone I follow whose opinion I value more highly than others is more likely to catch my eye.

There is value in multiple retweets. I’d love to have this be an option to see all retweets or only the first one.

Problems with the Current Implementations

Aside from the two viewpoints about credibility and the value of multiple retweets, there are things lacking in the current retweet implementations. As my friend Peter Whooly pointed out, it’s hard to tell if these are problems with the Twitter clients or Twitter’s API.

No Way to See Who Has Retweeted Your Tweets

In Tweetie, when you go under your profile and look at the retweets, there is no way to tell who retweeted your tweet. This is possible on Twitter’s web interface.

No Notification of Retweets

One of the nice aspects of the old style of retweeting was that retweets also contained the @reply syntax. This meant that you could not only could see the retweets easily, but if your Twitter client offered notifications for replies, you would be prompted when someone retweeted you.

Knowing when someone retweets you is important so that you can participate in the conversation.

Retweets Don’t Show Up in Lists

This again is an issue of credibility and reputation. Say you create a list of people whose opinions and thoughts you highly value. It is a very select list and you read every tweet these people write. When you look at that list, you will miss any retweets using the new feature.

Being able to see retweets in Twitter lists is a big deal.

Ability to Annotate Retweets

This is already on the Twitter team’s radar. Ev says they have some ideas on how they might implement it. This isn’t a show stopper for me, but it is for a lot of other people.

Vocal Minority or Silent Majority?

One of the things that got me worked up about this was seeing Loren Brichter’s take on the new retweet feature. He said, “vocal minority have problem with change – no doubt once they try it they’ll realize how awesome it is.”

Because Loren is the developer of Tweetie, the iPhone client I prefer to use, his opinion about the retweet feature matters. The fact that he thinks that:

  1. it is only a vocal minority that has problems with it and
  2. that we simply have a problem with change

frustrated me. From the conversations I’ve had with other users, that isn’t an accurate description.

Many of the same people who have problems with the new retweet feature embraced the new lists feature. Discounting opinions by saying people simply have a problem with change is a way of marginalizing contrary opinions without having to address them. There are legitimate issues with the retweet feature as I’ve outlined above.

And I’m not convinced that it is a minority of people who have problems with the new retweet feature. So far, I haven’t seen a single person who thinks the new retweet feature is complete.

Unlike lists which a majority of people raved about and immediately started using, the new retweet feature is something that most people seem to be at best accepting with hopes that Twitter will address its issues and at worst, so strongly opposed to the new feature that they are taking actions like refusing to upgrade Tweetie to avoid it.

How to Fix Retweets

I don’t disagree with most of what Ev said were the reasons for the new retweet feature. I also think formalizing retweets can lead to some really interesting information and features.

That said, the new feature has significant shortcomings that need to be addressed before we should consider the old way of retweeting deprecated.

I’m thankful that Loren implemented the new feature in Tweetie. It made me recognize that the feature wasn’t going away and was already impacting me even if I choose to use the old style retweet because others may use the new feature and I won’t see their retweets.

Therefore, the most important thing we can do to fix the situation is provide feedback to Twitter and Twitter client developers.

My hope is that if enough people provide feedback to Twitter (they are asking for feedback on the feature) that we can have a new retweet feature that we embrace as enthusiastically as we did Twitter lists.

Freedom Time: Google Voice Letter to the FCC, iPhone App Store & Mobile Gatekeepers

Monday, September 21st, 2009

Friday is the day to release news you want people to forget. No surprise then that Friday was when Google released the unredacted version of its letter to the FCC about Apple’s rejection of the Google Voice application.

In case you missed it, the FCC sent letters to Apple, Google, and AT&T asking them about Apple’s rejection of the Google Voice for iPhone application and what role each company played.

Apple and AT&T released the full content of their responses to the FCC. Google asked for portions of its response to be redacted. However, a Freedom of Information Act request prompted Google to divulge the full content of their response.

And yet despite this latest revelation, the he said, she said nature of the follow ups, and word that Google may even have a screenshot proving that Apple is lying, Google Voice is nowhere near the most important App Store rejection.

That distinction belongs to Freedom Time.

Why Freedom Time Matters More than Google Voice

Freedom Application ScreenshotLike many iPhone applications, Freedom Time was a frivolous application. The application displayed a cartoon character of George Bush with arms like a Mickey Mouse watch. But instead of telling time, the application counted down the days until Inauguration Day.

Freedom Time wasn’t one of the more high-profile iPhone App Store rejections. Unlike Google Voice, people barely noticed when the application was rejected.

What is important is the reason why Freedom Time was rejected. Apple’s response to the developer was:

Upon review of your application, Freedom Time cannot be posted to the App Store because it contains content that does not comply with Community Standards. Usage of such materials, as outlined in the iPhone SDK Agreement section 3.3.12, is prohibited:

“Applications must not contain any obscene, pornographic, offensive or defamatory content or materials of any kind (text, graphics, images, photographs, etc.), or other content or materials that in Apple’s reasonable judgement may be found objectionable by iPhone or iPod touch users.”

Defaming, demeaning, or attacking political figures is not considered appropriate content for the App Store.

Can you imagine political discourse of any significance that doesn’t include demeaning or attacking political figures? Like it or not, that’s part of the exchange of ideas that form a democracy.

This policy essentially bans any editorial cartoons—cartoons that have been part of America’s history since its inception.

The idea that political discourse might be rejected from the App Store as a matter of policy surely must be a mistake, right?

Think Different? What’s the Point?

Unfortunately, it isn’t a mistake. The developer of Freedom Time emailed Steve Jobs, and he actually got a reply. Steve wrote:

Even though my personal political leanings are democratic, I think this app will be offensive to roughly half our customers. What’s the point?

Steve

I’ve often wondered what the Steve Jobs who attended Reed College during the early days of the Watergate scandal would think of that quote.

Steve Jobs, George Bush, Richard Nixon, and Scott Ritter

These four people—two that I admire and two that broke our trust—have become linked in my mind because of the Freedom Time rejection.

Freedom of speech is easy to defend when the speech is popular, but the real test comes when you have to defend unpopular speech or things that you don’t agree with.

In Fall 2008, George Bush had the worst approval ratings since Nixon. At a time in which we had one of the most unpopular Presidents in American history, Apple didn’t have the courage to approve a simple, stupid application like Freedom Time.

What is the likelihood that Apple would approve a truly controversial and unpopular application during a time when popular opinion makes it difficult to stand up for what’s right?

I find myself wondering what would have happened if former marine and U.N. Weapons Inspector Scott Ritter had tried to release an application in 2002 talking about how there were no weapons of mass destruction in Iraq.

When Ritter did speak up in 2002 and told the world that he had been in Iraq and that there were no weapons of mass destruction, popular opinion was so high in favor of Bush policies that despite being known as a patriot, conservative, and a hawk, Ritter was called a traitor by some.

What if the only means Scott Ritter had to share what he knew with the rest of the world had been through an App Store?

Flickr Censorship Pales in Comparison

Censored Obama imageRecently Flickr received a lot of scrutiny and pressure because of perceived censorship of a political image. The image showed a modified version of Obama on the cover of Time Magazine where Obama was made to look like the Joker from the most recent Batman movie.

Yahoo, the parent company for Flickr, later explained that they removed the image from Flickr because they had received a copyright infringement claim.

I don’t care to debate the Flickr censorship case. Instead, I want to ask simply why Flickr got a lot of grief for censoring a single image that they say they removed because of a copyright claim, but Apple has thus far escaped scrutiny for a standing policy that rejects any applications that attack political figures.

The image that Flickr removed would have never made it through the iPhone app review process in the first place.

The Mobile Proposition: Trade Liberty for Security

Apple has good reasons for why it has an App Store review process. It told the FCC that:

We created an approval process that reviews every application submitted to Apple for the App Store in order to protect consumer privacy, safeguard children from inappropriate content, and avoid applications that degrade the core experience of the iPhone.

This is a very similar argument that carriers and handset manufacturers have been making for years now. The argument is that mobile phones contain so much personal, sensitive information that applications need to be vetted to ensure that consumers are protected.

This is the same argument that Ben Franklin famously warned us about when he said:

Those who would give up Essential Liberty to purchase a little Temporary Safety, deserve neither Liberty nor Safety.

And despite the fact that we would not accept similar arguments from our government, we seem willing to give up our freedoms to mobile companies for the sake of our own security.

It’s Not About Apple. It’s About Gatekeepers

While I’ve spent most of my time focusing on Apple, please don’t mistake this as a tirade against Apple. Apple just happens to be leading the way in this area of mobile as well.

The reality is that if mobile is going to live up to its promise, we need a future without gatekeepers.

It isn’t hard to conceive of a future where more people have smartphones than have PCs. In some countries, people get more news from their mobile phones than they do from their desktop computers.

Before we get to the point where mobile phones have become the primary way that people get their news and information, we need to ensure that we have the freedom to publish what we want without restrictions.

For these reasons, I’m encouraged by the work of organizations like the Open Mobile Consortium. They are tackling the difficult work of providing truly open mobile solutions that allow people in repressive regimes to communicate freely.

The Moral Imperative of the Mobile Web

In addition to the Open Mobile Consortium, we need to make sure that there are alternatives to app stores and their gatekeepers. The best alternative is web technology.

This is why I’ve gone from thinking about mobile web technology as a smart business decision for some applications to thinking of it as a moral imperative.

Even if you are an Objective-C programmer who has had a lot of success on the iPhone App Store, it is in your best interest that the mobile web develop into a viable alternative to app stores. It is in society’s best interest.

To get to that point, we need to solve the short-coming of the mobile web. We need the technology to stabilize. We need real browsers on all phones. And we need a reliable and easy way to accept payment for our mobile web applications and services.

I cannot state this strongly enough: we need an open and free mobile web to be a viable alternative to the mobile gatekeepers to ensure that we have the freedom to say what must be said and the ability to have our voices heard by others.

JavaScript GZIP Compression in WordPress: What’s Possible and what Hurts

Thursday, September 17th, 2009

WordPress 2.8 introduced some constants and bits and bots that nominally make certain kinds of compression of JavaScript and CSS possible. This post looks at JavaScript compression and explains what is possible, and what is very, very hard.

In a nutshell, with a bit of tweaking, you can GZIP and concatenate the scripts that come packaged with WordPress. GZipping and concatenating anything else–plugin scripts or scripts in your own theme–is not currently supported in any obviously sane way (using WP’s WP_Scripts management class anyway).

I’m going to give away the ending to save you some time:

add_action('wp_enqueue_scripts', 'lyza_force_compress');
function lyza_force_compress()
{
    global $compress_scripts, $concatenate_scripts;
    $compress_scripts = 1;
    $concatenate_scripts = 1;
    define('ENFORCE_GZIP', true); 
 
    /* enqueue your scripts here */
}

Putting the above in your functions.php file may result in insanely good compression on your subsequently-enqueued JavaScript files. I say may because GZIP is one of those fidgety server-side things that varies from hosting provider to hosting provider. I tested this approach on two vastly different environments and had good success, but as always with these things, YMMV.

While this may look rather silly and simple, figuring out exactly which constants and globals to set and when to set them took me just about forever.

The most important thing to note is that this only works on scripts that come pre-packaged with WordPress and are listed in the wp_default_scripts() function in wp-includes/script-loader.php. This is slightly irritating.

When it Does Work

The above will concatenate and GZIP all of the applicable enqueued JavaScript into a single request, served out through the wp-admin/load-scripts.php script.

  • By “applicable”, I mean scripts listed in wp-includes/script-loader.php in the wp_default_scripts() function.
  • If you have applicable JavaScript in both the head and the foot, you will end up with two script src tags. If everything is in the foot (or the head), you’ll get one tag. You not only get GZipping, you get fewer HTTP requests! Yay!
  • JavaScript in plugins and your own theme won’t get concatenated and GZipped in this approach, but it certainly doesn’t break it.

In testing, the following:

    wp_enqueue_script('jquery');
    wp_enqueue_script('thickbox');
    wp_enqueue_script('scriptaculous');
    wp_enqueue_script('editor');

Went from:

10 requests, 310kB

to

2 requests, 90kB

with the activation of the above function. Nice! I got two requests because the above enqueueing puts stuff in both the head and the footer.

That’s a 340% improvement on filesize alone.

Why Won’t It Work for All JavaScript?

Because there are no, nada, zilch, none hooks for making it do so without doing some deep surgery and writing a plugin. It boils down to a couple of places in code:

From wp-includes/class.wp-scripts.php in the do_item() function:

100
101
102
103
104
105
106
107
108
	if ( $this->in_default_dir($srce) ) {
		$this->print_code .= $this->print_scripts_l10n( $handle, false );
		$this->concat .= "$handle,";
		$this->concat_version .= "$handle$ver";
		return true;
	} else {
		$this->ext_handles .= "$handle,";
		$this->ext_version .= "$handle$ver";
	}

To get the built-in concatenation and GZIPped delivery, it is necessary that the if statement here evaluate true. I won’t explain the nitty gritty unless you really want me to.

So, my first approach was to add paths to the $wp_scripts->default_dirs Array to add entries for my theme’s scripts and my plugin dir’s scripts. Big fat fail.

The reason is that the actual file — wp-admin/load-scripts.php — that serves up the concatenated, zipped JavaScript is a standalone script. I imagine that this is both for security and for performance. It does not have the complement of WordPress constants and hooks that we are accustomed to. In fact, it is completely and absolutely unpluggable (unless I missed something). It only includes the files that define the WP_Scripts and WP_Dependencies classes, and utility functions for those. It does not include any theme- or plugin-level items.

And it does something that completely shuts down the game. It instantiates a new, clean WP_Scripts object and then calls wp_default_scripts().

If you’ll recall, the WP_Scripts object in a normal WordPress request is a global singleton that manages all of the enqueued scripts. By creating a new instantiation, the load-scripts.php script has obliterated any notion of any enqueued scripts. Further, the wp_default_scripts() function is a hard-coded list of the JavaScript files that WordPress comes packaged with. While this function nominally triggers the ‘wp_default_scripts’ action, this is not usable here because no files are getting included in which I could take advantage of that hook. Further, it redefines do_action() and other API functions as blank functions that do nothing.

The load-scripts.php file then iterates through the requested JavaScript handles (comma-delimited GET) and sees if it recognizes them from the wp_default_scripts() list. As anything that’s in your own theme or in a plugin won’t be in this list, FAIL.

Though I see some possible options for me in the writing-a-plugin realm, I also sadly see that it would replicate functionality and am highly curious as to what the WordPress developers had in mind here.

Getting all JavaScript into the Footer in WordPress? Not so fast, Buster!

Thursday, September 17th, 2009


Warning: Technical WordPress post ahead!

Overview: Really Getting JavaScript Into the Footer

Quoth the WordPress Version 2.8 feature list:

– Improvements to the script loader: allows plugins to queue scripts for the front end head and footer, adds hooks for server side caching of compressed scripts, adds support for ENFORCE_GZIP constant (deflate is used by default since it’s faster)

At the time, I thought Wow, cool. When I have time, I’ll investigate that and then immediately forgot about it for a few months. During RSS-coffee-breaks I read Lester Chan’s post about how to put JavaScript in the footer (sounds easy enough!) and Andrew Ozz’s post, which left me coated with an intense and foolish optimism about compression.

What I aim to do in this post — part one of a series of three if I find time to investigate the second and third pieces — is explain why it’s not as easy as you’d expect to get some scripts (specifically scripts that come with WordPress by default) into the footer, and how you can make it happen.

If you’re in a hurry, you can skip to the Summary section at the end of the post.

WP JavaScript Inclusion: Header vs. Footer

What I read had me believe that it is falling-off-log easy to put all WordPress JavaScript in the footer. If you are trying to include a piece of JavaScript, say, in a plugin, that WP has not previously known about, it is that easy. But woe if you try this on certain scripts that come packaged with WordPress.

Let’s take a look at the functions that are involved in letting WordPress know that you want to use a given piece of JavaScript.

These are taken from wp-includes/functions.wp-scripts.php.

wp_register_script() and wp_enqueue_script()

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
/**
 * Register new JavaScript file.
 *
 * @since r16
 * @see WP_Dependencies::add() For parameter information.
 */
function wp_register_script( $handle, $src, $deps = array(), $ver = false, $in_footer = false ) {
	global $wp_scripts;
	if ( !is_a($wp_scripts, 'WP_Scripts') )
		$wp_scripts = new WP_Scripts();
 
	$wp_scripts->add( $handle, $src, $deps, $ver );
	if ( $in_footer )
		$wp_scripts->add_data( $handle, 'group', 1 );
}
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/**
 * Enqueues script.
 *
 * Registers the script if src provided (does NOT overwrite) and enqueues.
 *
 * @since r16
 * @see WP_Script::add(), WP_Script::enqueue()
*/
function wp_enqueue_script( $handle, $src = false, $deps = array(), $ver = false, $in_footer = false ) {
	global $wp_scripts;
	if ( !is_a($wp_scripts, 'WP_Scripts') )
		$wp_scripts = new WP_Scripts();
 
	if ( $src ) {
		$_handle = explode('?', $handle);
		$wp_scripts->add( $_handle[0], $src, $deps, $ver );
		if ( $in_footer )
			$wp_scripts->add_data( $_handle[0], 'group', 1 );
	}
	$wp_scripts->enqueue( $handle );
}

As a theme developer, you may only ever have encounters with wp_enqueue_script(). But let’s look at what each of these functions does so I can then explain the issue.

wp_register_script() tells WordPress about a script, but does not actually cause it to be included in a given page request. By default, WordPress registers a gripload of scripts that are then available to you, the theme hacker, when or if you should need them. A list of these can be found in wp-includes/script-loader.php in the wp_defalut_scripts() function. Highlights include jQuery, prototype, scriptaculous, etc., as well as extensions to those frameworks (e.g. jQuery UI). WordPress (via the WP_Scripts class, itself extended from WP_Dependencies) handles dependencies and makes sure that jQuery UI doesn’t get included without its necessary jQuery, if you should forget to enqueue jQuery itself or it gets enqueued after jQuery UI.

wp_enqueue_script() tells WordPress, hey, I actually need this script, in this request. You may have seen or done something like this:

wp_enqueue_script('jquery');

This spools up jQuery and spits out a script tag to include the requested script.

In a lot of cases, it seems easy and straightforward to do this simple enqueue request. jQuery comes packaged with WP and is automatically registered for you, so you just have to hand the wp_enqueue_script() function one argument: $handle.

As a clever theme hacker, you may have noticed that the signature for wp_enqueue_script() and wp_register_script() changed in version 2.8 and this seems exciting. An $in_footer parameter was added:

wp_enqueue_script( $handle, $src = false, $deps = array(), $ver = false, $in_footer = false );

Totally psyched, you update your theme and use:

wp_enqueue_script('jquery','','','',true);

And wait for the magic. RELOAD! Wait, maybe something’s cached. RELOAD! Wait, what? RELOADRELOADRELOAD.

jQuery is still in the head.

So you get irritable and you quit trying, or like me you spend a few hours deactivating all of your plugins and trying to figure out where the problem is. You notice that the same thing happens with other scripts that WP already knows about (that is, the scripts in wp_default_scripts()). Stubbornly, they won’t get out of your page’s head element.

Here’s why.

Why WordPress Default JavaScripts Won’t Move to the Footer

The crux is: if the script you are enqueueing has anything defined as a dependency in WordPress’ wp_default_scripts() function, it will ignore your request to put it in the footer (I’ll provide a workaround shortly).

The reason for this is twofold.

Dependency Handling and “Groups”

Part of WordPress’ dependency handling for scripts involves “groups”, the ins and outs of which I’ll leave as an exercise for an intrigued reader. In an oversimplification, it put scripts with dependencies (e.g. jQuery, Scriptaculous) in groups[0]. It explicitly puts scripts that depend on other scripts in groups[1]. The default behavior of both wp_register_script() is to put a script in groups[0] if the $in_footer argument != true.

How Groups Handling does Something Possibly Confusing

OK, now check out this snippet from class.wp-scripts.php (do_item() method):

85
86
87
88
if ( 0 === $group && $this->groups[$handle] > 0 ) {
	$this->in_footer[] = $handle;
	return false;
}

This piece of logic puts groups > 0 into the footer. So that’s how WP decides to move things into the footer–it’s based on where the script is in the $wp_scripts->groups Array.

But here’s a potential pitfall in the wp_enqueue_script() function:

	if ( $src ) {
		$_handle = explode('?', $handle);
		$wp_scripts->add( $_handle[0], $src, $deps, $ver );
		if ( $in_footer )
			$wp_scripts->add_data( $_handle[0], 'group', 1 );
	}
	$wp_scripts->enqueue( $handle );

If you don’t give wp_enqueue_script() a $src (which you don’t have to provide do if the script has already been registered) for your $handle, it is going to enqueue it in whatever group it’s already registered in. So, when you do your little simple enqueue:

wp_enqueue_script('jquery','','','',true);

The entire part of the function where it would put it in the footer doesn’t execute because the if($src) test fails. And jQuery has already been registered—in groups[0].

Possible Workaround

I don’t like this but it works:

wp_enqueue_script('jquery','/wp-includes/js/jquery/jquery.js','','',true);

jQuery is now in the footer.

This does still appear to handle dependencies correctly, but I haven’t deeply tested. Also, there are some valid reasons to have some scripts, and possibly jQuery, in the head. This was just a demo.

Getting JS into the Footer: Quick Summary

// This will NOT put jquery in the footer
wp_enqueue_script('jquery','','','',true); 
 
// But this will, if inelegant and circumventing abstraction
wp_enqueue_script('jquery','/wp-includes/js/jquery/jquery.js','','',true);

For My Next Trick…Compression

Really, this post was a red herring. I tripped into this oddity while investigating the second part of the WordPress 2.8 feature claim: adds hooks for server side caching of compressed scripts, adds support for ENFORCE_GZIP constant (deflate is used by default since it’s faster). We’ll talk about that next time.