Name

state_select — display state selector dropdown box

DESCRIPTION

The state_select widget displays a state selector dropdown box.

EXAMPLES

Example: State selector

[widget name=widget_stateselect type=state_select]

          

NOTES

AVAILABILITY

state_select is available in Interchange versions:

4.6.0-5.9.0 (git-head)

SOURCE

Interchange 5.9.0:

Source: code/Widget/country_select.widget
Lines: 386


# Copyright 2005-2009 Interchange Development Group and others
# 
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.  See the LICENSE file for details.

CodeDef state_select  Widget  1
CodeDef state_select  Description State (needs country_select)
CodeDef state_select  Help Requires country_select widget for country to work properly
CodeDef state_select  Routine <<EOR
sub {
my $opt = shift;
my $sel = $opt->{state_element};
if(! $sel) {
  my $n = $opt->{name};
  my $pre = '';
  if($n =~ /^([a-z]_)/) {
    $pre = $1;
  }
  $sel = "${pre}state_widget_container";
}
$opt->{type} = 'hidden';
my $wid = Vend::Form::display($opt);
return qq{$wid<span id="$sel"></span>};
}
EOR

CodeDef state_select ExtraMeta <<EOM
{
_order => [ qw/
    state_element
  /],
state_element => {
  label => 'State element ID',
  help => 'The CSS ID of the span containing the dynamic widget. The \
 default is usually good (state_widget_container or b_state_widget_container)',
  widget => 'text_30',
},
}
EOM

