Facebook, Facebook, Facebook, how I despise thee. I’m in the middle of developing a Flash based Facebook application, which requires the ability for a user to view particular images in Facebook supported countries. I assumed Facebook had some sort of API which would return the countries they support. But as it turns out, they dont. Facebook groups countries by locale and language as demonstrated by Facebook’s locale xml : http://www.facebook.com/translations/FacebookLocales.xml .
Not really usable in regards to what I need, but I can work with it. The widget below is a tool I created which takes the FacebookLocales.xml and the ISO 3166 code lists and spits out the countries that Facebook supports, in either xml format or an array of objects. I thought this would be useful for you other flash devs out there.
The code is quite simple :
/****************************
* Manuel Gonzalez *
* design@stheory.com *
* www.stheory.com *
* www.codingcolor.com *
*****************************/
package
{
import flash.display.Sprite;
import flash.system.Security;
import flash.system.System;
import fl.controls.Button;
import fl.controls.TextArea;
import fl.controls.RadioButton;
import fl.controls.RadioButtonGroup;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.display.Loader;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
import flash.utils.Dictionary;
public class DocApp extends Sprite
{
private var facebookXml:String = "FacebookLocales.xml";
private var isoXml:String = "iso_3166-1_list_en.xml";
private var facebookCountryCodes:Array;
private var isoDataArray:Array;
private var finalCountriesData:Array;
private var outputField:TextArea;
private var printOutputButton:Button;
private var clipBoardButton:Button;
private var rbg:RadioButtonGroup;
public function DocApp()
{
Security.loadPolicyFile("your_path_to_cross_domain.xml");
createUI();
outputField.text = "loading data";
loadXML(facebookXml, fbXMLLoaded);
}
/*
Method: loadXML
Parameters:
inPath:String
inCallback:Function
Returns:
*/
private function loadXML(inPath:String, inCallback:Function):void
{
var loader:URLLoader = new URLLoader ();
var req:URLRequest = new URLRequest(inPath);
loader.addEventListener(Event.COMPLETE, inCallback, false, 0, true);
loader.load(req);
}
/*
Method: fbXMLLoaded
Parameters: evt:Event
Returns:
*/
private function fbXMLLoaded(evt:Event):void
{
var theXml:XML = new XML(evt.target.data);
parseFbXml(theXml);
arrayRemoveDup(facebookCountryCodes);
//
loadXML(isoXml, isoXMLLoaded);
}
/*
Method: isoXMLLoaded
Parameters: evt:Event
Returns:
*/
private function isoXMLLoaded(evt:Event):void
{
var theXml:XML = new XML(evt.target.data);
parseIsoXml(theXml);
buildCountryData();
outputField.text = "Data Ready";
}
/*
Method: parseIsoXml
Parameters: inXml:XML
Returns:
*/
private function parseIsoXml(inXml:XML):void
{
var data:XML = inXml as XML;
isoDataArray = [];
var numCountries:int = data.ISO_3166_1_Entry.length();
for (var i:int = 0; i < numCountries; i++) {
var current:XML = data.ISO_3166_1_Entry[i];
var cObj:Object = {};
cObj.value = current.ISO_3166_1_Alpha_2_Code_element;
cObj.label = current.ISO_3166_1_Country_name;
isoDataArray.push(cObj);
}
}
/*
Method: parseFbXml
Parameters: inXml:XML
Returns:
*/
private function parseFbXml(inXml:XML):void
{
var data:XML = inXml as XML;
facebookCountryCodes = [];
var numLocales:int = data.locale.length();
for (var i:int =0; i< numLocales; i++) {
var current:XML = data.locale[i];
var rep:String = current.codes[0].code.*.representation;
var pos:int = rep.indexOf("_");
var countryCode:String = rep.substr(pos + 1);
facebookCountryCodes.push(countryCode);
}
}
/*
Method: buildCountryData
Parameters:
Returns:
*/
private function buildCountryData():void
{
var len:int = facebookCountryCodes.length;
finalCountriesData = [];
for (var i:int = 0; i < len; i++) {
var codeStr:String = facebookCountryCodes[i];
var isolen:int = isoDataArray.length;
for (var j:int = 0; j < isolen; j++) {
if (codeStr.toLowerCase() == isoDataArray[j].value.toLowerCase()) {
finalCountriesData.push(isoDataArray[j]);
break;
}
}
}
}
/*
Method: createUI
Parameters:
Returns:
*/
private function createUI():void
{
outputField = new TextArea();
outputField.setSize(500, 500);
outputField.move(25, 40);
addChild(outputField);
printOutputButton = new Button();
printOutputButton.width = 75;
printOutputButton.move(450,10);
printOutputButton.label = "Print";
printOutputButton.setStyle("textFormat", new TextFormat("Arial"));
printOutputButton.toggle = true;
printOutputButton.addEventListener(MouseEvent.CLICK, printToOutputField,false,0,true);
addChild(printOutputButton);
//
clipBoardButton = new Button();
clipBoardButton.width = 125;
clipBoardButton.move(225,550);
clipBoardButton.label = "Copy To Clipboard";
clipBoardButton.setStyle("textFormat", new TextFormat("Arial"));
clipBoardButton.toggle = true;
clipBoardButton.addEventListener(MouseEvent.CLICK, copyData,false,0,true);
addChild(clipBoardButton);
//
rbg = new RadioButtonGroup("options");
createRadioButton("Xml", rbg,225,10);
createRadioButton("Array of Obj", rbg,325,10);
}
/*
Method: copyData
Parameters: evt:MouseEvent
Returns:
*/
private function copyData(evt:MouseEvent):void
{
copyToClipboard(outputField);
}
/*
Method: printToOutputField
Parameters: evt:MouseEvent
Returns:
*/
private function printToOutputField(evt:MouseEvent):void
{
if (rbg.selection == null) {
return;
}
outputField.text = "";
if (rbg.selection.label == "Xml") {
printXMLToOutput();
} else {
printObjArrayToOutput();
}
}
/*
Method: createRadioButton
Parameters:
rbLabel:String
rbg:RadioButtonGroup
xpos:Number
ypos:Number
Returns:
*/
private function createRadioButton(rbLabel:String, rbg:RadioButtonGroup,xpos:Number,ypos:Number):void
{
var rb:RadioButton = new RadioButton();
rb.group = rbg;
rb.label = rbLabel;
rb.move(xpos, ypos);
addChild(rb);
}
/*
Method: copyToClipboard
Parameters: inTf:*
Returns:
*/
private function copyToClipboard(inTf:*):void
{
System.setClipboard(inTf.text);
}
/*
Method: printObjArrayToOutput
Parameters:
Returns:
*/
private function printObjArrayToOutput():void
{
finalCountriesData.sortOn("label");
var len:int = finalCountriesData.length;
outputField.text = 'var facebookCountries:Array = [';
for (var i:int = 0; i < len; i++) {
if (i == len - 1) {
outputField.appendText('{value:'+'"'+finalCountriesData[i].value+'"'+',label:"'+finalCountriesData[i].label+'"}];');
} else {
outputField.appendText('{value:"'+finalCountriesData[i].value+'",label:"'+finalCountriesData[i].label+'"},\n');
}
}
}
/*
Method: printXMLToOutput
Parameters:
Returns:
*/
private function printXMLToOutput():void
{
outputField.text = '<facebook_countries_en xml:lang="en"> \n';
finalCountriesData.sortOn("label");
var len:int = finalCountriesData.length;
for (var i:int = 0; i < len; i++) {
outputField.appendText('<country_entry> \n');
outputField.appendText(' <country_code>'+finalCountriesData[i].value+'</country_code> \n');
outputField.appendText(' <country_name>'+finalCountriesData[i].label+'</country_code> \n');
outputField.appendText('</country_entry> \n');
}
outputField.appendText('<facebook_countries_en>');
}
/***************** HELPER METHODS *********************************/
/*
Method: arrayRemoveDup
Parameters: inArry:Array
Returns:
*/
private function arrayRemoveDup(inArry:Array):void
{
var i,j:int;
for (i = 0; i < inArry.length - 1; i++) {
for (j = i + 1; j < inArry.length; j++) {
if (inArry[i] === inArry[j]) {
inArry.splice(j, 1);
}
}
}
}
}
}
The code loads up FacebookLocale.xml, parses it and creates a facebook country code array. I proceed by removing duplicates in the array. Next, I load up the countries ISO xml , parse it and create a countries ISO data array with objects that contain the country name and country code. Lastly, I build my final country array by taking the Facebook country codes and searching for them in the countries ISO data array. If a country is found the ISO data Object is pushed to the final array. The rest of the code supports the UI. I’ve included everything you need in the download below. To keep the country list up to date you should always download the necessary xml files:
FacebookLocale.xml
iso_3166-1_list_en.zip
Also, Flash does not like the dash’s in the iso_3166-1_list_en.xml. If you download the zip from ISO and compare it with the xml I provided for you in the download, you will notice I replaced the dash with an underscore.
**** NOTE the duplicate function is not efficient, look over your output for doubles. I’ll release the fix when I get around to it. If you solved it, please post it …keep ActionScript open source.
Anyhow, enjoy!