Sunday 13 March 2016

JavaScript Flags 2

As promised, I thought I'd take time to document some of the code behind my JavaScript flags hobby project. If you look at the data file for the flags, flagdata.js, you'll see a single JSONP-style JavaScript call:
Flags({
  AD:["Andorra",10/7,"..."],
  ...
  BL:["Saint-Barthelemy","FR"],
  ...
  JP:["Japan",3/2,"FwCrO+0+0+72"],
  ...
  ZW:["Zimbabwe",2,"..."]
});
The single argument is an object with ISO-3166 two-letter codes as keys and arrays of two or three elements as values. If the array has three elements, they are:
  1. The country or territory name, as a string;
  2. The flag's aspect ratio, as a rational floating-point number; and
  3. The instructions for drawing the flag, as a string (see below).
If the array has only two elements, they are:
  1. The country or territory name, as a string;
  2. The ISO-3166 code of the "parent" country whose flag this entry shares, as a two letter string.
The latter scheme allows "aliases" to be set up for flags that are shared by more than one territory:
  • France
  • Netherlands
  • Norway
  • United States of America
The instructions for drawing the flags as represented as a string. The pseudo-BNF of these instructions is as follows:
instructions ::= instruction ... 
instruction ::= command argument … 
command ::= 'A'..'Z' 
argument ::= number | colour 
number ::= sign digit ... 
sign ::= '+' | '-' 
digit ::= '0'..'9' 
colour ::= 'a'..'z'
It is therefore trivial to parse these instruction streams using regular expressions. For example, Japan has the following entry:
JP:["Japan",3/2,"FwCrO+0+0+72"]
The instruction stream can be split into individual instructions using:
instructions.match(/([A-Z][^A-Z]*)/g)
This produces an array:
["Fw", "Cr", "O+0+0+72"]
These three instructions can be further divided into numbers (which are always preceded with a sign) and single-letter colours:
instruction.match(/.\d*/g)
This produces an array for each instruction:
[
  ["F", "w"],
  ["C", "r"],
  ["O", "+0", "+0", "+72"]
]
The first element is thus always an upper-case letter and is used as the key into a map for commands. I'll discuss the meaning of each letter (command) next time. Subsequent elements in the instruction array are arguments to the command: numbers and/or colours. Colours are always lower-case letters:
a: #39F light-blue
b: #00F medium-blue
c: #009 dark-blue
g: #CCC grey
m: #630 brown
n: #000 black
o: #F60 dark-orange
p: #F90 light-orange
r: #F00 bright-red
s: #C00 medium-red
t: #900 dark-red
u: #060 dark-green
v: #090 medium-green
w: #FFF white
y: #FF0 yellow
But for now, we'll finish off the Japanese flag example by expanding the instruction arrays:
fill white
colour bright-red
circle +0 +0 +72
This would get translated by the JavaScript code in flags.js to the following pseudo-SVG:
svg viewbox="0 0 360 240" xmlns="http://www.w3.org/2000/svg"
  g stroke="none" transform="matrix(1.5,0,0,-1,180,120)"
    g
      rect fill="#FFF" height="240" width="240" x="-120" y="-120" /
      ellipse cx="+0" cy="+0" fill="#F00" rx="48" ry="+72" /
    /g
  /g
/svg

No comments:

Post a Comment