From Web Programming

Refresh Twitter and Facebook social icons after an Ajax request

I recently found myself dealing with the following problem: I wanted to lazy-load as much of the social networking components of a site as possible, which meant deferring the load of both the Twitter and Facebook JS until after the document finished rendering. This process was relatively straightforward, but in the course of implementing the buttons I discovered something interesting: when you do an Ajax request to refresh a portion of the page, buttons in there are not dynamically refreshed. This makes sense–there’s nothing to re-run the appropriate JS methods to render them–but it’s not good.

My quest on Google first took me to this forum, where the exact same problem I was having was discussed back in Sept-Oct. Since a new version of the Twitter @anywhere API came out today, and doesn’t include a TweetButton, that wasn’t going to be an option either.

Thankfully, I found this post, which outlined the best workaround I’d seen yet for interacting with Twitter’s widgets.js file. It’s worth a quick aside here: the problem is created because the @anywhere API, which has all named functions, does not have a method to create a TweetButton. That is handled instead within widgets.js, which is all wrapped in one big anonymous function. There’s a render() method hiding pitifully inside, but it took someone with JS skills beyond mine to coax it out of hiding.

Both of the examples in the previous link work great, and can be cut-and-paste. In my case, however, I didn’t want to mess with the actual $.get request, which was happening in a completely different script file, and was written years ago. Thankfully, a few quick tweaks resulted in this:

$('.topic-term-link').ajaxComplete(function(){
   //re-render the facebook icons (in a div with id of 'content')     
   FB.XFBML.parse(document.getElementById('content'));

  //re-render twitter icons by calling the render() method on each
  $('#content').find('a.twitter-share-button').each(function(){
     var tweet_button = new twttr.TweetButton( $( this ).get( 0 ) );
     tweet_button.render();
  });
});

Since jQuery lets me bind directly to the ajaxComplete event, I didn’t even need control over the Ajax call, which is good, because it wasn’t an option. Now, maybe Twitter will name the main function in widgets.js and we can just call a single line like for Facebook in the above example.

502 Bad Gateway with phpMyAdmin and nginx

I recently ran into an issue with phpMyAdmin served via nginx. When I would click on some of the databases on the sidebar in the home phpMyAdmin screen, the main frame would return a 502 Bad Gateway from nginx. The nginx error.log revealed an “upstream sent too big header while reading response header from upstream” error, which led me to this site. By adding the suggested lines into the http {} section of the nginx.conf file, then restarting nginx, I was able to see the table view load correctly in phpMyAdmin. It’s worth noting that I’m using php-cgi, not php-fpm, so the exact directives required may be slightly different if you’re using php-fpm.

I found a Moodle easter egg!

I’ve been spending the morning trying to get our copy of Moodle moved over to a new server. As I was debugging some files in the lib/ directory, I noticed a file called womenslib.php (all other files are named %lib.php, i.e. weblib.php). I decided it was worth a look-see, and here’s what I found in the file:

   include('../config.php');
   redirect('http://en.wikipedia.org/wiki/Women%27s_liberation');

Maybe I’m wrong and this is linked somewhere, but it sure looks like an easter egg to me. Go Moodle devs!

jQuery – Excluding elements with attributes ending in a particular string

Ok, let’s say you have some data that looks like this:

A title
Some content
A title
Some content

Now, if you need to style just the elements that are NOT post-modal, you have a problem. You can’t just select elements that start with an id value of ‘post,’ because then you will be selecting all the divs within the container. You could style the html with an additional class, but in this case the html wasn’t changeable, and adding a class with jQuery presents the same problem as selecting the elements–they’ll all match at the start of the id, even the ones we don’t want. The solution is this:

$(".container").children().not('[id$=modal]').each(function(){
//you can do something to each non-modal element in here
});

Now we’ve selected only the elements within our container that don’t contain the word ‘modal’ at the end, and we’re free to do whatever we need to them (in my case, it was pagination). For additional info on the .not() method, check out the jQuery doc.

WordCamp Boulder 11 a.m. update

I’m attending WordCamp Boulder today, and as of now I’ve seen a couple of sessions. I have to say the Caching talk was quite informative and entertaining, and on a personal note was a source of some working nginx rewrite rules for WP Super Cache. Thanks to vocecommunications.com‘s Chris and Sean for an entertaining and informative talk. The only complaint I have is that the venue, TechStars’ office environment, was way too small for the group that attended. Don’t think that’s anyone’s fault, just the downside of an awesome talk with great attendance.

The second talk I attended focused on design. Some of the interesting notes I took away from that were that talk were to avoid ‘lorem ipsum’ default content, design for mobile by creating scalable CSS, and that designers should know at least HTML and CSS, even if they’re just ‘frontend’ people. The lorem ipsum issue made good sense–if you don’t know what kind of content you’re designing for, it’s likely your design will be generic and not help the content stand out for what it is. It’s worth spending the time to create some sample posts that actually represent the specific content you will be showing on the production site. Along the lines of mobile styling, the design panel agreed that scaling is the best way to address the needs of diverse resolutions. As we add things like smartphones, iPads, etc., the ability to target inidividual browsers becomes cumbersome, and something like http://simplebits.com/, which uses a design that scales quite nicely from iPhone to full desktop resolution, becomes a better choice.