CodeDef country_select  Widget  1
CodeDef country_select  Description Country
CodeDef country_select  Help Requires state_select widget for state to work properly
CodeDef country_select  Routine <<EOR
sub {
  my ($opt) = @_;
my $name = $opt->{name} ||= 'country';

use vars qw/$Tag/;

my $sel = $opt->{state_element};

my $pre = '';

if(! $sel) {
  my $n = $opt->{name};
  if($n =~ /^([a-z]_)/) {
    $pre = $1;
  }
  $sel = "${pre}state_widget_container";
}

my $svar = $opt->{state_var} || $opt->{state_variable} || "${pre}state";
my $svar_in = $svar . '_cs_in';
my $size = $opt->{state_size} || $opt->{cols} || $opt->{width} || '16';
my $ctab = $opt->{country_table} || 'country';
$opt->{state_style} ||= 'font-style: italic; font-size: smaller';

my $die = sub {
  my ($msg, @arg) = @_;
  $msg = errmsg($msg) if @arg;
  $Tag->error({ name => 'country_select widget', set => $msg});
  ::logError($msg);
  return undef;
};

my $pr; 
my $ap;

my $stab = $opt->{state_table} || 'state';

my $csort = $opt->{country_sort} || ($opt->{no_region} ? 'name' : 'sorder,name');
my $ssort = $opt->{state_sort} || 'country,name';

my @csort = grep /\w/, split /[\s,\0]+/, $csort;

my $csort_sub = sub {
  for(@csort) {
    my $so = $a->{$_} cmp $b->{$_};
    return $so if $so;
  }
  return 0;
};

my @ssort = grep /\w/, split /[\s,\0]+/, $ssort;

my $ssort_sub = sub {
  for(@ssort) {
    my $so = $a->{$_} cmp $b->{$_};
    return $so if $so;
  }
  return 0;
};

my $cdb = dbref($ctab) or return $die->('country table %s not found', $ctab);
my $sdb = dbref($stab) or return $die->('state table %s not found', $stab);
$ctab = $cdb->name();
$stab = $sdb->name();
my $cq = "select * from $ctab";
my $sq = "select * from $stab";
my $cary = $cdb->query({ sql => $cq, hashref => 1});
my $sary = $sdb->query({ sql => $sq, hashref => 1});

@csort = grep exists($cary->[0]{$_}), @csort;
@ssort = grep exists($sary->[0]{$_}), @ssort;

@$cary = sort $csort_sub @$cary;
@$sary = sort $ssort_sub @$sary;

if($opt->{only_with_shipping}) {
  @$cary = grep $_->{shipmodes} =~ /\w/, @$cary;
}

my %states;

for my $s (@$sary) {
  my $c = $s->{country};
  push @{$states{$c} ||= []}, [ $s->{state}, $s->{name} ];
}

my @copts;
my %no_state;

my $v_formv = "${pre}formv";
my $v_csval = "${pre}csval";
my $v_f = "${pre}f";
my $v_no_state = "${pre}no_state";
my $v_state_tary = "${pre}state_tary";
my $v_state_vary = "${pre}state_vary";

my $prev;
for my $c (@$cary) {
  if($c->{no_state}) {
    $no_state{$c->{code}} = 1;
  }
  if(! $opt->{no_region} and $c->{region} and $c->{region} ne $prev) {
    push @copts, ["~~" . $c->{region} . "~~"];
    $prev = $c->{region};
  }
  push @copts, [ $c->{code}, $c->{name} ];
}

my @pre;
push @pre, <<EOF;
<script>
var $v_formv;
var $v_no_state = new Array;
EOF

for(keys %no_state) {
  push @pre, "$v_no_state\['$_'] = 1";
}

push @pre, <<EOF;
var $v_state_vary = new Array;
var $v_state_tary = new Array;
EOF

for(keys %states) {
  my $sa = $states{$_};
  my @sv;
  my @st;
  my %seen;
  @$sa = grep !$seen{$_->[0]}++, @$sa;
  for my $e (@$sa) {
    push @sv, $e->[0];
    push @st, $e->[1];
  }

  for(@sv) { s/'/\\'/g; }
  for(@st) { s/'/\\'/g; }

  my $string = "$v_state_vary\['$_'] = ['";
  $string .= join "','", '', @sv;
  $string .= "'];";
  push @pre, $string;
  $string = "$v_state_tary\['$_'] = ['";
  $string .= join "','", errmsg('--select state--'), @st;
  $string .= "'];";
  push @pre, $string;
}

my $cvar = $opt->{name};
$cvar =~ s/\W+/_/g;

my $extra = $opt->{state_extra} ? " $opt->{state_extra}" : '';
my $state_js = $opt->{state_js} ? "; $opt->{state_js}" : '';
my $state_class = $opt->{state_class} ? "$opt->{state_class}" : '';
my $country_js = $opt->{country_js} ? "; $opt->{country_js}" : '';
for ($state_js, $country_js) { s|\bthis\.form\b|$v_formv|g }

push @pre, <<EOF;
function ${cvar}_widget_adjust_state (cel,sval) {
  var sbox = document.getElementById('$sel');
  var country = cel.value;

  if(! $v_formv) {
    $v_formv=cel.form;
  }

  if(! sval) {
    if($v_formv.$svar && $v_formv.$svar.value)
      sval = $v_formv.$svar.value;
    else sval = '';
  }

  if(! sbox) return;
  if($v_no_state\[country]) {
    sbox.innerHTML = '<span style="$opt->{state_style}">No state required</span>';
    $v_formv.$svar.value = '';
    return;
  }
  var svary = $v_state_vary\[country];
  if(! svary) {
    var val = '';
    sbox.innerHTML = '<input type="text" size="$size" name="$svar_in" \
 id="$svar_in" value="' + sval + '" onChange="$v_formv.$svar.value = this.value"$extra>';
    $v_formv.$svar.value=sval;

    return;
  }
  var stary = $v_state_tary\[country];

  var str = '<select name="$svar_in" id="$svar_in" onChange="$v_formv.$svar.value \
 = this.value$state_js" class="$state_class"$extra>';
  for(var i = 0; i < svary.length; i++) {
    str += '<option value="' + svary[i] + '"';
    if(svary[i] == sval)
      str += ' SELECTED';
    str += '>';
    str += stary[i];
  }
  str += '</select>';
  sbox.innerHTML = str;

  return;
}
</script>
EOF

my $sval = $CGI::values{$svar} || $::Values->{$svar};
$sval = HTML::Entities::encode($sval, $ESCAPE_CHARS::std);
$sval = $Tag->jsq($sval) || "''";
my $fname = $opt->{form_name} || 'nevairbe';

my $prepend = join "\n", @pre;

if(my $sub = $opt->{callback_prescript}) {
  $sub->($prepend);
}
else {
  $opt->{prepend} = '' unless defined $opt->{prepend};
  $opt->{prepend} .= "\n" if length $opt->{prepend};
  $opt->{prepend} .= $prepend;
}


my $append = <<EOF;
<script>
var $v_f = document.$fname;
var $v_csval = $sval;
if(!$v_f) {
  for(var i = 0; i < document.forms.length; i++) {
    $v_f = document.forms[i];
    if($v_f.$opt->{name}) {
      if($v_f.$svar && $v_f.$svar.value) 
        $v_csval = $v_f.$svar.value;
      ${cvar}_widget_adjust_state($v_f.$opt->{name}, $v_csval);
      break;
    }
  }
}
$v_formv = $v_f;
if($v_formv.$svar) {
  csval = $v_formv.$svar.value;
}
${cvar}_widget_adjust_state($v_formv.$opt->{name}, $v_csval);

</script>
EOF

if(my $sub = $opt->{callback_postscript}) {
  $sub->($append);
}
else {
  $opt->{append} = '' unless defined $opt->{append};
  $opt->{append} .= "\n" if length $opt->{append};
  $opt->{append} .= $append;
}

$opt->{js} = qq{ onLoad="${cvar}_widget_adjust_state(this)" onChange="${cvar}_widget_adjust_state \
(this)$country_js"};
my @out;
#push @out, '<xmp>';
#push @out, ::uneval(\%states);
#push @out, '</xmp>';

$opt->{type} = 'select';
push @out, Vend::Form::display($opt, {}, \@copts);

return join "\n", @out;
}
EOR

