import rt 3.6.6
[freeside.git] / rt / html / Widgets / SelectionBox
1 %# BEGIN BPS TAGGED BLOCK {{{
2 %# 
3 %# COPYRIGHT:
4 %#  
5 %# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC 
6 %#                                          <jesse@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/copyleft/gpl.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 %# include javascript:
53 %# <& /Widgets/SelectionBox:header &>
54 %#
55 %# <%init>:
56 %# my $sel = $m->comp ('/Widgets/SelectionBox:new',
57 %#                Action => me.html',
58 %#                Name => 'my-selection',
59 %#                Available => \@items,
60 %#                # you can do things with @{$sel->{Current}} in the 
61 %#                # OnSubmit callback
62 %#                OnSubmit => sub { my $sel = shift; },
63 %#                Selected => \@selected);
64 %#
65 %# $m->comp ('/Widgets/SelectionBox:process', %ARGS, self => $sel)
66 %#
67 %# where @items is an arrayref, each element is [value, label],
68 %# and @selected is an arrayref of selected values from @items.
69 %#
70 %# and in html:
71 %# <& /Widgets/SelectionBox:sow, self => $sel &>
72 %#
73 %# if the SelectionBox is created with AutoSave option, OnSubmit will be called
74 %# on every button clicked in non-js mode.
75 <%method header>
76 % unless ($nojs) {
77 <script type="text/javascript" src="<%$RT::WebPath%>/NoAuth/js/class.js"></script>
78 <script type="text/javascript" src="<%$RT::WebPath%>/NoAuth/js/list.js"></script>
79 % }
80 <%ARGS>
81 $nojs => 0
82 </%ARGS>
83 </%method>
84
85 <%method new>
86 <%init>
87 $ARGS{_item_map} = {map {$_->[0] => $_->[1]} @{$ARGS{Available}}};
88 return \%ARGS;
89 </%init>
90 </%method>
91
92 <%method process>
93 <%init>
94 unless ($ARGS{$self->{Name}.'-Submit'}) {
95     # init
96     $self->{Current} = $self->{Selected};
97     $self->{Selected} = [];
98     return;
99 }
100
101 $self->{Selected} = $ARGS{$self->{Name}.'-Selected'};
102 if ($self->{Selected} && !ref($self->{Selected})) {
103     $self->{Selected} = [$self->{Selected}];
104 }
105
106 if ($ARGS{fromjs}) {
107     $self->{Current} = $self->{Selected};
108 }
109 else {
110     my $current = $self->{Current} = $ARGS{$self->{Name}.'-Current'};
111     ++$self->{Modified};
112     if ($current && !ref ($current)) {
113         $current = [$current];
114     }
115
116     if ($ARGS{add}) {
117         my $choosed = $ARGS{$self->{Name}.'-Available'};
118         for my $add (ref($choosed) ? @$choosed : $choosed) {
119             next if grep { $_ eq $add } @$current;
120             push @$current, $add;
121         }
122     }
123
124     if ($ARGS{remove}) {
125         my $choosed = $ARGS{$self->{Name}.'-Selected'};
126         for my $del (ref($choosed) ? @$choosed : $choosed) {
127             @$current = map { $_ eq $del ? () : $_ } @$current;
128         }
129     }
130
131     if ($ARGS{moveup} or $ARGS{movedown}) {
132         my $offset = $ARGS{moveup} ? 1 : 0;
133         my $choosed = $ARGS{$self->{Name}.'-Selected'};
134         $choosed = [$choosed] unless ref ($choosed);
135         my $canmove = 0; # not in the cornor
136         for my $i ($ARGS{moveup} ? 0..$#{$current} : reverse 0..$#{$current}) {
137             if (grep {$_ eq $current->[$i]} @$choosed) {
138                 if ($canmove) {
139                     splice (@$current, $i-$offset, 2,
140                             @{$current}[$i+1-$offset,$i-$offset]);
141                 }
142             }
143             else {
144                 ++$canmove;
145             }
146         }
147     }
148
149     if ($ARGS{clear}) {
150         $current = [];
151     }
152
153     $self->{Current} = $current;
154 }
155
156 @{$self->{Current}} = grep { exists $self->{_item_map}{$_} } @{$self->{Current}};
157
158 if ($self->{AutoSave} or $ARGS{$self->{Name}.'-Save'}) {
159     $self->{OnSubmit}->($self);
160     delete $self->{Modified};
161 }
162
163 </%init>
164 <%ARGS>
165 $self => undef
166 </%ARGS>
167
168 </%method>
169
170 <%method current>
171 % for (@{$self->{Current}}) {
172 <input type="hidden" class="hidden" name="<% $self->{Name} %>-Current" value="<%$_%>" />
173 % }
174 <%INIT>
175 </%INIT>
176 <%ARGS>
177 $self => undef
178 </%ARGS>
179
180 </%method>
181
182 <%method show>
183 <form method="post" action="<%$self->{Action}%>" name="SelectionBox-<% $name %>" id="SelectionBox-<% $name %>"
184 % unless ($nojs) {
185 onsubmit="list_<% $name %>.selectAll();"
186 % }
187 >
188 <input type="hidden" class="hidden" name="<% $self->{Name} %>-Submit" value="1" />
189 <& SelectionBox:current, self => $self &>
190 <input type="hidden" class="hidden" name="fromjs" value="0" />
191 <&|/l&>Available</&>:
192 <br />
193 <select name="<%$name%>-Available" id="<%$name%>-Available" size="<%$size%>" multiple="multiple">
194 % for (@{$self->{Available}}) {
195 <option value="<% $_->[0] %>"><% $_->[1] %></option>
196 % }
197 </select>
198 <input name="add" type="submit" class="button" value=" &rarr; " />
199 <select name="<%$name%>-Selected" id="<%$name%>-Selected" size="<%$size%>" multiple="multiple">
200 % for (@{$self->{Current}}) {
201 <option value="<% $_ %>"
202 % if (exists $selected{$_}) {
203 selected="selected"
204 % }
205 ><% $self->{_item_map}{$_} %></option>
206 % }
207 </select>
208 % unless ($ARGS{'NoArrows'}) {
209  <input name="moveup" type="submit" class="button" value=" &uarr; " />
210  <input name="movedown" type="submit" class="button" value=" &darr; " />
211 % }
212  <input name="remove" type="submit" class="button" value="<&|/l&>Delete</&>" />
213 % if ($ARGS{'Clear'}) {
214  <input name="clear" type="submit" class="button" value="<&|/l&>Clear</&>" />
215 % }
216
217 % my $caption = "";
218 % unless ($self->{'AutoSave'}) {
219 % if ($self->{Modified}) {
220 % $caption = loc('Selections modified. Please save your changes');
221 % }
222 <& /Elements/Submit, Caption => loc($caption), Label => loc('Save'), Name => $name.'-Save' &>
223 % }
224 </form>
225
226 % unless ($nojs) {
227 <script type="text/javascript">
228 //<![CDATA[
229 var list_<%$name%> = new list(document.getElementById("SelectionBox-<% $name %>"), 0, "list_<%$name%>");
230 //]]>
231 </script>
232 % }
233 <%ARGS>
234 $self => undef
235 $size => 10
236 $nojs => 0
237 </%ARGS>
238 <%INIT>
239 my $name = $self->{Name};
240 my %selected = map {$_ => 1} @{$self->{Selected}};
241 </%INIT>
242
243 </%method>