Google Chrome : array evals return out of order

I just want to make others aware of a little quirk with Google Chrome’s Javascript engine (V8), eval’d associative JSON arrays (aka objects) are returned in the incorrect order . The problem is that the engine doesn’t do what a programmer would expect it to do, but the programmer should be aware of why its happening and that it does happen.

Basically, take the following psuedo associative array/object and its corresponding JSON version:

Psuedo Associative array
Array (
 3503 => '',
 3847 => '',
 6852 => ''
);

JSON Array
var data = {3503:'',3847:'',6852:''};

Pretty basic huh? But that happens when we loop over this array/object? In Firefox, Safari and IE we get the same result, which is the array elements in the order listed above. Chrome on the other hand returns the items out of order. Now I know you are probably thinking, “its an array/object, order doesn’t matter”. This is technically true, but not if you are relying on the order for some reason, then you might find bugs cropping up. Check out the code below:

var data = {3503:'',3847:'',6852:''};
var s = '';
for(var i in data) {
	s += i + ',';
}
alert("Expected order: 3503,3847,6852nOrder observed: " + s)

Firefox, Safari and IE all return the following alert:

Expected order: 3503,3847,6852
Order observed: 3503,3847,6852

Chrome on the other hand returns this:

Expected order: 3503,3847,6852
Order observed: 6852,3503,3847


Weird! Give it a try in your current browser by clicking here

Javascript guru, John Resig, has posted a note about this:
http://ejohn.org/blog/javascript-in-chrome/

Or for the official bug reports:
http://code.google.com/p/v8/issues/detail?id=6
http://code.google.com/p/chromium/issues/detail?id=883

As always with javascript programming, expect the unexpected… and…
Be Warned!

Trac ticket: reset to new

We have recently moved from Mantis to Trac at work for our bug/task tracking, but we have encountered a slight issue with Trac’s workflow management. The issue is that we wanted to be able to move a ticket from the ‘assigned’ state to the ‘new’ state. This is a common scenario if a team member leaves or goes on holiday while they have tasks assigned to them. Quite often you wouldn’t just want to blindly ‘reassign’ these issues to another member, but reset them to their new status so another member can pick the task up when they have the time.

We decided to introduce a new state called ‘reset’ in the trac.ini [ticket-workflow] block which allows us to easily reset a ticket to the ‘new’ status as if it had just been created in the system. The new block looks like this:

reset = * -> new
reset.operations = del_resolution
reset.permissions = TICKET_MODIFY

Now at the bottom of each ticket, we have an option which says:

[ ] reset  Next status will be 'new'

Hope this works for you too :)

jQuery fadeIn/fadeOut IE cleartype glitch

While using the jQuery  javascript library today at work, I noticed a glitch under IE7. When fading a html node with the .fadeIn() and .fadeOut() functions in jQuery, IE drops the windows Cleartype rendering; which results in very ugly text. This problem appears to be very common, but no one has a nice solution for the problem.

The most common way to solve this problem is by removing the filter CSS attribute. In normal javascript, it would look like this:

document.getElementById('node').style.removeAttribute('filter');

and in jQuery, it would look like this:

$('#node').fadeOut('slow', function() {
   this.style.removeAttribute('filter');
});

This means that every single time we want to fade an element, we need to remove the filter attribute, which makes our code look messy.

A simple, more elegant solution would be to wrap the .fadeIn() and .fadeOut() functions with a custom function via the plugin interface of jQuery. The code would be exactly the same, but instead of directly calling the fade functions, we call the wrapper. Like so:

$('#node').customFadeOut('slow', function() {
   //no more fiddling with attributes here
});

So, how do you get this working? Just include the following code after you include the jQuery library for the added functionality.

(function($) {
	$.fn.customFadeIn = function(speed, callback) {
		$(this).fadeIn(speed, function() {
			if(jQuery.browser.msie)
				$(this).get(0).style.removeAttribute('filter');
			if(callback != undefined)
				callback();
		});
	};
	$.fn.customFadeOut = function(speed, callback) {
		$(this).fadeOut(speed, function() {
			if(jQuery.browser.msie)
				$(this).get(0).style.removeAttribute('filter');
			if(callback != undefined)
				callback();
		});
	};
})(jQuery);

