1# See bottom of file for license and copyright information
2package Foswiki::Form::Select;
3use strict;
4use warnings;
5
6use Foswiki::Form::ListFieldDefinition ();
7our @ISA = ('Foswiki::Form::ListFieldDefinition');
8
9use Assert;
10
11BEGIN {
12    if ( $Foswiki::cfg{UseLocale} ) {
13        require locale;
14        import locale();
15    }
16}
17
18sub new {
19    my $class = shift;
20    my $this  = $class->SUPER::new(@_);
21
22    # Parse the size to get min and max
23    $this->{size} ||= 1;
24    if ( $this->{size} =~ m/^\s*(\d+)\.\.(\d+)\s*$/ ) {
25        $this->{minSize} = $1;
26        $this->{maxSize} = $2;
27    }
28    else {
29        $this->{minSize} = $this->{size};
30        $this->{minSize} =~ s/[^\d]//g;
31        $this->{minSize} ||= 1;
32        $this->{maxSize} = $this->{minSize};
33    }
34
35    #must list every valid combination.
36    $this->{validModifiers} = [ '+multi', '+values', '+multi+values' ];
37
38    return $this;
39}
40
41=begin TML
42
43---++ getDefaultValue() -> $value
44The default for a select is always the empty string, as there is no way in
45Foswiki form definitions to indicate selected values. This defers the decision
46on a value to the browser.
47
48=cut
49
50sub getDefaultValue {
51    my $this = shift;
52    return ( exists( $this->{default} ) ? $this->{default} : '' );
53}
54
55=begin TML
56
57---++ ObjectMethod finish()
58Break circular references.
59
60=cut
61
62# Note to developers; please undef *all* fields in the object explicitly,
63# whether they are references or not. That way this method is "golden
64# documentation" of the live fields in the object.
65sub finish {
66    my $this = shift;
67    $this->SUPER::finish();
68    undef $this->{minSize};
69    undef $this->{maxSize};
70    undef $this->{valueMap};
71
72    return;
73}
74
75sub getDisplayValue {
76    my ( $this, $value ) = @_;
77
78    return $value unless $this->isValueMapped();
79
80    $this->getOptions();
81
82    my @vals = ();
83    foreach my $val ( split( /\s*,\s*/, $value ) ) {
84        if ( defined( $this->{valueMap}{$val} ) ) {
85            push @vals, $this->{valueMap}{$val};
86        }
87        else {
88            push @vals, $val;
89        }
90    }
91    return join( ", ", @vals );
92}
93
94sub renderForEdit {
95    my ( $this, $topicObject, $value ) = @_;
96
97    my $choices = '';
98
99    $value = '' unless defined $value;
100    my %isSelected;
101    if ( $this->isMultiValued() ) {
102        %isSelected = map { $_ => 1 } split( /\s*,\s*/, $value );
103    }
104    else {
105        $isSelected{$value} = 1;
106    }
107    foreach my $item ( @{ $this->getOptions() } ) {
108        my $option = $item
109          ; # Item9647: make a copy not to modify the original value in the array
110        my %params = ( class => 'foswikiOption', );
111        $params{selected} = 'selected' if $isSelected{$option};
112        if ( $this->{_descriptions}{$option} ) {
113            $params{title} = $this->{_descriptions}{$option};
114        }
115        if ( defined( $this->{valueMap}{$option} ) ) {
116            $params{value} = $option;
117            $option = $this->{valueMap}{$option};
118        }
119        $option =~ s/<nop/&lt\;nop/g;
120        $choices .= CGI::option( \%params, $option );
121    }
122    my $size = scalar( @{ $this->getOptions() } );
123    if ( $size > $this->{maxSize} ) {
124        $size = $this->{maxSize};
125    }
126    elsif ( $size < $this->{minSize} ) {
127        $size = $this->{minSize};
128    }
129    my $params = {
130        class => $this->cssClasses('foswikiSelect'),
131        name  => $this->{name},
132        size  => $this->{size},
133    };
134    if ( $this->isMultiValued() ) {
135        $params->{'multiple'} = 'multiple';
136        $value = CGI::Select( $params, $choices );
137
138        # Item2410: We need a dummy control to detect the case where
139        #           all checkboxes have been deliberately unchecked
140        # Item3061:
141        # Don't use CGI, it will insert the value from the query
142        # once again and we need an empt field here.
143        $value .=
144          '<input type="hidden" name="' . $this->{name} . '" value="" />';
145    }
146    else {
147        $value = CGI::Select( $params, $choices );
148    }
149    return ( '', $value );
150}
151
1521;
153__END__
154Foswiki - The Free and Open Source Wiki, http://foswiki.org/
155
156Copyright (C) 2008-2010 Foswiki Contributors. Foswiki Contributors
157are listed in the AUTHORS file in the root of this distribution.
158NOTE: Please extend that file, not this notice.
159
160Additional copyrights apply to some or all of the code in this
161file as follows:
162
163Copyright (C) 2001-2007 TWiki Contributors. All Rights Reserved.
164TWiki Contributors are listed in the AUTHORS file in the root
165of this distribution. NOTE: Please extend that file, not this notice.
166
167This program is free software; you can redistribute it and/or
168modify it under the terms of the GNU General Public License
169as published by the Free Software Foundation; either version 2
170of the License, or (at your option) any later version. For
171more details read LICENSE in the root of this distribution.
172
173This program is distributed in the hope that it will be useful,
174but WITHOUT ANY WARRANTY; without even the implied warranty of
175MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
176
177As per the GPL, removal of this notice is prohibited.
178