Item1821: Creative reusage of country list in registration form

Priority: Enhancement
Current State: Closed
Released In: 1.1.0
Target Release: minor
Applies To: Engine
Reported By: MichaelDaum
Waiting For:
Last Change By: KennethLavrsen
There's a nice list of countries in the registration form. I wonder how to refactor this code to reuse the list somewhere else, e.g. in a "Country" formfield. So the task is to move it out there, and introduce it back again by some means of WikiApp. There are definitely a bunch of approaches there to do this either using standard Foswiki means or extra plugins.

This time I don't want to propose how to refactor it. Let's first see what others come up with.

So how woud you go for it?

  1. move out the country list from UserRegistration
  2. remove any html specifics previously used in the registration form i.e. the surrounding <option>....</option> code
  3. reintroduce the list dynamically by adding the option prefix and suffix again
  4. create a DataForm that has got a "Country" formfield; allowed values defined by this country list
  5. the list of countries should be manageable easily

-- MichaelDaum - 10 Jul 2009

Why not just using the select mechanism with the country list shipped as a Table in a topic in System?

  • Which select mechanism? - MD

-- ColasNahaboo - 10 Jul 2009

Maybe this can be done as a cached version of Wikipedias List of country names in various languages taking multiple languages into account.

  • Can you elaborate this? - MD

-- FranzJosefGigler - 10 Jul 2009

Let's have some demos in the Sandbox.

Extra points for elegance, simplicity, ease of use, robustness, maintainability and restriction to foswiki core means.

-- MichaelDaum - 10 Jul 2009

I've updated the html option list using

    use Geo::GeoNames;
    my $geo = new Geo::GeoNames();
    my $countryInfo = $geo->country_info();
    my $sortedByName = sort {
                                $a->{countryName} <=> $b->{countryName}
                            } @$countryInfo;
    foreach my $hash (@{$countryInfo}) {
        print '  <option>'.$hash->{countryName}."</option>\n";

this code should really be in the appropriate

anyone done any work on extracting this into a reusable list?

-- SvenDowideit - 12 Oct 2009

Er, the idea is clever but the code is flawed. The sorted list isn't used; if it were, the sort doesn't work because the wrong comparison operator is used. Try something like this:

use warnings;
use strict;

use Geo::GeoNames;

my $geo = new Geo::GeoNames();
my $countryInfo = $geo->country_info();
my @sortedByName = sort {
    $a->{countryName} cmp $b->{countryName}
} @$countryInfo;
foreach my $hash (@sortedByName) {
    print '  <option value="' .$hash->{countryCode}.'">'.$hash->{countryName}."</option>\n";

However, this is painfully slow, as it goes to every time. Country names don't change often, so you should do something like this instead:

use warnings;
use strict;

use Geo::GeoNames;
use Data::Serializer;

# Persistent store for country list
my $file = "/tmp/countrylist";

# Expiration time (seconds)
my $cachetime = 24*60*60;
# DEBUG: $cachetime = 10;

sub getList {
    my $s = Data::Serializer->new();
    my $fh;

    # Try persistent store
    if( open( $fh, '<', $file ) ) {
   if( (stat $fh)[9] + $cachetime > time() ){
       my $x = $s->retrieve( $fh );
       close $fh;
       return @$x;
   # Expired, refresh
   close $fh;

    my $geo = new Geo::GeoNames();
    my $countryInfo = $geo->country_info();
    my @sortedByName = sort {
   $a->{countryName} cmp $b->{countryName}
    } @$countryInfo;
    $s->store( \@sortedByName, $file, '>', 0660 );

    return @sortedByName;

my @sortedByName = getList();

foreach my $hash (@sortedByName) {
    print '  <option value="' .$hash->{countryCode}.'">'.$hash->{countryName}."</option>\n";

This can be part of the build -- or even made into a dynamic part of Foswiki. You could have a countrycode plugin, or make it a macro in the core. Country names, codes are certainly used by many applications (the point of the original report.) However, I'll leave implementation as an exercise...

You should, of course, adjust the filename, cache timeout & permissions to suit your taste.


-- TimotheLitt - 25 Oct 2009

To reuse a country list I would do the following two things:

1. Put the country names in a table in another topic, use Name header so that formfields can look it up by default behaviour with DataForms. The table would be "edittable" to easy do updates (editrowplugin I use):


2. Use FilterPlugin and EXTRACT to build the html options.

FilterPlugin doesn't seem to be active on Tasks web but see CountryNames in the Sandbox web for a live example.

Example WML:
<form name="fCountryNames" method="post" action="%TOPICURL%">

Select country from list:

<select name="COUNTRY"><option selected="%URLPARAM{ COUNTRY }%" value="%URLPARAM{COUNTRY}%" >%URLPARAM{COUNTRY}%</option>
%EXTRACT{ topic="CountryNames" web="Sandbox" skip="1" pattern="\|\s?(.*?)\s?\|" format="<option>$1</option>" }%
<input type="submit" value="Send" />
-- LarsEik - 25 Oct 2009

I have added a new example using a bullet list and regex search to CountryNames.

-- ArthurClemens - 06 Mar 2010

The example displays a perl regex at the end of the listbox (and in some of the examples, in several spots in the listbox).

-- TimotheLitt - 29 Jun 2010

FlexFormPlugin's RENDERFORDISPLAY is also able to return a list of allowed values. That's most probably the most robust mechanism as it reuses the core's native way to extract values from a formfield definition.

-- MichaelDaum - 30 Jun 2010

Well, that's been done in Foswiki-1.1 now: CountryList.

-- MichaelDaum - 20 Aug 2010

ItemTemplate edit

Summary Creative reusage of country list in registration form
ReportedBy MichaelDaum
Codebase trunk
SVN Range Foswiki-1.0.0, Thu, 08 Jan 2009, build 1878
AppliesTo Engine
Priority Enhancement
CurrentState Closed
Checkins distro:4a680cfceabe
TargetRelease minor
ReleasedIn 1.1.0
Topic revision: r15 - 04 Oct 2010, KennethLavrsen
The copyright of the content on this website is held by the contributing authors, except where stated elsewhere. See Copyright Statement. Creative Commons License    Legal Imprint    Privacy Policy