I have been informed by Steve Reynolds that the US Whitehouse Website is using some of the JS documented on this blog post. I would just like to say thanks to everyone who contributed in the comments. :)

Issues with mysql 2.7 gem

I’ve been trying to get a rails development setup running on my Leopard install. After managing to get the mysql gem installed without errors, I can’t use the gem in any projects.

When I run rake db:migrate, I get the following error:

G5:ag $ rake db:migrate(in /Users/xxx/Projects/ag)
dyld: lazy symbol binding failed: Symbol not found: _mysql_init
Referenced from: /Library/Ruby/Gems/1.8/gems/mysql-2.7/lib/mysql.bundle
Expected in: dynamic lookupdyld: Symbol not found: _mysql_init
Referenced from: /Library/Ruby/Gems/1.8/gems/mysql-2.7/lib/mysql.bundle
Expected in: dynamic lookup
Trace/BPT trap

If anyone knows what the problem is, and has a solution, please let me know by leaving a comment!

EDIT:Thanks to Chris for doing the hard and blogging about it on this blog post  which appears to solve this problem. I’ll post here again once I have tried this solution.

Rails gem install mysql throws error: *** extconf.rb failed ***

Whilst reading guides on how to setup a rails dev server under OS X (both Tiger and Leopard), I kept running into issues installing the mysql gem. The guides would instruct you to install the mysql client libraries from the mysql website, which is fine. But to get improved performance under rails, you must install the mysql gem, but in doing so, I would constantly run into issues getting the gem to install correctly. The issues normally arises after running the following command:

sudo gem install mysql -- --with-mysql-dir=/usr/local/mysql

And the resulting error is:

checking for mysql_query() in -lmysqlclient... no

*** extconf.rb failed ***

Could not create Makefile due to some reason, probably lack of

necessary libraries and/or headers.  Check the mkmf.log file for more

details.  You may need configuration options.

Basically, the gem compile fails as a result of not knowing where the correct mysql files are, despite the fact that the command line switch points to the mysql folder.

To fix this problem, use a line like the following:

sudo gem install mysql -- --with-mysql-config=/usr/local/mysql/bin/mysql_config

Note that instead of pointing at the mysql folder, we are pointing at a mysql config which is bundled with the mysql client install files.

natsort() pain in PHP

While writing some software for work which works out distances between geographic locations, I discovered some nastiness with the natsort() function in php.

This function implements a sort algorithm that orders alphanumeric strings in the way a human being would while maintaining key/value associations. This is described as a “natural ordering”.

So, given this definition of natsort, I’ll now outline a working example and then an example of the problem I encountered.
Lets say we have a list of values in an array that need to be sorted descending whilst maintaining key/value pairs. E.g:

$a = array(4 => 9.1, 3 => 4.2, 10 => 4.5);
natsort($a);

As you would expect, the resulting array looks a little something like this.

print_r($a);
Array
(
[3] => 4.2
[10] => 4.5
[4] => 9.1
)

But what happens when the values in the array we are trying to sort are a little more complex:

$a = array(4 => 9.11705244995,3 => 4.23956628237,10 => 4.5361796771);
natsort($a);

The resulting array isn’t what we expect though.

print_r($a);
Array
(
[10] => 4.5361796771
[3] => 4.23956628237
[4] => 9.11705244995
)

As you can see, the sort order is incorrect. As you have probably picked up, the 4.5xxx number’s decimal places are 1 less than the other two numbers. As soon as you change 4.5361796771 to 4.53617967711 and run natsort() over it, it returns the correct order.

Conclusion: Don’t use natsort() when sorting floats of different precision as it will return incorrect values! Use something like asort() if you want to maintain key/value pairs, or sort() if you don’t care about the key ordering.

APML2JSON Script/Service

This script takes an APML feed, and parses it into valid APML-JSON based on the APML-JSON spec on the APML wiki. Instead of manually parsing the APML into JSON, I have used the XSLT file attached to the aforementioned spec page along with xsltproc to generate the JSON data. The idea behind this script is based on John Resig’s RSS2JSON script.At the moment the script is pretty hacky for release, so I have provided a REST interface that can be accessed via a GET request.

A request to the interface would take the following form:
http://bmn.name/examples/apml2json/?url=URL&callback=CALLBACK