I’ve definitely gotten my $25 worth so far.

WP-dBug

A colleague at work found dBug, a sweet PHP class for creating nice, clean debug output and implemented it into our framework. While debugging a different WordPress plugin, I realized how nice it would be to have similar output in WordPress. Thanks to some planned system downtime during a major datacenter move where I work, I finally had a chance to create a plugin to implement the dBug class. It’s basically a wrapper for the original class–all the credit should and does go to Kwaku Otchere for creating what is (in my opinion) the nicest-looking debug output I’ve ever seen. It’s simple as heck to use the plugin: just install it, activate, and call it like this:

[cc lang=”php”]
function fill_my_screen_with_stuffs (){
global $wpdb;
wp_dbug( $wpdb );
wp_die( ‘Did you know WP 3.0 has a cool new wp_die() function?’ );
}

[/cc]

As a side note, you can use dBug for whatever code you want–just include the single PHP file and use it according to the author’s instructions.

PHP function to parse out an integer into its component bits

A single integer is a great way to save data for options that are either/or, like whether a particular checkbox should be selected within an array of checkboxes. There are a lot of advantages, including a small database footprint (a single int instead of perhaps a comma-separated list-string), and really fast execution based on bit parsing.

To create an integer that can be used to save options as bits, simply assign values based on multiples of 2 to each option (i.e. 1, 2, 4, 8, 16). For example, 7 indicates the presence of three bits: 1, 2, and 4. Setting the integer is no problem–simply sum the bits together. Parsing the bits back out, however, is a little more difficult. Here’s a handy function to do that and put the results in an array:

[cc lang=”php”]
public static function parse_my_bits( $int = null ) {
$bits = array();
for($i=1;$i<=$int;$i*=2) { if( ($i & $int) > 0);
array_push($bits, $i);
}
return $bits;
}
[/cc]

If anyone knows of a faster way to do this, please comment below. After all, the purpose of using bitwise math is to save on overhead–if I’m doing it terribly inefficiently, I’d like to know.

CodeColorer for WordPress is totally sweet

After trying out a few code snippet plugins for WordPress, and not having much luck, I found CodeColorer. CodeColorer creates a nice code box for your snippet, which is quite visually appealing. Here’s an example of some php:

[cc lang=”php”]
‘none’);
echo $foo;
?>
[/cc]

Once you look at the code snippet that CodeColorer outputs, though, you start to get a sense of everything that it can actually do. For example, mouse over one of the functions above, and you’ll notice it links you to the appropriate function reference on php.net. I’ve just started working with the plugin, so I’m sure I haven’t tapped all the features yet, but so far I’m quite impressed.

neverblog is now running on a Linode VPS

[simage=127,288,y,left,]Speed: sweet, glorious speed. That’s what you should find as you visit this site in the future, now that everything’s been moved over to a Linode Virtual Private Server. After checking out a colleague’s site that loads pretty much instantly, despite beingĀ  a similar WordPress blog, I decided to sign on with Linode and dump my current Dreamhost shared hosting. At the same time, I followed the same colleague’s suggestion to switch my web server from Apache to nginx. If you’re not familiar with nginx, and you’re hosting a site on which you control the web server, nginx is definitely worth a look as an alternative to Apache, since it’s lighter and faster (also, it seems that the program’s author is willing to work with users to improve functionality).

I was pretty happy with my Dreamhost shared hosting for a while, but this site has outgrown the limited resources that I had, and furthermore the actual physical host that Dreamhost had me on was getting quite old (and full o’ data). I tried a Dreamhost PS for the last week, and while it seems to be decently fast (although the preview PS has 2+GB of RAM), I’m a little ticked off by the pricing. When I was looking at the PS, it was listed as $15 a month for 300MB of RAM (not a bad deal). Once I signed up for the trial, however, the total cost was revealed as $15 plus the shared hosting fee I already pay ($10.95 a month). That brought the total to about $26 a month, a lot more than the $20 a month for the Linode VPS with 360MB of RAM. All in all, the last 4-5 hours of moving my sites over has been worth it, and Linode has been tip-top so far. I’ll post more on them as I continue to use their hosting, and post some articles about the configuration I’m running on the VPS.

Tagline Rotator Plugin for WordPress version 1.1

Thanks to the holiday break, there’s a new version of Tagline Rotator available in time for the new year. You can read about it on the WordPress site here. The major improvement is that it now uses WordPress database prefixing. If you’re not familiar with this, it won’t affect your use of the plugin (you should still upgrade though). If you run a WPMU (multi-user) blog, or if you have several blogs sharing a single database, however, this is great news. It means you can run as many separate instances of Tagline Rotator as you want on the same database, and they will each use the prefix assigned to that blog. Please let me know if you run into any problems with this new version, and please use the automated upgrade feature of WordPress (or at least de-activate and re-activate the plugin when you upgrade). This will allow the plugin to rename its table using the WP prefix. Otherwise, you will get a mySQL error if your WP database prefix is not wp_ as the new version will be trying to access the taglines from the renamed database before it has been renamed. De-activating and re-activating the plugin fixes this error if you do get it.