Priority: Enhancement
Current State: Closed
Released In: 1.1.0
Target Release: minor
Applies To: Engine
Component:
Branches:
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?
Task:
- move out the country list from UserRegistration
- remove any html specifics previously used in the registration form i.e. the surrounding
<option>....</option>
code
- reintroduce the list dynamically by adding the option prefix and suffix again
- create a DataForm that has got a "Country" formfield; allowed values defined by this country list
- 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 build.pl..
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 ws.geonames.org 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.
Enjoy,
--
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>" }%
</select>
<input type="submit" value="Send" />
</form>
---
GOT: %URLPARAM{ COUNTRY }%
--
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