Generating Country List For HTML Select

December 13, 2011

During a client project using Paypal DirectPayment API, I had to make a <select> with all the countries with their country codes as the value. For example:

<option value="US">United States</option>
<option value="CA">Canada</option>

Paypal already gives this list.

Problem is that it's only in English and all in caps. What I needed is a French version and an English version, not in caps.

Geonames.org just happens to have what I needed. This Python script is what I coded to generate what I needed:

import urllib, json, unicodedata

def get_list(username='demo', lang='en'):
"""Fetches the json of all countries from geonames.org."""
params = urllib.urlencode({'lang': lang, 'username': username})
url = 'http://api.geonames.org/countryInfoJSON?%s' % params
f = urllib.urlopen(url)
response_text = f.read()
return json.loads(response_text)["geonames"]

def country_list_generator(country_list, func):
"""Returns a generator of countries.
They are sorted alphabetically,
and the func passed as argument is applied to each of them."""
ordered = sorted(country_list,
key=lambda k: strip_accents(k['countryName']))
return (func(country) for country in ordered)

def country_to_option(country):
"""Transforms a country dict to an html option tag,
The country code is used for the value."""
return ('<option value="%s">%s</option>\n' % \
(country['countryCode'], country['countryName'])).encode('utf-8')

def country_to_csharp_dict_pair(country):
"""Transforms a country dict to a C# Dictionary pair."""
return ('{"%s", "%s"},\n' % \
(country['countryCode'], country['countryName'])).encode('utf-8')

def strip_accents(s):
"""Removes the accents from a unicode string.
This function is used for sorting."""
return ''.join((c for c in unicodedata.normalize('NFD', s) \
if unicodedata.category(c) != 'Mn'))

if __name__ == '__main__':
country_list = get_list('demo', lang='en')
with open('output.txt', 'w') as f:
gen = country_list_generator(country_list, country_to_option)
f.writelines(gen)

Hope it's useful to someone else.

The code is on Github.

Styling Google Maps

August 29, 2011

It seems to be a little known fact that you can add custom styles to Google Maps using the Javascript API.

It's really not that complex and we use it often for client sites.

First thing to do is create the JSON to use for the style. You can use this wizard, it's a great tool for that.

Then you use the JSON in your Javascript like so:

// your JSON
var mapStyle = [
{
featureType: "landscape",
elementType: "all",
stylers: [
{ hue: "#ff4d00" },
{ lightness: -72 },
{ saturation: -74 }
]
}
];

// usual Google Maps code, plus styling
var map;

$(function () {
var mapOptions = {
zoom: 12,
mapTypeId: 'MapStyle',
mapTypeControlOptions: {
mapTypeIds: ['MapStyle', google.maps.MapTypeId.SATELLITE]
}
};

var styledMapOptions = { name: "Map" };

map = new google.maps.Map(document.getElementById("styled-maps-example-1"), mapOptions);
map.setCenter(new google.maps.LatLng(46.8,-71.25));
var mapType = new google.maps.StyledMapType(mapStyle, styledMapOptions);
map.mapTypes.set('MapStyle', mapType);
map.setMapTypeId('MapStyle');
});

It's even in the docs. I don't see any reason why there's so little use of this feature.

Understanding Quadratic Bézier Curves

August 27, 2011

In a client project I had to draw by hand a quadratic Bézier curve, because the html5 canvas quadraticCurveTo does not return the information about the path drawn and I needed it.

Some basic explanation of a quadratic Bézier curve. You have a start point P1, an end point P2 and a control point C. Both the x and y of each point on the path is dependant on t, which will vary from 0 to 1. t=0 at the begining of the curve and t=1 and the end of the curve.

You draw an imaginary line between P1 and C (P1C line) and another one between C and P2 (CP2 line). For each value of t, you mark an imaginary point on P1C and CP2. The point on P1C is at t of the line, starting at P1, and the point on the CP2 line is at t of the line, starting at C. Let's call those points C1 and C2.

Then, you draw an imaginary line between C1 and C2, and you mark a real point at t of the C1C2 line.

You repeat the procedure for every value of t, where t varies from 0 to 1. All the points you marked on the line C1C2 are showing the quadratic Bézier curve.

Here's a little animation I made to explain it better:

t = 0

You can have a look at the source for a complete understanding, but here's the important part, edited for clarity:

// constants
var CANVAS_WIDTH = 301;
var CANVAS_HEIGHT = 301;
var p1x = 20;
var p1y = 200;
var cx = 140;
var cy = 20;
var p2x = 280;
var p2y = 280;

// basic setup
var $t = $('#bezier-example-1-t span');

var animationCanvas = $('#bezier-example-1 .animation').get(0);
var animationContext = animationCanvas.getContext('2d');
animationCanvas.width = CANVAS_WIDTH;
animationCanvas.height = CANVAS_HEIGHT;

var curveCanvas = $('#bezier-example-1 .curve').get(0);
var curveContext = curveCanvas.getContext('2d');
curveCanvas.width = CANVAS_WIDTH;
curveCanvas.height = CANVAS_HEIGHT;
curveContext.strokeStyle = "#777";
curveContext.lineWidth = 2;
curveContext.beginPath();
curveContext.moveTo(p1x, p1y);
curveContext.stroke();

setInterval(updateDemo, 1000/30);

var t = 0;
var d = 1; // direction

function updateDemo() { // called 30 times/second to animate
if (t > 1 || t < 0) {
d *= -1; // change direction
curveContext.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
curveContext.beginPath();
}
t += 0.01 * d; // continue moving
$t.html(Math.round(t*100)/100);
// update values
var c1x = p1x + (cx - p1x) * t;
var c1y = p1y + (cy - p1y) * t;
var c2x = cx + (p2x - cx) * t;
var c2y = cy + (p2y - cy) * t;
var tx = c1x + (c2x - c1x) * t;
var ty = c1y + (c2y - c1y) * t;

animationContext.save();
// clear old sketch
animationContext.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
// draw new line
animationContext.beginPath();
animationContext.strokeStyle = '#aaa';
animationContext.lineWidth = 1;
animationContext.moveTo(c1x, c1y);
animationContext.lineTo(c2x, c2y);
animationContext.stroke();
// draw points on lines
drawPoint(animationContext, c1x, c1y, 2, '#0f0');
drawPoint(animationContext, c2x, c2y, 2, '#0f0');
// draw point on curve
drawPoint(animationContext, tx, ty, 3, '#f0f');
animationContext.restore();

// draw the new Bezier curve segment
curveContext.lineTo(tx, ty);
curveContext.stroke();
}

The code is on Github.