CodeDef country_select ExtraMeta <<EOM
{
_order => [ qw/
    state_var
    state_style
    state_class
    country_sort
    no_region
    only_with_shipping
    form_name
    country_table
    state_table
    state_element
    state_js
  /],
state_var => {
  label => 'State variable',
  help => 'default is <i>state</i>, might use <i>b_state</i> instead',
  widget => 'text_16',
},
state_class => {
  label => 'CSS class for state',
  help => 'Modify look of state text',
  widget => 'text_20',
},
state_style => {
  label => 'CSS style for state',
  help => 'Modify look of state text',
  widget => 'text_60',
},
no_region => {
  label => 'Region sort',
  help => 'Controls country groupings',
  options => '=Region sort, 1=No region sort',
  widget => 'select',
},
only_with_shipping => {
  label => 'Only with shipping',
  help => 'Only show countries that have value in shipmodes',
  options => '=All countries, 1=Only with shipping',
  widget => 'select',
},
country_sort => {
  label => 'Country sort order',
  help => 'Should be "name" if no region sort, "sorder,name" with region',
  widget => 'text_16',
},
country_table => {
  label => 'Country table',
  help => 'default is usually good (country)',
  widget => 'text_16',
},
state_sort => {
  label => 'State sort order',
  help => 'Default of <i>country,name</i> is usually OK',
  widget => 'text_16',
},
state_table => {
  label => 'State table',
  help => 'default is usually good (state)',
  widget => 'text_16',
},
state_element => {
  label => 'State element ID',
  help => 'The CSS ID of the span containing the dynamic widget. The \
 default is usually good (state_widget_container or b_state_widget_container)',
  widget => 'text_30',
},
state_js => {
  label => 'State javascript',
  help => 'Runs specified javascript under onChange. E.g. "state_js=check_tax(this.form)"',
  widget => 'text_20',
},
}
EOM

AUTHORS

Interchange Development Group

SEE ALSO

country_select(7ic)

DocBook! Interchange!