rt 4.2.13 ticket#13852
[freeside.git] / rt / share / html / Widgets / SelectionBox
1 %# BEGIN BPS TAGGED BLOCK {{{
2 %#
3 %# COPYRIGHT:
4 %#
5 %# This software is Copyright (c) 1996-2016 Best Practical Solutions, LLC
6 %#                                          <sales@bestpractical.com>
7 %#
8 %# (Except where explicitly superseded by other copyright notices)
9 %#
10 %#
11 %# LICENSE:
12 %#
13 %# This work is made available to you under the terms of Version 2 of
14 %# the GNU General Public License. A copy of that license should have
15 %# been provided with this software, but in any event can be snarfed
16 %# from www.gnu.org.
17 %#
18 %# This work is distributed in the hope that it will be useful, but
19 %# WITHOUT ANY WARRANTY; without even the implied warranty of
20 %# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21 %# General Public License for more details.
22 %#
23 %# You should have received a copy of the GNU General Public License
24 %# along with this program; if not, write to the Free Software
25 %# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 %# 02110-1301 or visit their web page on the internet at
27 %# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
28 %#
29 %#
30 %# CONTRIBUTION SUBMISSION POLICY:
31 %#
32 %# (The following paragraph is not intended to limit the rights granted
33 %# to you to modify and distribute this software under the terms of
34 %# the GNU General Public License and is only of importance to you if
35 %# you choose to contribute your changes and enhancements to the
36 %# community by submitting them to Best Practical Solutions, LLC.)
37 %#
38 %# By intentionally submitting any modifications, corrections or
39 %# derivatives to this work, or any other work intended for use with
40 %# Request Tracker, to Best Practical Solutions, LLC, you confirm that
41 %# you are the copyright holder for those contributions and you grant
42 %# Best Practical Solutions,  LLC a nonexclusive, worldwide, irrevocable,
43 %# royalty-free, perpetual, license to use, copy, create derivative
44 %# works based on those contributions, and sublicense and distribute
45 %# those contributions and any derivatives thereof.
46 %#
47 %# END BPS TAGGED BLOCK }}}
48 %# The SelectionBox Widget
49 %# 
50 %# SYNOPSIS
51 %#
52 %# <%init>:
53 %# my $sel = $m->comp ('/Widgets/SelectionBox:new',
54 %#                Action => me.html',
55 %#                Name => 'my-selection',
56 %#                Available => \@items,
57 %#                # you can do things with @{$sel->{Current}} in the 
58 %#                # OnSubmit callback
59 %#                OnSubmit => sub { my $sel = shift; },
60 %#                Selected => \@selected);
61 %#
62 %# $m->comp ('/Widgets/SelectionBox:process', %ARGS, self => $sel)
63 %#
64 %# where @items is an arrayref, each element is [value, label],
65 %# and @selected is an arrayref of selected values from @items.
66 %#
67 %# and in html:
68 %# <& /Widgets/SelectionBox:show, self => $sel &>
69 %#
70 %# if the SelectionBox is created with AutoSave option, OnSubmit will be called
71 %# on every button clicked
72 <%method new>
73 <%init>
74 $ARGS{_item_map} = {map {$_->[0] => $_->[1]} @{$ARGS{Available}}};
75 return \%ARGS;
76 </%init>
77 </%method>
78
79 <%method process>
80 <%init>
81 unless ($ARGS{$self->{Name}.'-Submit'}) {
82     # init
83     $self->{Current} = $self->{Selected};
84     $self->{Selected} = [];
85     return;
86 }
87
88 $self->{Selected} = $ARGS{$self->{Name}.'-Selected'};
89 if ($self->{Selected} && !ref($self->{Selected})) {
90     $self->{Selected} = [$self->{Selected}];
91 }
92
93 my $current = $self->{Current} = $ARGS{$self->{Name}.'-Current'};
94 if ($current && !ref ($current)) {
95     $current = [$current];
96 }
97
98 unless ($self->{ReadOnly}) {
99     ++$self->{Modified};
100     if ($ARGS{add}) {
101         my $choosed = $ARGS{$self->{Name}.'-Available'};
102         for my $add (ref($choosed) ? @$choosed : $choosed) {
103             next if grep { $_ eq $add } @$current;
104             push @$current, $add;
105         }
106     }
107
108     if ($ARGS{remove}) {
109         my $choosed = $ARGS{$self->{Name}.'-Selected'};
110         for my $del (ref($choosed) ? @$choosed : $choosed) {
111             @$current = map { $_ eq $del ? () : $_ } @$current;
112         }
113     }
114
115     if ($ARGS{moveup} or $ARGS{movedown}) {
116         my $offset = $ARGS{moveup} ? 1 : 0;
117         my $choosed = $ARGS{$self->{Name}.'-Selected'};
118         $choosed = [$choosed] unless ref ($choosed);
119         my $canmove = 0; # not in the cornor
120         for my $i ($ARGS{moveup} ? 0..$#{$current} : reverse 0..$#{$current}) {
121             if (grep {$_ eq $current->[$i]} @$choosed) {
122             if ($canmove) {
123                 splice (@$current, $i-$offset, 2,
124                     @{$current}[$i+1-$offset,$i-$offset]);
125             }
126             }
127             else {
128             ++$canmove;
129             }
130         }
131     }
132
133     if ($ARGS{clear}) {
134         $current = [];
135     }
136
137     $self->{Current} = $current;
138 }
139
140 @{$self->{Current}} = grep { exists $self->{_item_map}{$_} } @{$self->{Current}};
141
142 if ($self->{AutoSave} or $ARGS{$self->{Name}.'-Save'}) {
143     $self->{OnSubmit}->($self);
144     delete $self->{Modified};
145 }
146
147 </%init>
148 <%ARGS>
149 $self => undef
150 </%ARGS>
151
152 </%method>
153
154 <%method current>
155 % for (@{$self->{Current}}) {
156 <input type="hidden" class="hidden" name="<% $self->{Name} %>-Current" value="<%$_%>" />
157 % }
158 <%INIT>
159 </%INIT>
160 <%ARGS>
161 $self => undef
162 </%ARGS>
163
164 </%method>
165
166 <%method show>
167 <form method="post" action="<%$self->{Action}%>" name="SelectionBox-<% $name %>" id="SelectionBox-<% $name %>">
168 <input type="hidden" class="hidden" name="<% $self->{Name} %>-Submit" value="1" />
169 <& SelectionBox:current, self => $self &>
170 <&|/l&>Available</&>:
171 <br />
172 <select name="<%$name%>-Available" id="<%$name%>-Available" size="<%$size%>" multiple="multiple" class="selection-box">
173 % for (@{$self->{Available}}) {
174 <option value="<% $_->[0] %>"><% $_->[1] %></option>
175 % }
176 </select>
177
178 % unless ($self->{ReadOnly}) {
179 <input aria-label="Add" name="add" type="submit" class="button" value=" &rarr; " />
180 % }
181
182 <select name="<%$name%>-Selected" id="<%$name%>-Selected" size="<%$size%>" multiple="multiple" class="selection-box">
183 % for (@{$self->{Current}}) {
184 <option value="<% $_ %>"
185 % if (exists $selected{$_}) {
186 selected="selected"
187 % }
188 ><% $self->{_item_map}{$_} ||'' %></option>
189 % }
190 </select>
191 % unless ($self->{'ReadOnly'}) {
192 % unless ($ARGS{'NoArrows'}) {
193  <input aria-label="Move up" name="moveup" type="submit" class="button" value=" &uarr; " />
194  <input aria-label="Move down" name="movedown" type="submit" class="button" value=" &darr; " />
195 % }
196  <input name="remove" type="submit" class="button" value="<&|/l&>Delete</&>" />
197 % if ($ARGS{'Clear'}) {
198  <input name="clear" type="submit" class="button" value="<&|/l&>Clear</&>" />
199 % }
200 % if ( $ARGS{'ShowUpdate'} ) {
201  <input name="update" type="submit" class="button" value="<&|/l&>Update</&>" />
202 % }
203 % }
204
205 % my $caption = "";
206 % unless ($self->{'AutoSave'}) {
207 % if ($self->{Modified}) {
208 % $caption = loc('Selections modified. Please save your changes');
209 % }
210 <& /Elements/Submit, Caption => loc($caption), Label => loc('Save'), Name => $name.'-Save' &>
211 % }
212 </form>
213
214 <%ARGS>
215 $self => undef
216 $size => 10
217 </%ARGS>
218 <%INIT>
219 my $name = $self->{Name};
220 my %selected = map {$_ => 1} @{$self->{Selected}};
221 </%INIT>
222
223 </%method>