The callback parameter is optional. If specified, the resulting JSON is wrapped in the callback for easy parsing at the client end, otherwise the resulting JS Object is assigned to a variable which can be accessed via JS. The results from the call are cached hourly to reduce the load on the server. :)

Example Interface call: http://bmn.name/examples/apml2json/?
url=http://blog.bmn.name/index.php?apml=apml&callback=parseFeed

For more information on how to use the resulting JS, head over to John’s RSS2JSON page as he provides some sample JS.

Blu-ray PS3 stuttering playback woes… Solved!

This blog post is for anyone who owns a PS3 and has discovered that *some* Blu-ray discs have stuttering/dropped frames playback.

I purchased a Playstation 3 back in April 2007, and received a free copy of Casino Royale on Blu-ray as part of a PS3 promotion. Needless to say, I opened the PS3 and stuck the blu-ray disc in to the drive to see what all the blu-ray fuss was about. The movie looked fantastic, even on my standard def TV. It looked even better on my brothers HDTV. Now you may be wondering why I’m saying this. Well, as I later found out, this initial experience was not indicative of the PS3′s blu-ray performance on every blu-ray disc.

Fast-forward ahead 8 months.

I decided to go halves in a brand new Samsung Full HDTV (1080p) for christmas. The picture quality of this baby is phenomenal on both HD FTA and PS3. As a present to myself, I went to JB-HIFI and purchased 3 blu-ray movies to try on the brand new tv. I bought Kingdom of Heaven, Gone in 60 Seconds and Behind Enemy Lines; all of which are fantastic movies. I tried out Behind Enemy Lines, and it looked spectacular. I then tried Kingdom of Heaven and had a similar reaction. Then, as you would have guessed, I tried Gone in 60 Seconds…

Arrrgghhhh! What the hell did they do to make this movie so painful to watch? The movie started out fine, but after about 40 seconds, the video started to stutter. It appeared as though video frames were being dropped as the audio wasn’t affected.

I continued to watch once the stuttering had stopped to see if it was a once off. But I was disappointed to find out that it continued to do it every 1 minute or so for about 10 seconds. I became very frustrated as blu-ray discs aren’t cheap. So I went back to JB-HIFI and swapped the disc for another copy of Gone in 60 Seconds so I could work out whether it was a disc problem or a PS3 problem.

I slid the disc into the console and held my breath…

Right on queue, it started to stutter. Argh! At this point I was very angry. I decided to have a hunt around in the BD/DVD settings section of the PS3. One option I found seemed like it fit the bill.

“BD 1080p 24Hz Output (HDMI) – Sets the playback method for BDs recorded at 24Hz (frames/second)”

By default this option is set to ‘Automatic’, so I decided to fiddle with this setting and set it to ‘Off’. I started the blu-ray disc up again and held my breath…

40 seconds passed…. 50 seconds passed… 5 minutes passed…

Nothing! Not a single stutter or anything! The problem was fixed. There is nothing on the blu-ray disc cover to suggest that the movie is in 24fps, so I guess its trial and error for each disc. But at least you now know how to fix the problem!

I’d like to hear from other people who have had the same problem.

EDIT: I have found a few resources on the net of other people experiencing the same problem, so if you wish to know the exact reason for this stuttering – read this thread.

JSON-APML Tag Cloud

As a member of the APML Google group, I’m constantly reading and keeping in touch with the APML developments. The latest development that sparked my interest was the need for a JSON equivalent of the APML standard which could be used as a more lightweight interchange format for more efficient web application implementations of the APML spec.

David Novakovic put his hand up to start working on the JSON-APML spec, and naturally, I decided to give him a hand. We decided to make the JSON-APML spec as close to the XML version as possible without the bloat of XML. You can read more about the spec proposed over at the JSON-APML Google Groups thread. Feel free to join the group and give your thoughts about the spec proposed.

Given this spec, I decided to do a quick working example of using the JSON-APML format. The example I created uses a service created by Paul Lamere over at Tastebroker. Paul’s script scrapes profile data from various websites, and returns a well-formed APML feed. My script uses these feeds as a base for conversion into the JSON-APML spec.

How it works:

The demo connects to a server with user and service information. The server then scrapes Paul’s APML feeds for a given user/service, parses the APML into JSON-APML and returns it to the browser. The browser then formats the data into a tag cloud using javascript.

Check the example of APML-JSON out.