1 # Copyright 2005-2009 Interchange Development Group and others
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 2 of the License, or
6 # (at your option) any later version. See the LICENSE file for details.
8 CodeDef state_select Widget 1
9 CodeDef state_select Description State (needs country_select)
10 CodeDef state_select Help Requires country_select widget for country to work properly
11 CodeDef state_select Routine <<EOR
14 my $sel = $opt->{state_element};
18 if($n =~ /^([a-z]_)/) {
21 $sel = "${pre}state_widget_container";
23 $opt->{type} = 'hidden';
24 my $wid = Vend::Form::display($opt);
25 return qq{$wid<span id="$sel"></span>};
29 CodeDef state_select ExtraMeta <<EOM
35 label => 'State element ID',
36 help => 'The CSS ID of the span containing the dynamic widget. The default is usually good (state_widget_container or b_state_widget_container)',
42 CodeDef country_select Widget 1
43 CodeDef country_select Description Country
44 CodeDef country_select Help Requires state_select widget for state to work properly
45 CodeDef country_select Routine <<EOR
48 my $name = $opt->{name} ||= 'country';
52 my $sel = $opt->{state_element};
58 if($n =~ /^([a-z]_)/) {
61 $sel = "${pre}state_widget_container";
64 my $svar = $opt->{state_var} || $opt->{state_variable} || "${pre}state";
65 my $svar_in = $svar . '_cs_in';
66 my $size = $opt->{state_size} || $opt->{cols} || $opt->{width} || '16';
67 my $ctab = $opt->{country_table} || 'country';
68 $opt->{state_style} ||= 'font-style: italic; font-size: smaller';
72 $msg = errmsg($msg) if @arg;
73 $Tag->error({ name => 'country_select widget', set => $msg});
81 my $stab = $opt->{state_table} || 'state';
83 my $csort = $opt->{country_sort} || ($opt->{no_region} ? 'name' : 'sorder,name');
84 my $ssort = $opt->{state_sort} || 'country,name';
86 my @csort = grep /\w/, split /[\s,\0]+/, $csort;
90 my $so = $a->{$_} cmp $b->{$_};
96 my @ssort = grep /\w/, split /[\s,\0]+/, $ssort;
100 my $so = $a->{$_} cmp $b->{$_};
106 my $cdb = dbref($ctab) or return $die->('country table %s not found', $ctab);
107 my $sdb = dbref($stab) or return $die->('state table %s not found', $stab);
108 $ctab = $cdb->name();
109 $stab = $sdb->name();
110 my $cq = "select * from $ctab";
111 my $sq = "select * from $stab";
112 my $cary = $cdb->query({ sql => $cq, hashref => 1});
113 my $sary = $sdb->query({ sql => $sq, hashref => 1});
115 @csort = grep exists($cary->[0]{$_}), @csort;
116 @ssort = grep exists($sary->[0]{$_}), @ssort;
118 @$cary = sort $csort_sub @$cary;
119 @$sary = sort $ssort_sub @$sary;
121 if($opt->{only_with_shipping}) {
122 @$cary = grep $_->{shipmodes} =~ /\w/, @$cary;
128 my $c = $s->{country};
129 push @{$states{$c} ||= []}, [ $s->{state}, $s->{name} ];
135 my $v_formv = "${pre}formv";
136 my $v_csval = "${pre}csval";
138 my $v_no_state = "${pre}no_state";
139 my $v_state_tary = "${pre}state_tary";
140 my $v_state_vary = "${pre}state_vary";
145 $no_state{$c->{code}} = 1;
147 if(! $opt->{no_region} and $c->{region} and $c->{region} ne $prev) {
148 push @copts, ["~~" . $c->{region} . "~~"];
149 $prev = $c->{region};
151 push @copts, [ $c->{code}, $c->{name} ];
158 var $v_no_state = new Array;
161 for(keys %no_state) {
162 push @pre, "$v_no_state\['$_'] = 1";
166 var $v_state_vary = new Array;
167 var $v_state_tary = new Array;
171 my $sa = $states{$_};
175 @$sa = grep !$seen{$_->[0]}++, @$sa;
181 for(@sv) { s/'/\\'/g; }
182 for(@st) { s/'/\\'/g; }
184 my $string = "$v_state_vary\['$_'] = ['";
185 $string .= join "','", '', @sv;
188 $string = "$v_state_tary\['$_'] = ['";
189 $string .= join "','", errmsg('--select state--'), @st;
194 my $cvar = $opt->{name};
197 my $extra = $opt->{state_extra} ? " $opt->{state_extra}" : '';
198 my $state_js = $opt->{state_js} ? "; $opt->{state_js}" : '';
199 my $country_js = $opt->{country_js} ? "; $opt->{country_js}" : '';
200 for ($state_js, $country_js) { s|\bthis\.form\b|$v_formv|g }
203 function ${cvar}_widget_adjust_state (cel,sval) {
204 var sbox = document.getElementById('$sel');
205 var country = cel.value;
212 if($v_formv.$svar && $v_formv.$svar.value)
213 sval = $v_formv.$svar.value;
218 if($v_no_state\[country]) {
219 sbox.innerHTML = '<span style="$opt->{state_style}">No state required</span>';
220 $v_formv.$svar.value = '';
223 var svary = $v_state_vary\[country];
226 sbox.innerHTML = '<input type="text" size="$size" name="$svar_in" id="$svar_in" value="' + sval + '" onChange="$v_formv.$svar.value = this.value"$extra>';
227 $v_formv.$svar.value=sval;
231 var stary = $v_state_tary\[country];
233 var str = '<select name="$svar_in" id="$svar_in" onChange="$v_formv.$svar.value = this.value$state_js"$extra>';
234 for(var i = 0; i < svary.length; i++) {
235 str += '<option value="' + svary[i] + '"';
242 sbox.innerHTML = str;
249 my $sval = $CGI::values{$svar} || $::Values->{$svar};
250 $sval = HTML::Entities::encode($sval, $ESCAPE_CHARS::std);
251 $sval = $Tag->jsq($sval) || "''";
252 my $fname = $opt->{form_name} || 'nevairbe';
254 my $prepend = join "\n", @pre;
256 if(my $sub = $opt->{callback_prescript}) {
260 $opt->{prepend} = '' unless defined $opt->{prepend};
261 $opt->{prepend} .= "\n" if length $opt->{prepend};
262 $opt->{prepend} .= $prepend;
268 var $v_f = document.$fname;
269 var $v_csval = $sval;
271 for(var i = 0; i < document.forms.length; i++) {
272 $v_f = document.forms[i];
273 if($v_f.$opt->{name}) {
274 if($v_f.$svar && $v_f.$svar.value)
275 $v_csval = $v_f.$svar.value;
276 ${cvar}_widget_adjust_state($v_f.$opt->{name}, $v_csval);
283 csval = $v_formv.$svar.value;
285 ${cvar}_widget_adjust_state($v_formv.$opt->{name}, $v_csval);
290 if(my $sub = $opt->{callback_postscript}) {
294 $opt->{append} = '' unless defined $opt->{append};
295 $opt->{append} .= "\n" if length $opt->{append};
296 $opt->{append} .= $append;
299 $opt->{js} = qq{ onLoad="${cvar}_widget_adjust_state(this)" onChange="${cvar}_widget_adjust_state(this)$country_js"};
302 #push @out, ::uneval(\%states);
303 #push @out, '</xmp>';
305 $opt->{type} = 'select';
306 push @out, Vend::Form::display($opt, {}, \@copts);
308 return join "\n", @out;
312 CodeDef country_select ExtraMeta <<EOM
328 label => 'State variable',
329 help => 'default is <i>state</i>, might use <i>b_state</i> instead',
333 label => 'CSS class for state',
334 help => 'Modify look of state text',
338 label => 'CSS style for state',
339 help => 'Modify look of state text',
343 label => 'Region sort',
344 help => 'Controls country groupings',
345 options => '=Region sort, 1=No region sort',
348 only_with_shipping => {
349 label => 'Only with shipping',
350 help => 'Only show countries that have value in shipmodes',
351 options => '=All countries, 1=Only with shipping',
355 label => 'Country sort order',
356 help => 'Should be "name" if no region sort, "sorder,name" with region',
360 label => 'Country table',
361 help => 'default is usually good (country)',
365 label => 'State sort order',
366 help => 'Default of <i>country,name</i> is usually OK',
370 label => 'State table',
371 help => 'default is usually good (state)',
375 label => 'State element ID',
376 help => 'The CSS ID of the span containing the dynamic widget. The default is usually good (state_widget_container or b_state_widget_container)',
380 label => 'State javascript',
381 help => 'Runs specified javascript under onChange. E.g. "state_js=check_tax(this.form)"',